diff --git a/ChangeLog b/ChangeLog index ee094908..e4680c18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,9 @@ iRedMail-1.2: - OpenBSD 6.5. Please use the latest stable release 6.6 instead. * Improvements: + + Able to store banned IP addresses in SQL db. + iRedAdmin-Pro customers can view banned addresses and unban them on + web UI directly. + Fail2ban now works on OpenBSD. + Track last login of both POP3/IMAP logins, also when new (last one) email was delivered via LMTP/LDA. diff --git a/conf/fail2ban b/conf/fail2ban index 4731062c..d128078a 100644 --- a/conf/fail2ban +++ b/conf/fail2ban @@ -60,3 +60,7 @@ elif [ X"${KERNEL_NAME}" == X'FREEBSD' ]; then elif [ X"${KERNEL_NAME}" == X'OPENBSD' ]; then export FAIL2BAN_ACTION='pf' fi + +# SQL db. +export FAIL2BAN_DB_NAME='fail2ban' +export FAIL2BAN_DB_USER='fail2ban' diff --git a/conf/postgresql b/conf/postgresql index 28504a6f..1458d74c 100644 --- a/conf/postgresql +++ b/conf/postgresql @@ -27,8 +27,6 @@ export SYS_USER_PGSQL='postgres' export SYS_GROUP_PGSQL='postgres' -export PGSQL_USER_HOMEDIR='/var/lib/postgresql' - export PGSQL_RC_SCRIPT_NAME='postgresql' export PGSQL_INIT_SQL_SAMPLE="${RUNTIME_DIR}/pgsql_init.pgsql" @@ -52,6 +50,7 @@ elif [ X"${DISTRO}" == X'DEBIAN' -o X"${DISTRO}" == X'UBUNTU' ]; then export PGSQL_VERSION='11' fi + export PGSQL_USER_HOMEDIR='/var/lib/postgresql' export PGSQL_DATA_DIR="/var/lib/postgresql/${PGSQL_VERSION}/main" export PGSQL_CONF_DIR="/etc/postgresql/${PGSQL_VERSION}/main" export PGSQL_CONF_POSTGRESQL="${PGSQL_CONF_DIR}/postgresql.conf" diff --git a/dialog/optional_components.sh b/dialog/optional_components.sh index 803059d7..d331b22d 100644 --- a/dialog/optional_components.sh +++ b/dialog/optional_components.sh @@ -116,3 +116,7 @@ echo "export SOGO_SIEVE_MASTER_PASSWD='${SOGO_SIEVE_MASTER_PASSWD}'" >> ${IREDMA export random_pw="$(${RANDOM_STRING})" export IREDAPD_DB_PASSWD="${IREDAPD_DB_PASSWD:=${random_pw}}" echo "export IREDAPD_DB_PASSWD='${IREDAPD_DB_PASSWD}'" >> ${IREDMAIL_CONFIG_FILE} + +export random_pw="$(${RANDOM_STRING})" +export FAIL2BAN_DB_PASSWD="${FAIL2BAN_DB_PASSWD:=${random_pw}}" +echo "export FAIL2BAN_DB_PASSWD='${FAIL2BAN_DB_PASSWD}'" >> ${IREDMAIL_CONFIG_FILE} diff --git a/functions/amavisd.sh b/functions/amavisd.sh index 6e8c24e7..ed05ca74 100644 --- a/functions/amavisd.sh +++ b/functions/amavisd.sh @@ -26,7 +26,7 @@ amavisd_initialize_db() { - ECHO_DEBUG "Import Amavisd database and privileges." + ECHO_DEBUG "Import Amavisd database and grant privileges." if [ X"${BACKEND}" == X'OPENLDAP' -o X"${BACKEND}" == X'MYSQL' ]; then ${MYSQL_CLIENT_ROOT} <> ${INSTALL_LOG} 2>&1 chmod 0777 ${PGSQL_USER_HOMEDIR}/amavisd.sql >/dev/null - su - ${SYS_USER_PGSQL} -c "psql -d template1" >> ${INSTALL_LOG} <> ${INSTALL_LOG} 2>&1 <. #--------------------------------------------------------------------- +_enable_jail() { + _jail_conf="${FAIL2BAN_JAIL_CONF_DIR}/${1}" -fail2ban_config() -{ - ECHO_INFO "Configure Fail2ban (authentication failure monitor)." + if [ -e ${_jail_conf} ]; then + perl -pi -e 's#(enabled.*=.*)false#${1}true#' ${_jail_conf} + fi +} +fail2ban_initialize_db() { + ECHO_DEBUG "Import Fail2ban database and grant privileges." + + if [ X"${BACKEND}" == X'OPENLDAP' -o X"${BACKEND}" == X'MYSQL' ]; then + ${MYSQL_CLIENT_ROOT} < /root/.my.cnf-${FAIL2BAN_DB_USER} <> ${INSTALL_LOG} <> ${INSTALL_LOG} <> ${INSTALL_LOG} 2>&1 <> ${STATUS_FILE} +} + +fail2ban_config() { ECHO_DEBUG "Disable all default filters in ${FAIL2BAN_JAIL_CONF}." perl -pi -e 's#^(enabled).*=.*#${1} = false#' ${FAIL2BAN_JAIL_CONF} @@ -66,18 +130,19 @@ fail2ban_config() ECHO_DEBUG "Copy sample Fail2ban filter config files." cp -f ${SAMPLE_DIR}/fail2ban/filter.d/*.conf ${FAIL2BAN_FILTER_DIR} - # Enable Nginx - if [ X"${WEB_SERVER}" == X'NGINX' ]; then - perl -pi -e 's#(enabled.*=.*)false#${1}true#' ${FAIL2BAN_JAIL_CONF_DIR}/nginx-http-auth.local - fi + # Enable jail for optional components. + [ X"${WEB_SERVER}" == X'NGINX' ] && _enable_jail nginx-http-auth.local + [ X"${USE_ROUNDCUBE}" == X'YES' ] && _enable_jail roundcube.local + [ X"${USE_SOGO}" == X'YES' ] && _enable_jail sogo.local - if [ X"${USE_ROUNDCUBE}" == X'YES' ]; then - perl -pi -e 's#(enabled.*=.*)false#${1}true#' ${FAIL2BAN_JAIL_CONF_DIR}/roundcube.local - fi - - if [ X"${USE_SOGO}" == X'YES' ]; then - perl -pi -e 's#(enabled.*=.*)false#${1}true#' ${FAIL2BAN_JAIL_CONF_DIR}/sogo.local - fi + [ X"${DISTRO}" == X'OPENBSD' ] && service_control enable fail2ban >> ${INSTALL_LOG} 2>&1 echo 'export status_fail2ban_config="DONE"' >> ${STATUS_FILE} } + +fail2ban_setup() { + ECHO_INFO "Configure Fail2ban (authentication failure monitor)." + + check_status_before_run fail2ban_initialize_db + check_status_before_run fail2ban_config +} diff --git a/functions/netdata.sh b/functions/netdata.sh index 494bec2a..bf46d150 100644 --- a/functions/netdata.sh +++ b/functions/netdata.sh @@ -44,7 +44,7 @@ netdata_install() netdata_config() { - ECHO_INFO "Configure netdata." + ECHO_INFO "Configure netdata (system and application monitor)." # Disable sending anonymouse statistics to netdata cloud. touch ${NETDATA_CONF_DIR}/.opt-out-from-anonymous-statistics diff --git a/functions/optional_components.sh b/functions/optional_components.sh index 64116675..fdb840f3 100644 --- a/functions/optional_components.sh +++ b/functions/optional_components.sh @@ -11,18 +11,22 @@ optional_components() check_status_before_run iredapd_setup # iRedAdmin. - [ X"${USE_IREDADMIN}" == X'YES' ] && check_status_before_run iredadmin_setup + [ X"${USE_IREDADMIN}" == X'YES' ] && \ + check_status_before_run iredadmin_setup # Roundcubemail. - [ X"${USE_ROUNDCUBE}" == X'YES' ] && check_status_before_run rcm_setup + [ X"${USE_ROUNDCUBE}" == X'YES' ] && \ + check_status_before_run rcm_setup # SOGo - [ X"${USE_SOGO}" == X'YES' ] && check_status_before_run sogo_setup - - # netdata. - [ X"${USE_NETDATA}" == X'YES' ] && check_status_before_run netdata_setup + [ X"${USE_SOGO}" == X'YES' ] && \ + check_status_before_run sogo_setup # Fail2ban. [ X"${USE_FAIL2BAN}" == X'YES' -a X"${DISTRO}" != X'FREEBSD' ] && \ - check_status_before_run fail2ban_config + check_status_before_run fail2ban_setup + + # netdata. + [ X"${USE_NETDATA}" == X'YES' ] && \ + check_status_before_run netdata_setup } diff --git a/functions/packages.sh b/functions/packages.sh index a26a3ec1..5bcdcb8c 100644 --- a/functions/packages.sh +++ b/functions/packages.sh @@ -436,20 +436,21 @@ EOF ALL_PKGS="${ALL_PKGS} py-pip py-jinja2 py-webpy py-flup py-bcrypt py-curl py-requests py-netifaces" fi - # Fail2ban + # Fail2ban. Install fail2ban and geoip. if [ X"${USE_FAIL2BAN}" == X'YES' ]; then ENABLED_SERVICES="${ENABLED_SERVICES} fail2ban" - if [ X"${DISTRO}" == X'OPENBSD' ]; then + if [ X"${DISTRO}" == X'RHEL' ]; then + [[ X"${DISTRO_VERSION}" == X'7' ]] && ALL_PKGS="${ALL_PKGS} fail2ban GeoIP GeoIP-data" + [[ X"${DISTRO_VERSION}" == X'8' ]] && ALL_PKGS="${ALL_PKGS} fail2ban GeoIP GeoIP-GeoLite-data" + + DISABLED_SERVICES="${DISABLED_SERVICES} shorewall gamin gamin-python" + elif [ X"${DISTRO}" == X'DEBIAN' -o X"${DISTRO}" == X'UBUNTU' ]; then + ALL_PKGS="${ALL_PKGS} fail2ban geoip-bin geoip-database" + elif [ X"${DISTRO}" == X'OPENBSD' ]; then # No port for fail2ban. Install from source tarball with pip later. # rc script will be generated from sample file later. - ALL_PKGS="${ALL_PKGS} py-pip py3-pip" - else - ALL_PKGS="${ALL_PKGS} fail2ban" - - if [ X"${DISTRO}" == X'RHEL' ]; then - DISABLED_SERVICES="${DISABLED_SERVICES} shorewall gamin gamin-python" - fi + ALL_PKGS="${ALL_PKGS} py-pip py3-pip GeoIP geolite-country" fi fi diff --git a/functions/postgresql.sh b/functions/postgresql.sh index 6a3407b3..94b68de2 100644 --- a/functions/postgresql.sh +++ b/functions/postgresql.sh @@ -113,6 +113,7 @@ EOF *:*:*:${SOGO_DB_USER}:${SOGO_DB_PASSWD} *:*:*:${RCM_DB_USER}:${RCM_DB_PASSWD} *:*:*:${AMAVISD_DB_USER}:${AMAVISD_DB_PASSWD} +*:*:*:${FAIL2BAN_DB_USER}:${FAIL2BAN_DB_PASSWD} EOF chown ${SYS_USER_PGSQL}:${SYS_GROUP_PGSQL} ${PGSQL_DOT_PGPASS} diff --git a/samples/fail2ban/action.d/banned_db.conf b/samples/fail2ban/action.d/banned_db.conf new file mode 100644 index 00000000..3500b4f7 --- /dev/null +++ b/samples/fail2ban/action.d/banned_db.conf @@ -0,0 +1,13 @@ +# - Store banned IP in SQL db while it's banned. +# - Remove banned IP from SQL db while it's unbanned. + +[Definition] +actionstart = +actioncheck = + +actionban = /usr/local/bin/fail2ban_banned_db ban +actionunban = /usr/local/bin/fail2ban_banned_db unban + +# Each time Fail2ban is stopped or restarted, `actionstop` will be executed, +# so the SQL table will be empty each time it stopped or restarted. +actionstop = /usr/local/bin/fail2ban_banned_db cleanup diff --git a/samples/fail2ban/bin/fail2ban_banned_db b/samples/fail2ban/bin/fail2ban_banned_db new file mode 100644 index 00000000..d395c092 --- /dev/null +++ b/samples/fail2ban/bin/fail2ban_banned_db @@ -0,0 +1,199 @@ +#!/usr/bin/env bash +# Author: Zhang Huangbin +# Puprpose: +# - Store banned IP address in SQL db while it's banned. +# - Remove unbanned IP address from SQL db while it's unbanned. +# - Unban IP addresses which have column `remove=1`. + +# Usage: +# +# *) Store a banned IP address: +# +# banned_db ban +# +# - : One IP address each time. +# - : Network ports. Multiple ports must be separated by comma. +# - : `tcp` or `udp`. +# - : Fail2ban jail name. +# +# *) Remove an one or multiple unbanned IP addresses. Notes: +# +# - it removes IP from all jails. +# - multiple IP addresses must be separated by space. +# +# banned_db unban [ip] [ip] +# +# *) Cleanup a jail. When Fail2ban is stopping or restarting, `cleanup` will +# be executed. Cleanup manually is supported too: +# +# banned_db cleanup +# +# *) Query SQL db and remove IP addresses which have `remove=1`. +# +# banned_db unban_db +# +# Examples: +# +# banned_db ban 192.168.0.1 110,143,993,995 tcp dovecot-iredmail +# banned_db unban 192.168.0.1 +# banned_db cleanup dovecot-iredmail +# banned_db unban_db + +# +# Sample Fail2ban jail config file (/etc/fail2ban/jail.d/xx.local): +# +# [jail-name] +# ... +# action = ...[your other actions here]... +# banned_db[name=jail-name, port="80", protocol=tcp] +# +# WARNING: the name set in `banned_db[name=]` must be same as the jail name. + +export DB_NAME="fail2ban" +export DB_TABLE="banned" +export DB_USER="fail2ban" + +# GeoIP +export CMD_GEOIPLOOKUP="$(which geoiplookup)" +export CMD_GEOIPLOOKUP6="$(which geoiplookup6)" + +if [ -f /root/.my.cnf-fail2ban ]; then + export CMD_SQL="mysql --defaults-file=/root/.my.cnf-fail2ban ${DB_NAME}" + export DB_TYPE="mysql" +elif [ -f /root/.my.cnf ]; then + export CMD_SQL="mysql --defaults-file=/root/.my.cnf ${DB_NAME}" + export DB_TYPE="mysql" +else + # Absolute path to ~/.pgpass + # - RHEL: /var/lib/pgsql/.pgpass + # - Debian/Ubuntu: /var/lib/postgresql/.pgpass + # - FreeBSD: /var/db/postgres/.pgpass + # - OpenBSD: /var/postgresql/.pgpass + for dir in \ + /var/lib/pgsql \ + /var/lib/postgresql \ + /var/db/postgres \ + /var/postgresql; do + if [ -f ${dir}/.pgpass ]; then + export PGPASSFILE="${dir}/.pgpass" + export CMD_SQL="psql -U ${DB_USER} -d ${DB_NAME}" + export DB_TYPE="pgsql" + fi + done +fi + +if [ X"${CMD_SQL}" == X'' ]; then + echo "No MySQL or PostgreSQL related config file found. Abort." + echo " - MySQL: /root/.my.cnf-fail2ban (or /root/.my.cnf)" + echo " - PostgreSQL: ~/.pgpass (under PostgreSQL daemon user's home directory)" + exit 255 +fi + +export _action="$1" + +if [[ X"${_action}" == X"ban" ]]; then + _ip="${2}" + _ports="${3}" + _protocol="${4}" + _jail="${5}" + + if [[ X"${_ip}" == X'' ]] || \ + [[ X"${_ports}" == X'' ]] || \ + [[ X"${_protocol}" == X'' ]] || \ + [[ X"${_jail}" == X'' ]]; then + echo "IP, ports, protocol, or jail name is empty. Abort." + exit 255 + fi + + _hostname="$(hostname)" + + # Lookup for country name. + _country='' + if echo ${_ip} | grep ':' &>/dev/null; then + if [[ -x ${CMD_GEOIPLOOKUP6} ]]; then + _country="$(${CMD_GEOIPLOOKUP6} ${_ip} | grep '^GeoIP Country Edition:' | awk -F': ' '{print $2}')" + fi + else + if [[ -x ${CMD_GEOIPLOOKUP} ]]; then + _country="$(${CMD_GEOIPLOOKUP} ${_ip} | grep '^GeoIP Country Edition:' | awk -F': ' '{print $2}')" + fi + fi + + if [ X"${DB_TYPE}" == X'mysql' ]; then + ${CMD_SQL} </dev/null + + if [[ X"$?" == X'0' ]]; then + echo "Already banned." + else + ${CMD_SQL} >/dev/null <> ${tmp_file} + + while read jail ip; do + # Avoid SQL injection: don't allow whitespace, ';', quotes in + # jail name and IP address. + if echo ${jail} | grep "[ ;\"\']" &>/dev/null; then + echo "[WARNING] Invalid jail name: '${jail}'." + continue + fi + + if echo ${ip} | grep "[ ;\"\']" &>/dev/null; then + echo "[WARNING] Invalid IP address: '${ip}'." + continue + fi + + # fail2ban-client returns number of processed rows on command line, + # let's discard it to avoid noise/confusion. + fail2ban-client set ${jail} unbanip ${ip} >/dev/null + [[ X"$?" == X'0' ]] && echo "Unbanned ${ip} from jail [${jail}]." + done < ${tmp_file} + rm -f ${tmp_file} &>/dev/null +fi diff --git a/samples/fail2ban/jail.d/dovecot.local b/samples/fail2ban/jail.d/dovecot.local index ecccfd9a..84526ef4 100644 --- a/samples/fail2ban/jail.d/dovecot.local +++ b/samples/fail2ban/jail.d/dovecot.local @@ -1,5 +1,6 @@ [dovecot-iredmail] enabled = true filter = dovecot.iredmail -action = PH_FAIL2BAN_ACTION[name=dovecot, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] logpath = PH_DOVECOT_LOG_FILE +action = PH_FAIL2BAN_ACTION[name=dovecot, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] + banned_db[name=dovecot, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] diff --git a/samples/fail2ban/jail.d/nginx-http-auth.local b/samples/fail2ban/jail.d/nginx-http-auth.local index 7fd9978f..7fcbe5eb 100644 --- a/samples/fail2ban/jail.d/nginx-http-auth.local +++ b/samples/fail2ban/jail.d/nginx-http-auth.local @@ -1,5 +1,6 @@ [nginx-http-auth] enabled = false filter = nginx-http-auth -action = PH_FAIL2BAN_ACTION[name=nginx, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] logpath = PH_NGINX_LOG_ERRORLOG +action = PH_FAIL2BAN_ACTION[name=nginx, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] + banned_db[name=nginx, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] diff --git a/samples/fail2ban/jail.d/postfix-pregreet.local b/samples/fail2ban/jail.d/postfix-pregreet.local index 94379d4b..f81f6330 100644 --- a/samples/fail2ban/jail.d/postfix-pregreet.local +++ b/samples/fail2ban/jail.d/postfix-pregreet.local @@ -1,6 +1,7 @@ [postfix-pregreet-iredmail] enabled = true +maxretry = 1 filter = postfix-pregreet.iredmail logpath = PH_MAILLOG -maxretry = 1 action = PH_FAIL2BAN_ACTION[name=postfix, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] + banned_db[name=postfix, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] diff --git a/samples/fail2ban/jail.d/postfix.local b/samples/fail2ban/jail.d/postfix.local index 957c8a71..3a54bfab 100644 --- a/samples/fail2ban/jail.d/postfix.local +++ b/samples/fail2ban/jail.d/postfix.local @@ -1,5 +1,6 @@ [postfix-iredmail] enabled = true filter = postfix.iredmail -action = PH_FAIL2BAN_ACTION[name=postfix, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] logpath = PH_MAILLOG +action = PH_FAIL2BAN_ACTION[name=postfix, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] + banned_db[name=postfix, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] diff --git a/samples/fail2ban/jail.d/roundcube.local b/samples/fail2ban/jail.d/roundcube.local index f28d73c4..2f4547ac 100644 --- a/samples/fail2ban/jail.d/roundcube.local +++ b/samples/fail2ban/jail.d/roundcube.local @@ -1,6 +1,7 @@ [roundcube-iredmail] enabled = false -filter = roundcube.iredmail -action = PH_FAIL2BAN_ACTION[name=roundcube, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] -logpath = PH_RCM_LOGFILE findtime = 3600 +filter = roundcube.iredmail +logpath = PH_RCM_LOGFILE +action = PH_FAIL2BAN_ACTION[name=roundcube, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] + banned_db[name=roundcube, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] diff --git a/samples/fail2ban/jail.d/sogo.local b/samples/fail2ban/jail.d/sogo.local index 35df7dc0..35937236 100644 --- a/samples/fail2ban/jail.d/sogo.local +++ b/samples/fail2ban/jail.d/sogo.local @@ -1,5 +1,6 @@ [sogo-iredmail] enabled = false filter = sogo-auth -action = PH_FAIL2BAN_ACTION[name=sogo, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] logpath = PH_SOGO_LOG_FILE +action = PH_FAIL2BAN_ACTION[name=sogo, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] + banned_db[name=sogo, port="PH_FAIL2BAN_DISABLED_SERVICES", protocol=tcp] diff --git a/samples/fail2ban/jail.d/sshd.local b/samples/fail2ban/jail.d/sshd.local index 124e0654..ce5e776b 100644 --- a/samples/fail2ban/jail.d/sshd.local +++ b/samples/fail2ban/jail.d/sshd.local @@ -1,5 +1,6 @@ [sshd] enabled = true filter = sshd -action = PH_FAIL2BAN_ACTION[name=sshd, port="PH_SSHD_PORT", protocol=tcp] logpath = PH_SSHD_LOGFILE +action = PH_FAIL2BAN_ACTION[name=sshd, port="PH_SSHD_PORT", protocol=tcp] + banned_db[name=sshd, port="PH_SSHD_PORT", protocol=tcp] diff --git a/samples/fail2ban/sql/fail2ban.mysql b/samples/fail2ban/sql/fail2ban.mysql new file mode 100644 index 00000000..958270b8 --- /dev/null +++ b/samples/fail2ban/sql/fail2ban.mysql @@ -0,0 +1,28 @@ +-- +-- Used to store banned/unbanned clients +-- +CREATE TABLE IF NOT EXISTS `banned` ( + `id` BIGINT(20) UNSIGNED AUTO_INCREMENT, + -- Banned client IP address + `ip` VARCHAR(46) NOT NULL DEFAULT '', + -- A list of banned network ports, separated by comma + `ports` VARCHAR(50) NOT NULL DEFAULT '', + -- protocol: tcp, udp, ... + `protocol` VARCHAR(10) NOT NULL DEFAULT 'tcp', + -- Fail2ban jail name + `jail` VARCHAR(30) NOT NULL DEFAULT 'INPUT', + -- The server hostname which the ban/unban happens + `hostname` VARCHAR(255) NOT NULL DEFAULT '', + `country` VARCHAR(255) NOT NULL DEFAULT '', + -- When the ban happens + `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + -- if `remove=1`, `ip` will be removed by cron job. + `remove` TINYINT(1) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE INDEX (`ip`, `ports`, `protocol`), + INDEX (`hostname`), + INDEX (`jail`), + INDEX (`country`), + INDEX (`timestamp`), + INDEX (`remove`) +) ENGINE=InnoDB; diff --git a/samples/fail2ban/sql/fail2ban.pgsql b/samples/fail2ban/sql/fail2ban.pgsql new file mode 100644 index 00000000..b85169c9 --- /dev/null +++ b/samples/fail2ban/sql/fail2ban.pgsql @@ -0,0 +1,28 @@ +-- +-- Used to store banned/unbanned clients +-- +CREATE TABLE banned ( + id SERIAL PRIMARY KEY, + -- Banned client IP address + ip VARCHAR(46) NOT NULL DEFAULT '', + -- A list of banned network ports, separated by comma + ports VARCHAR(50) NOT NULL DEFAULT '', + -- protocol: tcp, udp, ... + protocol VARCHAR(10) NOT NULL DEFAULT 'tcp', + -- Fail2ban jail name + jail VARCHAR(30) NOT NULL DEFAULT '', + -- The server hostname which the ban/unban happens + hostname VARCHAR(255) NOT NULL DEFAULT '', + country VARCHAR(255) NOT NULL DEFAULT '', + -- When the ban happens + timestamp TIMESTAMP WITHOUT TIME ZONE NOT NULL DEFAULT (CURRENT_TIMESTAMP(0) AT TIME ZONE 'UTC'), + -- if `remove=1`, `ip` will be removed by cron job. + remove INT2 DEFAULT 0 +); + +CREATE UNIQUE INDEX idx_banned_ip_ports_protocol ON banned (ip, ports, protocol); +CREATE INDEX idx_banned_jail ON banned (jail); +CREATE INDEX idx_banned_hostname ON banned (hostname); +CREATE INDEX idx_banned_country ON banned (country); +CREATE INDEX idx_banned_timestamp ON banned (timestamp); +CREATE INDEX idx_banned_remove ON banned (remove);