Por que o iptables não está bloqueando um endereço IP? (Versão LB / proxy)

4

AVISO: Longo. Muita informação aqui.

Há 3 anos alguém perguntou Por que o iptables não está bloqueando um endereço IP? ? e descobriu-se que o motivo era porque os servidores estavam por trás do CloudFlare, o que tornava impossível bloquear os endereços IP diretamente do jeito que eles queriam, a menos que você o usasse de maneira diferente. Qualquer proxy reverso ou balanceador de carga causaria a mesma coisa.

Da mesma forma, configuramos o fail2ban com uma regra para proibir qualquer bots que tente forçar sua entrada no login administrativo ou no spam xmlrpc. O site está sentado atrás de um balanceador de carga, então obviamente não podemos proibir diretamente o endereço IP, mas o iptables deve estar aceitando a conexão e o padrão que combinam os dados do pacote para banir o tráfego específico.

Esta é a configuração fail2ban jail.conf:

[wp-auth] 
enabled = true
filter = wp-auth
action = iptables-proxy[name = lb, port = http, protocol = tcp]
         sendmail-whois[name=LoginDetect, [email protected], [email protected], sendername="Fail2Ban"]
logpath = /obfuscated/path/to/site/transfer_log
bantime = 604800
maxretry = 4
findtime = 120

Esta é simplesmente a correspondência de padrões para solicitações wp-login:

[Definition]
failregex = ^<HOST> .* "POST /wp-login.php
ignoreip = # our ip address

Esta é a nossa ação fail2ban iptables que deveria ser capaz de bloquear esses bots, mas a maior parte não parece. É da seção Dicas do site CentOS para fail2ban atrás de um proxy . Por razões de brevidade, deixei apenas os comentários do cabeçalho da seção no lugar.

# Fail2Ban configuration file
#
# Author: Centos.Tips
#

[INCLUDES]

before = iptables-blocktype.conf

[Definition]

# Option:  actionstart
actionstart = iptables -N fail2ban-<name>
              iptables -A fail2ban-<name> -j RETURN
              iptables -I <chain> -p <protocol> --dport <port> -j fail2ban-<name>

# Option:  actionstop
actionstop = iptables -D <chain> -p <protocol> --dport <port> -j fail2ban-<name>
             iptables -F fail2ban-<name>
             iptables -X fail2ban-<name>

# Option:  actioncheck
actioncheck = iptables -n -L <chain> | grep -q 'fail2ban-<name>[ \t]'

# Option:  actionban
actionban = iptables -I fail2ban-<name> 1 -p tcp --dport 80 -m string --algo bm --string 'X-Forwarded-For: <ip>' -j DROP

# Option:  actionunban
actionunban = iptables -D fail2ban-<name> -p tcp --dport 80 -m string --algo bm --string 'X-Forwarded-For: <ip>' -j DROP

[Init]
# Default name of the chain
name = default

# Option:  port
port = http

# Option:  protocol
protocol = tcp

# Option:  chain
chain = INPUT    

Então, como mencionei, o site está em um par de servidores por trás de um balanceador de carga elástico e parece funcionar no teste. Podemos adicionar qualquer um dos nossos endereços IP e não podemos acessar o site. Apesar disso, os bots parecem conseguir passar.

[root:~/] iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N fail2ban-SSH
-N fail2ban-lb
-A INPUT -p tcp -m tcp --dport 80 -j fail2ban-lb
-A INPUT -p tcp -m tcp --dport 22 -j fail2ban-SSH
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 5666 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 24007:24020 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
-A fail2ban-SSH -j RETURN
-A fail2ban-lb -p tcp -m tcp --dport 80 -m string --string "X-Forwarded-For: 91.200.12.33" --algo bm --to 65535 -j DROP
-A fail2ban-lb -p tcp -m tcp --dport 80 -m string --string "X-Forwarded-For: 91.134.50.10" --algo bm --to 65535 -j DROP
-A fail2ban-lb -p tcp -m tcp --dport 80 -m string --string "X-Forwarded-For: 160.202.163.125" --algo bm --to 65535 -j DROP
-A fail2ban-lb -p tcp -m tcp --dport 80 -m string --string "X-Forwarded-For: 162.243.68.232" --algo bm --to 65535 -j DROP
-A fail2ban-lb -j RETURN

A porta 80 é a única porta aberta a todos. Todos os outros são ACL com os grupos de segurança da AWS. IPtables parece estar processando na ordem correta e, portanto, deve estar bloqueando esses IPs com base em seu cabeçalho X-Forwarded-For. Existe um plug-in do Firefox que permite enviar esses cabeçalhos com solicitações iniciais e, como resultado, também é bloqueado com qualquer um desses IPs de bots.

O endereço IP de origem não parece estar forjando o cabeçalho X-Forwarded-For com o qual estamos jogando, já que o ELB os reescreve de qualquer maneira. O tcpdump não mostra nenhuma informação extra no pacote no nível do servidor.

22:07:14.309998 IP ip-10-198-178-233.ec2.internal.11054 > ec2-10.4.8.71.http: Flags [P.], seq 2545:3054, ack 19506, win 166, options [nop,nop,TS val     592575835 ecr 2772410449], length 509
E..1..@[email protected]
...
f.p+..P.Nz.
20............
#Q.[.?.QPOST /wp-login.php HTTP/1.1
host: www.thiswebsite.com
Accept: */*
Accept-Language: zh-cn
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Referer: http://www.thiswebsite.com/wp-login.php
User-Agent: Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; 125LA; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)
X-Forwarded-For: 91.200.12.33
X-Forwarded-Port: 80
X-Forwarded-Proto: http
Content-Length: 21
Connection: keep-alive

Essas solicitações estão sendo registradas no transfer_log. Quando fazemos a mesma coisa e forjamos o X-Forwarded-For, somos pegos pelo iptables antes mesmo de chegar ao Apache. O tcpdump também mostra nossos IPs extras.

20:10:25.378873 IP ip-10-198-178-233.ec2.internal.11054 > ec2-10.4.8.71.http: Flags [P.], seq 3157:3860, ack 124583, win 267, options [nop,nop,TS     val 526293643 ecr 2507283790], length 703
E...Tf@.@.[.
...
f.p,O.P...GU........m.....
.^...r.QPOST /wp-login.php HTTP/1.1
host: www.thiswebsite.com
Accept: /
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.5
Cache-Control: no-cache
Cookie: __utma=190528439.16251225.1476378792.1478280188.1478289736.3; __utmz=190528439.1476378792.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);     _icl_current_language=en; __utmc=190528439; __utmb=190528439.2.10.1478289736; __utmt=1
Pragma: no-cache
Referer: http://www.thiswebsite.com/
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:49.0) Gecko/20100101 Firefox/49.0
X-Forwarded-For: 91.200.12.33, <our ip address>
X-Forwarded-Port: 80
X-Forwarded-Proto: http
Connection: keep-alive

Eu também tenho o log de acesso do ELB aqui que espero ver uma entrada, mas não os logs de transferência do Apache.

2016-11-07T22:07:14.309917Z mLB 91.200.12.33:60407 10.4.8.71:80 0.000079 1.99244 0.000091 200 200 21 3245 "POST http://www.thiswebsite.com:80/wp-login.php HTTP/1.1" "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; 125LA; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)" - -

Portanto, o endereço IP (pelo menos de acordo com o ELB) não parece ser forçado no nível X-Forwarded-For. Por que o tráfego não está bloqueado? O endereço IP também aparece constantemente no log do fail2ban com o usual:

fail2ban.actions[11535]: INFO [wp-auth] 91.200.12.33 already banned
    
por dcmbrown 08.11.2016 / 18:23

2 respostas

2

Suas regras do iptables parecem boas. Não se pode dizer ao certo o que eles estão passando, no entanto, sem que o log aceite. O Tcpdump não diz isso porque ele é executado na entrada antes que o iptables seja executado. Como você precisa de um balanceador de carga, os logs de aceitação do iptables para a porta 80 provavelmente produziriam arquivos muito grandes que você precisaria gerenciar cuidadosamente (para uso do disco) e precisaria de scripts ou outras ferramentas para analisá-los. No entanto, é isso que você precisa fazer para descobrir o que está acontecendo.

O que eu posso lhe dizer acima, porém, é que há um problema de vazamento inerente ao uso de correspondência de cadeia de pacotes de rede para filtragem em nível de aplicativo. Os limites de pacotes não respeitam os limites dos aplicativos, portanto, em um ambiente de alto ataque, algumas dessas solicitações serão transmitidas. Este é um efeito estatístico. Com pedidos suficientes direcionados ao seu sistema, a probabilidade de que alguns deles sejam divididos em mais de um pacote aumenta. Só isso pode explicar os vazamentos. Os hackers podem inclinar as probabilidades a seu favor inserindo cabeçalhos que aumentam o tamanho do pacote. Mas o volume sozinho é suficiente.

Para filtragem completa, você precisa filtrar no nível do aplicativo. O Apache fornece vários mecanismos para isso. Você pode bloquear usuários identificados pelo fail2ban com uma regra .htaccess para o X-Forwarded-For. Você também pode filtrar sua diretiva Location. Não vejo uma opção para fazer isso dentro do fail2ban, nem um utilitário autônomo que faz isso, mas um script personalizado para sincronizar fail2ban jail-ees com um filtro do apache seria uma maneira de implementar um filtro no nível do aplicativo.

Mais uma consideração: você publicou regras para o IPv4. Se você estiver aceitando conexões IPv6 na porta 80, será necessário garantir que essas regras também sejam mantidas.

    
por 27.04.2017 / 20:08
0

Parece que o fail2ban não está realmente fazendo as novas regras que você acha que é. Quando você vê a mensagem "já banido", você faz um "iptables -L" e vê a regra desejada? Uma mensagem "já banida" indica que sua detecção está funcionando, mas seu firewall não está. Se você ver a regra, mas não está funcionando, isso significa que algo sobre a regra não funciona e você precisa repensar a regra.

Seu failregex e ignoreip me dizem que você só quer bloquear todos que não são de seus endereços IP. Isso parece muito mais simples do que usar o fail2ban.

Na verdade, o seu Admin Console precisa mesmo de um balanceador de carga? 99% do tráfego para esse site deve ser ruim tentando invadir. Se você sabe quais endereços permitir, e seu failregex e ignoreip indicam que você faz isso, você pode simplesmente tornar o Admin Console acessível diretamente, mas apenas para os IPs permitidos. / p>

Oh, ei, isso não é sobre o SSL, é? Se for, o iptables não pode ler o cabeçalho X-Forwarded-For.

Eu realmente gosto da ideia de HBruijn sobre o uso da API do cloudflares. Eles deveriam estar fazendo o bloqueio, não você.

Por fim, se você decidir fazer a filtragem no nível do apache, o mod_rewrite tem reescrever mapas que são ótimos para isso. Os recursos dbd e prg permitem que você altere o mapeamento sem reiniciar o apache.

Espero que algo disso ajude

-Dylan

    
por 02.05.2017 / 19:08