Então, estou executando um servidor docker com um contêiner nginx fazendo proxy reverso de vários outros contêineres. No host, quero usar o fail2ban para banir IPs que tentam invadir sites do WordPress. Bem simples, mas preciso usar uma ação personalizada para que o banimento ocorra na cadeia DOCKER-USER, caso contrário, os encaminhamentos do docker (que também usam iptables) substituem os banimentos. Para conseguir isso, monto o diretório de logs do nginx do host para o contêiner para que o fail2ban possa observá-los do host.
Tudo parece estar funcionando perfeitamente, exceto pelo fato de que não está banindo nenhum IP. O regex corresponde corretamente nos testes, banir manualmente funciona perfeitamente, os logs do fail2ban não mostram nenhuma estranheza; estou perplexo.
Aqui está um trecho ofuscado/anonimizado do registro de acesso;
132.321.555.777 - - [24/Mar/2025:17:12:07 +0000] "POST //xmlrpc.php HTTP/1.1" 200 423 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
132.321.555.777 - - [24/Mar/2025:17:12:07 +0000] "POST //xmlrpc.php HTTP/1.1" 200 423 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
132.321.555.777 - - [24/Mar/2025:17:12:07 +0000] "POST //xmlrpc.php HTTP/1.1" 200 423 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
132.321.555.777 - - [24/Mar/2025:17:12:08 +0000] "POST //xmlrpc.php HTTP/1.1" 200 423 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
132.321.555.777 - - [24/Mar/2025:17:12:08 +0000] "POST //xmlrpc.php HTTP/1.1" 200 423 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
84.29.333.555 - - [24/Mar/2025:17:12:08 +0000] "GET /wp-content/uploads/2024/06/xx-32x32.png HTTP/1.1" 200 926 "-" "NetworkingExtension/8620.2.4.10.8 Network/4277.82.1 iOS/18.3.2"
84.29.333.555 - - [24/Mar/2025:17:12:08 +0000] "GET /wp-content/uploads/2024/06/xx-180x180.png HTTP/1.1" 200 5567 "-" "NetworkingExtension/8620.2.4.10.8 Network/4277.82.1 iOS/18.3.2"
132.321.555.777 - - [24/Mar/2025:17:12:09 +0000] "POST //xmlrpc.php HTTP/1.1" 200 423 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
132.321.555.777 - - [24/Mar/2025:17:12:09 +0000] "POST //xmlrpc.php HTTP/1.1" 200 423 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
132.321.555.777 - - [24/Mar/2025:17:12:09 +0000] "POST //xmlrpc.php HTTP/1.1" 200 423 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
132.321.555.777 - - [24/Mar/2025:17:12:10 +0000] "POST //xmlrpc.php HTTP/1.1" 200 423 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
43.166.222.22 - - [24/Mar/2025:17:12:02 +0000] "GET / HTTP/1.1" 400 248 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
84.29.123.32 - - [24/Mar/2025:17:12:08 +0000] "GET /wp-content/uploads/2023/01/xx-300x225.png HTTP/1.1" 200 115438 "-" "NetworkingExtension/8620.2.4.10.8 Network/4277.82.1 iOS/18.3.2"
84.29.123.32 - - [24/Mar/2025:17:12:08 +0000] "GET /wp-content/uploads/2024/06/xx-192x192.png HTTP/1.1" 200 5994 "-" "NetworkingExtension/8620.2.4.10.8 Network/4277.82.1 iOS/18.3.2"
84.29.123.32 - - [24/Mar/2025:17:12:09 +0000] "GET /wp-content/uploads/2024/06/xx-32x32.png HTTP/1.1" 200 926 "-" "NetworkingExtension/8620.2.4.10.8 Network/4277.82.1 iOS/18.3.2"
/etc/fail2ban/jail.local
[nginx-xmlrpc]
enabled = true
filter = nginx-xmlrpc
logpath = /var/dockervolumes/nginx/logs/access.log
maxretry = 1
findtime = 5
bantime = 3600
action = iptables-docker
Configurei o maxretry e o findtime bem baixos para testes, mas isso não ajudou.
/etc/fail2ban/filter.d/nginx-xmlrpc.conf
[INCLUDES]
before = nginx-bad-request.conf
[Definition]
failregex = ^<HOST>.*] "POST (|.*)\/xmlrpc\.php.*
^<HOST>.*] "GET (|.*)\/xmlrpc\.php.*
^<HOST> .* "POST .*wp-login.php
ignoreregex = ^<HOST>.*] "POST (|.*)\/xmlrpc\.php\?for=jetpack.*
datepattern = ^[^\[]*\[({DATE})
{^LN-BEG}
Como você pode ver, eu já tentei mexer no padrão de datas, mas isso não ajudou.
/etc/fail2ban/action.d/iptables-docker.conf
[Definition]
actionstart =
actionstop =
actioncheck = /usr/sbin/iptables -n -L DOCKER-USER | grep -q '[<ip>]'
actionban = /usr/sbin/iptables -I DOCKER-USER -s <ip> -j DROP
actionunban = /usr/sbin/iptables -D DOCKER-USER -s <ip> -j DROP
Testando o regex; fail2ban-regex /var/dockervolumes/nginx/logs/access.log /etc/fail2ban/filter.d/nginx-xmlrpc.conf
Running tests
=============
Use failregex filter file : nginx-xmlrpc, basedir: /etc/fail2ban
Use datepattern : ^[^\[]*\[({DATE})
{^LN-BEG} : Default Detectors
Use log file : /var/dockervolumes/nginx/logs/access.log
Use encoding : UTF-8
Results
=======
Failregex: 13345 total
|- #) [# of hits] regular expression
| 1) [13299] ^<HOST>.*] "POST (|.*)\/xmlrpc\.php.*
| 2) [20] ^<HOST>.*] "GET (|.*)\/xmlrpc\.php.*
| 3) [26] ^<HOST> .* "POST .*wp-login.php
`-
Ignoreregex: 0 total
Date template hits:
|- [# of hits] date format
| [26486] ^[^\[]*\[(Day(?P<_sep>[-/])MON(?P=_sep)ExYear[ :]?24hour:Minute:Second(?:\.Microseconds)?(?: Zone offset)?)
`-
Lines: 26486 lines, 0 ignored, 13345 matched, 13141 missed
[processed in 2.39 sec]
Testando o ban manualmente; fail2ban-client set nginx-xmlrpc banip 1.2.5.9
Produz log:
2025-03-24 19:09:35,909 fail2ban.actions [828254]: NOTICE [nginx-xmlrpc] Ban 1.2.5.9
E lista corretamente o ip bloqueado; iptables -L DOCKER-USER
Chain DOCKER-USER (1 references)
target prot opt source destination
DROP all -- 1.2.5.9 anywhere
DROP all -- 1.2.4.9 anywhere
DROP all -- 1.2.3.9 anywhere
DROP all -- 1.2.3.8 anywhere
DROP all -- 1.2.3.7 anywhere
DROP all -- 1.2.3.6 anywhere
DROP all -- 1.2.3.5 anywhere
RETURN all -- anywhere anywhere
O log também não mostra mais nenhuma estranheza; tail -f /var/log/fail2ban.log
2025-03-24 19:00:29,067 fail2ban.actions [828254]: NOTICE [nginx-xmlrpc] Restore Ban 1.2.3.5
2025-03-24 19:00:29,080 fail2ban.actions [828254]: NOTICE [nginx-xmlrpc] Restore Ban 1.2.3.6
2025-03-24 19:00:29,094 fail2ban.actions [828254]: NOTICE [nginx-xmlrpc] Restore Ban 1.2.3.7
2025-03-24 19:00:29,104 fail2ban.actions [828254]: NOTICE [nginx-xmlrpc] Restore Ban 1.2.3.8
2025-03-24 19:00:29,115 fail2ban.actions [828254]: NOTICE [nginx-xmlrpc] Restore Ban 1.2.3.9
2025-03-24 19:00:29,126 fail2ban.actions [828254]: NOTICE [nginx-xmlrpc] Restore Ban 1.2.4.9
2025-03-24 19:00:29,240 fail2ban.filtersystemd [828254]: INFO [nginx-xmlrpc] Jail is in operation now (process new journal entries)
2025-03-24 19:05:53,278 fail2ban.actions [828254]: NOTICE [nginx-xmlrpc] Unban 1.2.3.4
2025-03-24 19:09:33,024 fail2ban.actions [828254]: WARNING [nginx-xmlrpc] 1.2.4.9 already banned
2025-03-24 19:09:35,909 fail2ban.actions [828254]: NOTICE [nginx-xmlrpc] Ban 1.2.5.9
ATUALIZAR:
~ status do cliente fail2ban nginx-xmlrpc
Status for the jail: nginx-xmlrpc
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- Journal matches: _SYSTEMD_UNIT=nginx.service + _COMM=nginx
`- Actions
|- Currently banned: 0
|- Total banned: 8
`- Banned IP list:
Essas 8 proibições foram meus testes manuais.
~ iptables-salvar
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -o br-51ec37449070 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-51ec37449070 -j DOCKER
-A FORWARD -i br-51ec37449070 ! -o br-51ec37449070 -j ACCEPT
-A FORWARD -i br-51ec37449070 -o br-51ec37449070 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2020 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2019 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2018 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2017 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2016 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2015 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2014 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2013 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2012 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2011 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2010 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2009 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2008 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2007 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2006 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2005 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2004 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2003 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2002 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2001 -j ACCEPT
-A DOCKER -d 172.18.0.39/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 2000 -j ACCEPT
-A DOCKER -d 172.18.0.6/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 443 -j ACCEPT
-A DOCKER -d 172.18.0.6/32 ! -i br-51ec37449070 -o br-51ec37449070 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-51ec37449070 ! -o br-51ec37449070 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-51ec37449070 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -s 1.14.96.192/32 -j DROP
-A DOCKER-USER -s 18.219.14.219/32 -j DROP
-A DOCKER-USER -s 174.138.27.210/32 -j DROP
-A DOCKER-USER -s 128.199.244.121/32 -j DROP
-A DOCKER-USER -s 45.130.145.4/32 -j DROP
-A DOCKER-USER -s 128.199.244.121/32 -j DROP
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Wed Mar 26 09:10:19 2025
# Generated by iptables-save v1.8.10 (nf_tables) on Wed Mar 26 09:10:19 2025
*nat
:PREROUTING ACCEPT [320032242:19224216945]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [396346224:30027564903]
:POSTROUTING ACCEPT [531692826:38140531338]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 ! -o br-51ec37449070 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2020 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2019 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2018 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2017 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2016 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2015 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2014 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2013 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2012 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2011 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2010 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2009 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2008 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2007 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2006 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2005 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2004 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2003 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2002 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2001 -j MASQUERADE
-A POSTROUTING -s 172.18.0.39/32 -d 172.18.0.39/32 -p tcp -m tcp --dport 2000 -j MASQUERADE
-A POSTROUTING -s 172.18.0.6/32 -d 172.18.0.6/32 -p tcp -m tcp --dport 443 -j MASQUERADE
-A POSTROUTING -s 172.18.0.6/32 -d 172.18.0.6/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER -i br-51ec37449070 -j RETURN
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2020 -j DNAT --to-destination 172.18.0.39:2020
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2019 -j DNAT --to-destination 172.18.0.39:2019
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2018 -j DNAT --to-destination 172.18.0.39:2018
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2017 -j DNAT --to-destination 172.18.0.39:2017
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2016 -j DNAT --to-destination 172.18.0.39:2016
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2015 -j DNAT --to-destination 172.18.0.39:2015
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2014 -j DNAT --to-destination 172.18.0.39:2014
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2013 -j DNAT --to-destination 172.18.0.39:2013
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2012 -j DNAT --to-destination 172.18.0.39:2012
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2011 -j DNAT --to-destination 172.18.0.39:2011
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2010 -j DNAT --to-destination 172.18.0.39:2010
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2009 -j DNAT --to-destination 172.18.0.39:2009
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2008 -j DNAT --to-destination 172.18.0.39:2008
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2007 -j DNAT --to-destination 172.18.0.39:2007
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2006 -j DNAT --to-destination 172.18.0.39:2006
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2005 -j DNAT --to-destination 172.18.0.39:2005
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2004 -j DNAT --to-destination 172.18.0.39:2004
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2003 -j DNAT --to-destination 172.18.0.39:2003
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2002 -j DNAT --to-destination 172.18.0.39:2002
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2001 -j DNAT --to-destination 172.18.0.39:2001
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 2000 -j DNAT --to-destination 172.18.0.39:2000
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 443 -j DNAT --to-destination 172.18.0.6:443
-A DOCKER ! -i br-51ec37449070 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.18.0.6:80
COMMIT
# Completed on Wed Mar 26 09:10:19 2025