fail2ban for Docker

Automatically ban repeated failed authentication attempts across docker services.

See fail2ban for a docker based reverse-proxy.

Docker Compose
f2b-docker:
  image: crazymax/fail2ban:latest
  restart: unless-stopped
  network_mode: host
  cap_add:
    - NET_ADMIN
    - NET_RAW
  environment:
    - F2B_LOG_LEVE=DEBUG
    - F2B_DB_PURGE_AGE=30d
    - F2B_MAX_RETRY=5
    - F2B_ACTION=%(action_)s
    - F2B_IPTABLES_CHAIN=DOCKER-USER
    - TZ=America/Los_Angeles
  volumes:
    - /data/services/fail2ban/docker:/data
    - /etc/localtime:/etc/localtime:ro
    - /var/log:/var/log:ro

See Send NGINX Logs to System for setting up NGINX proxy logs.

Enable NGINX Jails

This will enable jails for proxy auth, bad bots, home directories, open proxy, and open scripts.

0644 root root /data/jail.d/nginx.conf
# enable filtering of nginx http auth.
[nginx-http-auth]
enabled  = true
filter   = nginx-http-auth
port     = http,https
logpath  = /var/log/nginx/error.log
bantime  = -1
findtime = 86400
maxretry = 3

# Invalid file / directory access attempts.
[nginx-no-file-directory]
enabled  = true
filter   = nginx-no-file-directory
port     = http,https
logpath  = /var/log/nginx/error.log
bantime  = -1
findtime = 86400
maxretry = 2

# Forbidden index access attempts.
[nginx-forbidden]
enabled  = true
filter   = nginx-forbidden
port     = http,https
logpath  = /var/log/nginx/error.log
bantime  = -1
findtime = 86400
maxretry = 2

# Ban repeated client errors.
[nginx-errors]
enabled  = true
filter   = nginx-errors
port     = http,https
logpath  = /var/log/nginx/access.log
bantime  = -1
findtime = 86400
maxretry = 2

# Ban clients looking for scripts.
[nginx-noscript]
enabled  = true
filter   = nginx-noscript
port     = http,https
logpath  = /var/log/nginx/access.log
bantime  = -1
findtime = 86400
maxretry = 6

# Ban known malicious bad bots.
[nginx-badbots]
enabled  = true
filter   = nginx-badbots
port     = http,https
logpath  = /var/log/nginx/access.log
bantime  = -1
findtime = 86400
maxretry = 2

# Ban requests for user home directories.
[nginx-nohome]
enabled  = true
filter   = nginx-nohome
port     = http,https
logpath  = /var/log/nginx/access.log
bantime  = -1
findtime = 86400
maxretry = 2

# Ban attempts to use as an open proxy.
[nginx-noproxy]
enabled  = true
filter   = nginx-noproxy
port     = http,https
logpath  = /var/log/nginx/access.log
bantime  = -1
findtime = 86400
maxretry = 2

Example nginx.conf

Enable NGINX Filters

This will allow fail2ban to take action on matches and ban IPs. Most of these filters are based off the default filters.

Detect Bad Bots

0644 root root /data/filter.d/nginx-badbots.conf
# Fail2Ban configuration file
#
# Regexp to catch known spambots and software alike. Please verify
# that it is your intent to block IPs which were driven by
# above mentioned bots.

[Definition]

badbotscustom = EmailCollector|WebEMailExtrac|TrackBack/1\.02|sogou music spider|(?:Mozilla/\d+\.\d+ )?Jorgee
badbots       = Atomic_Email_Hunter/4\.0|atSpider/1\.0|autoemailspider|bwh3_user_agent|China Local Browse 2\.6|ContactBot/0\.2|ContentSmartz|DataCha0s/2\.0|DBrowse 1\.4b|DBrowse 1\.4d|Demo Bot DOT 16b|Demo Bot Z 16b|DSurf15a 01|DSurf15a 71|DSurf15a 81|DSurf15a VA|EBrowse 1\.4b|Educate Search VxB|EmailSiphon|EmailSpider|EmailWolf 1\.00|ESurf15a 15|ExtractorPro|Franklin Locator 1\.8|FSurf15a 01|Full Web Bot 0416B|Full Web Bot 0516B|Full Web Bot 2816B|Guestbook Auto Submitter|Industry Program 1\.0\.x|ISC Systems iRc Search 2\.1|IUPUI Research Bot v 1\.9a|LARBIN-EXPERIMENTAL \(efp@gmx\.net\)|LetsCrawl\.com/1\.0 \+http\://letscrawl\.com/|Lincoln State Web Browser|LMQueueBot/0\.2|LWP\:\:Simple/5\.803|Mac Finder 1\.0\.xx|MFC Foundation Class Library 4\.0|Microsoft URL Control - 6\.00\.8xxx|Missauga Locate 1\.0\.0|Missigua Locator 1\.9|Missouri College Browse|Mizzu Labs 2\.2|Mo College 1\.9|MVAClient|Mozilla/2\.0 \(compatible; NEWT ActiveX; Win32\)|Mozilla/3\.0 \(compatible; Indy Library\)|Mozilla/3\.0 \(compatible; scan4mail \(advanced version\) http\://www\.peterspages\.net/?scan4mail\)|Mozilla/4\.0 \(compatible; Advanced Email Extractor v2\.xx\)|Mozilla/4\.0 \(compatible; Iplexx Spider/1\.0 http\://www\.iplexx\.at\)|Mozilla/4\.0 \(compatible; MSIE 5\.0; Windows NT; DigExt; DTS Agent|Mozilla/4\.0 efp@gmx\.net|Mozilla/5\.0 \(Version\: xxxx Type\:xx\)|NameOfAgent \(CMS Spider\)|NASA Search 1\.0|Nsauditor/1\.x|PBrowse 1\.4b|PEval 1\.4b|Poirot|Port Huron Labs|Production Bot 0116B|Production Bot 2016B|Production Bot DOT 3016B|Program Shareware 1\.0\.2|PSurf15a 11|PSurf15a 51|PSurf15a VA|psycheclone|RSurf15a 41|RSurf15a 51|RSurf15a 81|searchbot admin@google\.com|ShablastBot 1\.0|snap\.com beta crawler v0|Snapbot/1\.0|Snapbot/1\.0 \(Snap Shots, \+http\://www\.snap\.com\)|sogou develop spider|Sogou Orion spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sogou spider|Sogou web spider/3\.0\(\+http\://www\.sogou\.com/docs/help/webmasters\.htm#07\)|sohu agent|SSurf15a 11 |TSurf15a 11|Under the Rainbow 2\.2|User-Agent\: Mozilla/4\.0 \(compatible; MSIE 6\.0; Windows NT 5\.1\)|VadixBot|WebVulnCrawl\.unknown/1\.0 libwww-perl/5\.803|Wells Search II|WEP Search 00

failregex     = ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*"(?:%(badbots)s|%(badbotscustom)s)"$

ignoreregex   =

datepattern   = ^[^\[]*\[({DATE})
                {^LN-BEG}

# DEV Notes:
# List of bad bots fetched from http://www.user-agents.org
# Generated on Thu Nov  7 14:23:35 PST 2013 by files/gen_badbots.
#
# Author: Yaroslav Halchenko

Note

This is a direct copy of the apache-badbots filter.

Detect Bad NGINX Basic Auth Attempts

0644 root root /data/filter.d/nginx-http-auth.conf
# fail2ban filter configuration for nginx
[Definition]

failregex   = ^ \[error\] \d+#\d+: \*\d+ user "(?:[^"]+|.*?)":? (?:password mismatch|was not found in "[^\"]*"), client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(?:, referrer: "\S+")?\s*$
              ^ \[error\] \d+#\d+: \*\d+ no user/password was provided for basic authentication, client: <HOST>, server: \S+, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"\s*$

ignoreregex =

datepattern = {^LN-BEG}

# DEV NOTES:
# Based on samples in https://github.com/fail2ban/fail2ban/pull/43/files
# Extensive search of all nginx auth failures not done yet.
#
# Author: Daniel Black

Note

This is the basic nginx-http-auth filter with an additional line to handle basic auth with no username or password.

Detect Access to Home Directories VIA Web

0644 root root /data/filter.d/nginx-nohome.conf
[Definition]

failregex   = ^<HOST> -.*GET .*/~.*

ignoreregex =

Detect Use of Server as a Ad-hoc Proxy

0644 root root /data/filter.d/nginx-noproxy.conf
[Definition]

failregex   = ^<HOST> -.*GET http.*

ignoreregex =

Detect Attempts to Directly Access/Execute Scripts

0644 root root /data/filter.d/nginx-noscript.conf
[Definition]

failregex   = ^<HOST> -.*GET.*(\.php|\.asp|\.exe|\.pl|\.cgi|\.scgi)

ignoreregex =

Detect Access to Forbidden Indexes

0644 root root /data/filter.d/nginx-forbidden.conf
[Definition]

failregex   = ^.*\[error\] \d+#\d+: .* is forbidden, client: <HOST>.*$

ignoreregex =

Detect Attempts to Access Invalid Files/Directories

0644 root root /data/filter.d/nginx-no-file-directory.conf
[Definition]

failregex   = ^.*\[error\] \d+#\d+: .* No such file or directory\), client: <HOST>.*$

ignoreregex =

Detect Multiple Client Error Codes

0644 root root /data/filter.d/nginx-errors.conf
# https://www.restapitutorial.com/httpstatuscodes.html
[Definition]

failregex   = ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*" (40[0-7,9]|4[1-8][0-9]) .*$

ignoreregex =

Restart fail2ban.