diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..479f07a --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +trigger-build.sh +run.sh +vars +tests/ diff --git a/Dockerfile b/Dockerfile index a22e0b5..4638f30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,8 @@ -FROM neomediatech/ubuntu-base:latest +FROM neomediatech/ubuntu-base:20.04 -ENV VERSION=0.10.2-2 \ - SERVICE=fail2ban +ENV VERSION=0.11.2 \ + SERVICE=fail2ban \ + FAIL2BAN_VERSION=0.11.2 LABEL maintainer="docker-dario@neomediatech.it" \ org.label-schema.version=$VERSION \ @@ -9,11 +10,22 @@ LABEL maintainer="docker-dario@neomediatech.it" \ org.label-schema.vcs-url=https://github.com/Neomediatech/${SERVICE} \ org.label-schema.maintainer=Neomediatech -RUN apt update && apt-get -y dist-upgrade && \ - apt-get install -y --no-install-recommends fail2ban ipset iptables ssmtp redis-tools curl whois && \ +RUN apt-get update && apt-get -y dist-upgrade && \ + apt-get install -y --no-install-recommends --no-install-suggests ca-certificates python3 python3-setuptools \ + python3-pycurl wget ipset iptables ssmtp redis-tools curl whois && \ rm -rf /var/lib/apt/lists* && \ rm -rf /etc/fail2ban/jail.d && \ - mkdir -p /var/run/fail2ban + mkdir -p /var/run/fail2ban && \ + cd /tmp && \ + wget https://github.com/fail2ban/fail2ban/archive/${FAIL2BAN_VERSION}.tar.gz -O fail2ban-${FAIL2BAN_VERSION}.tar.gz && \ + tar xvzf fail2ban-${FAIL2BAN_VERSION}.tar.gz && \ + cd fail2ban-${FAIL2BAN_VERSION} && \ + python3 setup.py install && \ + cd / && \ + mkdir -p /usr/local/etc/fail2ban && \ + cp -rp /etc/fail2ban /usr/local/etc && \ + rm -rfv /tmp/* + COPY entrypoint.sh /entrypoint.sh diff --git a/Dockerfile.22.04 b/Dockerfile.22.04 new file mode 100644 index 0000000..e03c9c0 --- /dev/null +++ b/Dockerfile.22.04 @@ -0,0 +1,38 @@ +FROM neomediatech/ubuntu-base:22.04 + +ENV SERVICE=fail2ban \ + APP_VERSION=1.0.1 + +LABEL maintainer="docker-dario@neomediatech.it" \ + org.label-schema.version=$APP_VERSION \ + org.label-schema.vcs-type=Git \ + org.label-schema.vcs-url=https://github.com/Neomediatech/${SERVICE} \ + org.label-schema.maintainer=Neomediatech + +RUN apt-get update && apt-get -y dist-upgrade && \ + apt-get install -y --no-install-recommends --no-install-suggests \ + libexpat1 libmpdec3 libpython3-stdlib libpython3.10-minimal libpython3.10-stdlib \ + libreadline8 libsqlite3-0 media-types python3 python3-minimal python3.10 python3.10-minimal \ + readline-common wget ipset iptables ssmtp redis-tools curl whois ca-certificates && \ + rm -rf /var/lib/apt/lists* && \ + rm -rf /etc/fail2ban/jail.d && \ + mkdir -p /var/run/fail2ban && \ + cd /tmp && \ + wget https://github.com/fail2ban/fail2ban/releases/download/1.0.1/fail2ban_${APP_VERSION}-1.upstream1_all.deb && \ + dpkg -i fail2ban_${APP_VERSION}-1.upstream1_all.deb && \ + cd / && \ + #mkdir -p /usr/local/etc/fail2ban && \ + #cp -rp /etc/fail2ban /usr/local/etc && \ + rm -rfv /tmp/* + + +COPY entrypoint.sh /entrypoint.sh + +RUN chmod a+x /entrypoint.sh + +VOLUME [ "/data" ] + +ENTRYPOINT [ "/tini", "--", "/entrypoint.sh" ] +CMD [ "fail2ban-server", "-f", "-x", "-v", "start" ] + +HEALTHCHECK --interval=30s --timeout=5s CMD fail2ban-client ping diff --git a/README.md b/README.md index 2aee227..ceecf8e 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,10 @@ Clone this repo if you want to use configs already set by me. ``` BASE_DIR="/srv/data/docker/containers/fail2ban/" NAME="fail2ban" -docker run -d --privileged --net=host --name $NAME --hostname $NAME -v $BASED_DIR/confs:/data neomediatech/$NAME +docker run -d --privileged --net=host --name $NAME --hostname $NAME -v $BASE_DIR/confs:/data neomediatech/$NAME ``` Add a bind mount where to point your logs that f2b need to monitor for ex: -`-v $BASED_DIR/logs:/var/log` +`-v $BASE_DIR/logs:/var/log` ## Warning Portainer doesn't understand `env_file` parameter (at least for now, 27 feb 2019). diff --git a/confs/action.d/manual-blacklist.local b/confs/action.d/manual-blacklist.local new file mode 100644 index 0000000..0cc8a3a --- /dev/null +++ b/confs/action.d/manual-blacklist.local @@ -0,0 +1,48 @@ +# Fail2Ban configuration file +# + +[INCLUDES] + +before = iptables-common.conf + +[Definition] + +actionstart = ipset create hash:ip timeout maxelem 4294967295 + -I -m set --match-set src -j + +actionflush = ipset flush + +actionstop = -D -m set --match-set src -j + + ipset destroy + +actionban = ipset add timeout -exist + +# actionprolong = %(actionban)s + +actionunban = ipset del -exist + +[Init] + +# Option: default-ipsettime +# Notes: specifies default timeout in seconds (handled default ipset timeout only) +# Values: [ NUM ] Default: 0 (no timeout, managed by fail2ban by unban) +default-ipsettime = 0 + +# Option: ipsettime +# Notes: specifies ticket timeout (handled ipset timeout only) +# Values: [ NUM ] Default: 0 (managed by fail2ban by unban) +ipsettime = 0 + +# expresion to caclulate timeout from bantime, example: +# banaction = %(known/banaction)s[ipsettime=''] +timeout-bantime = $([ "" -le 2147483 ] && echo "" || echo 0) + +ipmset = f2b- +familyopt = + + +[Init?family=inet6] + +ipmset = f2b-6 +familyopt = family inet6 diff --git a/confs/filter.d/manual-blacklist.conf b/confs/filter.d/manual-blacklist.conf new file mode 100644 index 0000000..61f63ed --- /dev/null +++ b/confs/filter.d/manual-blacklist.conf @@ -0,0 +1,21 @@ +# Fail2Ban filter for manual blacklisting IP addresses +# +# Write every IP addresses or networks in CIDR format you want in a file, +# one per line, then point this filter to that file. +# + +[INCLUDES] + +before = + +[Definition] + +failregex = \/(.*) + $ + +ignoreregex = + +[Init] + +# var = val + diff --git a/confs/jail.d/10-defaults.conf b/confs/jail.d/10-defaults.conf index e233f8c..851a65b 100644 --- a/confs/jail.d/10-defaults.conf +++ b/confs/jail.d/10-defaults.conf @@ -4,7 +4,7 @@ nodename = honey-node abusemsg = brute force auth on honeypot # -ignoreip = 127.0.0.1/8 +ignoreip = 127.0.0.0/8 bantime = 7200 findtime = 3600 diff --git a/confs/jail.d/neo.conf b/confs/jail.d/honeypot.conf similarity index 61% rename from confs/jail.d/neo.conf rename to confs/jail.d/honeypot.conf index 3a8b46f..9f8adb1 100644 --- a/confs/jail.d/neo.conf +++ b/confs/jail.d/honeypot.conf @@ -2,29 +2,29 @@ enabled = true port = 25,465,587,143,993,110,995 filter = exim-auth -logpath = /var/log/mainlog +logpath = /var/log/honeypot/exim4/mainlog findtime = 7200 bantime = 86400 maxretry = 2 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s (SMTP auth)", key="bad:deny:%(__name__)s:%(nodename)s:0"] + ipblock[port="%(port)s",msg="Trying SMTP Auth on honeypot (%(nodename)s)", bantime=%(bantime)s, db=auth] [exim-bad-sender] enabled = true port = smtp,ssmtp,587 filter = exim-bad-sender-neo -logpath = /var/log/mainlog +logpath = /var/log/honeypot/exim4/mainlog findtime = 3600 bantime = 3600 maxretry = 1 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s", key="bad:deny:%(__name__)s:%(nodename)s:0"] + ipblock[category="smtp-bad-sender",port="%(port)s",msg="BAD senders. From (%(nodename)s)",bantime="%(bantime)s",db=neo] [exim-defer] enabled = true port = smtp,ssmtp,587 filter = exim-defer-neo -logpath = /var/log/mainlog +logpath = /var/log/honeypot/exim4/mainlog findtime = 3600 bantime = 3600 maxretry = 1 @@ -37,106 +37,120 @@ bantime = 3600 findtime = 3600 maxretry = 3 filter = exim-redis-neo -logpath = /var/log/mainlog +logpath = /var/log/honeypot/exim4/mainlog action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] [mail-cbl] enabled = true port = 25,465,587 filter = exim-cbl -logpath = /var/log/mainlog +logpath = /var/log/honeypot/exim4/mainlog bantime = 7200 findtime = 3600 maxretry = 1 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="REJECTED - see https://www.abuseat.org/lookup.cgi for details ", key="bad:deny:cbl:%(nodename)s:1"] + ipblock[category="cbl",port="%(port)s",msg=" Access on SMTP ports, found on CBL.abuseat (%(nodename)s)", bantime=%(bantime)s, db=cbl] [dovecot] enabled = true port = 110,143,993,995 filter = dovecot -logpath = /var/log/dovecot.log +logpath = /var/log/honeypot/dovecot.log bantime = 3600 +maxretry = 1 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s (IMAP/POP auth)", key="bad:deny:%(__name__)s-auth:%(nodename)s:0"] abuseipdb[category="18",port="pop,imap,pops,imaps",msg=" POP/IMAP %(abusemsg)s server (%(nodename)s)"] + ipblock[port="%(port)s",msg=" POP/IMAP %(abusemsg)s server (%(nodename)s)", bantime=%(bantime)s, db=auth] [mysqld] enabled = true -port = 3306 +port = 7200 #filter = mysql-auth-neo #logpath = /var/log/mysql.log -logpath = /var/log/opencanary.log +logpath = /var/log/honeypot/opencanary.log filter = opencanary-neo[port="%(port)s"] findtime = 3600 bantime = 14400 maxretry = 2 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s (SQL auth)", key="bad:deny:%(__name__)s-auth:%(nodename)s:0"] abuseipdb[category="18",port="%(port)s",msg=" SQL %(abusemsg)s MySQL/MariaDB server (%(nodename)s)"] + ipblock[port="%(port)s",msg=" SQL %(abusemsg)s MySQL/MariaDB server (%(nodename)s)", bantime=%(bantime)s, db=auth] [ssh] enabled = true port = 22 #filter = sshd #logpath = /var/log/messages -logpath = /var/log/opencanary.log +logpath = /var/log/honeypot/opencanary.log filter = opencanary-neo[port="%(port)s",find=".*PASSWORD"] -bantime = 3600 -maxretry = 3 +bantime = 7200 +maxretry = 2 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s (SSH auth)", key="bad:deny:%(__name__)s-auth:%(nodename)s:0"] abuseipdb[category="18,22",port="ssh",msg=" SSH %(abusemsg)s server (%(nodename)s)"] + ipblock[port="%(port)s",msg=" SSH %(abusemsg)s server (%(nodename)s)", bantime=%(bantime)s, db=auth] [telnet] enabled = true port = 23 #logpath = /var/log/telnet.log -logpath = /var/log/opencanary.log +logpath = /var/log/honeypot/opencanary.log #filter = telnet-neo filter = opencanary-neo[port="%(port)s"] bantime = 28800 findtime = 3600 maxretry = 2 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s (TELNET auth)", key="bad:deny:%(__name__)s-auth:%(nodename)s:0"] abuseipdb[category="18",port="telnet",msg=" Telnet %(abusemsg)s server (%(nodename)s)"] + ipblock[port="%(port)s",msg="Telnet %(abusemsg)s server (%(nodename)s)", bantime=%(bantime)s, db=auth] [mssql] enabled = true port = 1433 -logpath = /var/log/opencanary.log +logpath = /var/log/honeypot/opencanary.log filter = opencanary-neo[port="%(port)s"] bantime = 360000 findtime = 3600 maxretry = 3 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s (MSSQL auth)", key="bad:deny:%(__name__)s-auth:%(nodename)s:0"] abuseipdb[category="18",port="%(port)s",msg=" MSSQL %(abusemsg)s server (%(nodename)s)"] + ipblock[port="%(port)s",msg="MSSQL %(abusemsg)s server (%(nodename)s)", bantime=%(bantime)s, db=auth] [vnc] enabled = true port = 5900 -logpath = /var/log/opencanary.log +logpath = /var/log/honeypot/opencanary.log filter = opencanary-neo[port="%(port)s"] bantime = 360000 -findtime = 3600 -maxretry = 3 +findtime = 14400 +maxretry = 2 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s (VNC auth)", key="bad:deny:%(__name__)s-auth:%(nodename)s:0"] abuseipdb[category="18",port="%(port)s",msg=" VNC %(abusemsg)s server (%(nodename)s)"] + ipblock[port="%(port)s",msg="VNC %(abusemsg)s server (%(nodename)s)", bantime=%(bantime)s, db=auth] [redis] enabled = true port = 6379 -logpath = /var/log/opencanary.log +logpath = /var/log/honeypot/opencanary.log filter = opencanary-neo[port="%(port)s"] bantime = 360000 findtime = 3600 maxretry = 3 action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s (REDIS auth)", key="bad:deny:%(__name__)s-auth:%(nodename)s:0"] abuseipdb[category="18",port="%(port)s",msg=" REDIS %(abusemsg)s server (%(nodename)s)"] + ipblock[port="%(port)s",msg="REDIS %(abusemsg)s server (%(nodename)s)", bantime=%(bantime)s, db=neo] + +################# +# il filtro "find" non sta funzionando, non so come mai +################## +[rdp-mstshash] +enabled = true +port = random +logpath = /var/log/honeypot/opencanary.log +filter = opencanary-neo[port="%(port)s",find=".*mstshash.*FUNCTION.*DATA_RECEIVED.*"] +bantime = 7200 +maxretry = 2 +action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] + ipblock[port="%(port)s",msg="RDP abuse with mstshash pattern %(abusemsg)s server (%(nodename)s)", bantime=%(bantime)s, db=neo] [dnsbl] enabled = yes @@ -144,8 +158,8 @@ maxretry = 1 findtime = 1200 bantime = 3600 filter = dnsbl-neo -logpath = /dnsbl-log/dnsbl-for-fail2ban.log +logpath = /var/log/honeypot/dnsbl-ipset/dnsbl-for-fail2ban.log action = iptables-ipset-proto6-allports[name=%(__name__)s, port="%(port)s", protocol="tcp", chain="%(chain)s", bantime=%(bantime)s] - redis[ttl="%(bantime)s", msg="From:%(nodename)s-%(__name__)s", key="bad:deny:%(__name__)s:%(nodename)s:0"] - + ipblock[category="dnsbl_ipset",port="to be done",msg=" From (%(nodename)s) with dnsbl_ipset",bantime="%(bantime)s",db=dnsbl_ipset] + dnsbl-ipset diff --git a/confs/jail.d/manual-blacklist.conf b/confs/jail.d/manual-blacklist.conf new file mode 100644 index 0000000..5196117 --- /dev/null +++ b/confs/jail.d/manual-blacklist.conf @@ -0,0 +1,9 @@ +[manual-blacklisted] +enabled = true +maxretry = 1 +action = manual-blacklist +filter = manual-blacklist +logpath = /var/log/honeypot/manual-blacklisted-ip.log +bantime = -1 +findtime = 86400 + diff --git a/entrypoint.sh b/entrypoint.sh index 1eddf3c..9d1317e 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -7,12 +7,14 @@ F2B_DEST_EMAIL=${F2B_DEST_EMAIL:-root@localhost} F2B_SENDER=${F2B_SENDER:-root@$(hostname -f)} F2B_ACTION=${F2B_ACTION:-%(action_)s} F2B_IPTABLES_CHAIN=${F2B_IPTABLES_CHAIN:-DOCKER-USER} -F2B_LOGDIR=${F2B_LOGDIR:-/data/log} +F2B_LOGDIR=${F2B_LOGDIR:-/var/log} SSMTP_PORT=${SSMTP_PORT:-25} SSMTP_HOSTNAME=${SSMTP_HOSTNAME:-$(hostname -f)} SSMTP_TLS=${SSMTP_TLS:-NO} +[ -f /data/config.ini ] && source /data/config.ini + # SSMTP echo "Setting SSMTP configuration..." if [ -z "$SSMTP_HOST" ] ; then @@ -39,9 +41,7 @@ unset SSMTP_PASSWORD # Init echo "Initializing files and folders..." mkdir -p /data/db /data/action.d /data/filter.d /data/jail.d /var/log /dnsbl-log -touch /var/log/{mainlog,dovecot.log,opencanary.log,auth.log} /dnsbl-log/dnsbl-for-fail2ban.log -chmod 666 /var/log/* /dnsbl-log/dnsbl-for-fail2ban.log -ln -sf /data/jail.d /etc/fail2ban/ +#ln -sf /data/jail.d /etc/fail2ban/ # Set some settings in jail.d/10-defaults.conf DEFAULTS_FILE="/data/jail.d/10-defaults.conf" @@ -101,6 +101,40 @@ for filter in ${filters}; do ln -sf "/data/filter.d/${filter}" "/etc/fail2ban/filter.d/" done +# Set some settings in jail.d/10-defaults.conf +DEFAULTS_FILE="/data/jail.d/10-defaults.conf" +if [ -f "${DEFAULTS_FILE}" ]; then + [ -n "${NODE_NAME}" ] && sed -i "s/^nodename.*/nodename = ${NODE_NAME}/g" "${DEFAULTS_FILE}" + [ -n "${IGNORE_IP}" ] && sed -i "s/^ignoreip.*/ignoreip = ${IGNORE_IP}/g" "${DEFAULTS_FILE}" +fi + +# Check custom jails +echo "Checking for custom jails in /data/jail.d..." +jails=$(ls -l /data/jail.d | egrep '^-' | awk '{print $9}') +if [ -n "$jails" ]; then + for jail in ${jails}; do + if [ -f "/etc/fail2ban/jail.d/${jail}" ]; then + echo " WARNING: ${jail} already exists and will be overriden" + rm -f "/etc/fail2ban/jail.d/${jail}" + fi + echo " Add custom jail ${jail}..." + ln -sf "/data/jail.d/${jail}" "/etc/fail2ban/jail.d/" + done +fi + +for file in $(ls /etc/fail2ban/jail.d); do + LOGPATHS="$(grep logpath /etc/fail2ban/jail.d/$file | awk -F= '{print $2}')" + for LOGPATH in $LOGPATHS; do + if [ ! -e "$LOGPATH" ]; then + mkdir -p "$(dirname "$LOGPATH")" + touch "$LOGPATH" + chmod 666 "$LOGPATH" + fi + done + touch /dnsbl-log/dnsbl-for-fail2ban.log + chmod 666 /dnsbl-log/dnsbl-for-fail2ban.log +done + [ ! -d "${F2B_LOGDIR}" ] && mkdir -p "${F2B_LOGDIR}" LOGFILE="${F2B_LOGDIR}/fail2ban.log" if [ ! -f $LOGFILE ]; then