Executando verificação de segurança...
41

Como mitigamos um ataque DoS usando iptables em um servidor Linux

Recentemente, tivemos que lidar com uma situação delicada em um ambiente de produção. Uma aplicação web começou a apresentar lentidão e, poucos minutos depois, ficou praticamente indisponível. Ao analisar os logs e o tráfego de rede, percebemos um volume anormal de conexões vindas de diversos IPs. Não era um ataque DDoS massivo, mas um DoS simples focado em esgotar as conexões do serviço.

O ambiente não utilizava WAF nem serviços avançados de mitigação na borda, então a solução mais rápida foi atuar diretamente no firewall do servidor. A decisão foi aplicar uma regra usando iptables para limitar a quantidade de novas conexões por IP dentro de um intervalo de tempo.

Segue um exemplo muito próximo do que utilizamos:


INTERFACE=ens33
IPTABLES=/sbin/iptables
ACTION="DROP"

# Max connection in seconds
SECONDS=60

# Max connections per IP
BLOCKCOUNT=250

# Clean
$IPTABLES -F

# Rules
$IPTABLES -I INPUT -p tcp -m multiport --dports 80,443 -i $INTERFACE -m state --state NEW -m recent --set
$IPTABLES -I INPUT -p tcp -m multiport --dports 80,443 -i $INTERFACE -m state --state NEW -m recent --update --seconds ${SECONDS} --hitcount ${BLOCKCOUNT} -j ${ACTION}

A ideia é simples: se um mesmo IP tentar abrir mais de 250 novas conexões em 60 segundos, o firewall bloqueia automaticamente. Depois de aplicar a regra, o servidor estabilizou em poucos instantes e o tráfego voltou ao normal.

Alguns pontos de atenção

  • Esse tipo de mitigação não substitui soluções mais completas (WAF, CDN, rate-limit na aplicação etc.).

  • Dependendo do tráfego real da aplicação, os valores de BLOCKCOUNT e SECONDS podem precisar ser ajustados.

  • Em ambientes com containers ou balanceamento de carga, talvez seja mais eficiente atuar em outra camada.

Não estou dizendo que essa seja a melhor solução para todos os cenários, mas naquele momento foi o que manteve o serviço online até aplicarmos medidas definitivas.


Este conteúdo foi escrito por Alex Hinckel, fundador da Proactus Tecnologia, empresa especializada em infraestrutura de TI e segurança corporativa.

Carregando publicação patrocinada...
3

Meus 2 cents,

Obrigado por compartilhar !

A solucao apontada usando o modulo 'recent' eh bem legal - simples e limpo de usar.

Para quem for estudar este script, alguns detalhes:

  1. Como usa '$IPTABLES -I' as regras sao inseridas, entao fica na posicao invertida - o resultado final eh (iptables -nvL):
INPUT -i ${INTERFACE} -p tcp -m multiport --dports 80,443 -m state --state NEW -m recent --update --seconds ${SECONDS} --hitcount ${BLOCKCOUNT} -j ${ACTION}
INPUT -i ${INTERFACE} -p tcp -m multiport --dports 80,443 -m state --state NEW -m recent --set

E isto eh correto: primeiro checa se o IP ja esta na lista 'recent' com os limites indicados, se sim ja 'dropa' (descarta). Caso nao esteja na lista, cai na regra seguinte e inclui nesta lista.

Uma pequena alteracao que pode ser legal eh incluir a opcao '--name XXXX' nas duas linhas, assim voce indica qual a lista que se refere - o que pode ser util se voce quiser criar varias listas 'recent' com valores diferentes (e protocolos diferentes).

Um ponto que gostaria de acrescentar eh que pode ser interessante usar este tipo de controle na tabela 'RAW' de forma que, caso o IP esteja na lista, evita que o mesmo entre no 'connection tracking' do NAT (observar a troca de -m state NEW para -m tcp --syn que eh basicamente a mesma coisa, mas sem usar tracking).

Por exemplo:

$IPTABLES -t raw -I PREROUTING -p tcp -m multiport --dports 80,443 -i ${INTERFACE} -m tcp --syn -m recent --set --name HTTP

$IPTABLES -t raw -I PREROUTING -p tcp -m multiport --dports 80,443 -i ${INTERFACE} -m tcp --syn -m recent --name HTTP --update --seconds ${SECONDS} --hitcount ${BLOCKCOUNT} -j ${ACTION} 

Outro adendo: tem outros modulos que podem ser uteis neste caso, como 'hashlimit', 'limit' e 'synproxy' (este ultimo eh legal, mais moderno e ainda um tanto subestimado).

Continue postando sobre o assunto, sempre eh legar ver conteudos diferentes (em especial como cyberseguranca) por aqui.

Saude e Sucesso !

2
2

Meus 2 cents extendidos,

O problema do fail2ban + SNORT aqui eh que para defesa contra DoS (que eh o tema do artigo) eles nao trabalham muito bem.

Veja, a ideia do DoS eh sobrecarregar o servidor com conexoes - utilizando recursos alem do previsto para ele.

Como o fail2ban e SNORT trabalham APOS a conexao ser estabelecida e analisada (p.ex. LOG) - dai nao serem tao eficazes (o consumo de recursos continua alto).

A ideia do iptables aqui eh justamente trabalhar na entrada do pacote, mas antes de ser analisado por qualquer sistema, e descartar quando ele tiver a aparencia de 'atacante' (no caso, grandes quantidades da mesma origem) e assim poupar recursos.

Como apontado no artigo - este tipo de mitigacao funciona legal contra ataques de pequeno porte. Se o servidor for atacado de forma 'profissional' (da para contratar DoS/DDoS com cartao de credito) o unico metodo eficaz eh direto para operadora/datacenter que hospeda o servidor, que provavelmente vai interagir com o BGP para resolver isso.

Mas concordo contigo - a dupla fail2ban + SNORT para analise de trafego eh muito boa - simples e direta. Eu incluiria ai o modsecurity para trabalhar no webserver, tambem uma opcao super bem vista.

Saude e Sucesso !

2

Tome cuidado com imagens ou arquivos grandes, pq da pra fazer slow connection (tipo download a menos de 1kb/s ...) use cloudflare ou outras alternativas ..

1

Legal a saida, desconhecia que podia utiliza o IPTABLES dessa forma.
No meu caso o gerenciamento era feito pelo Nginx, eu utilizei o fail2ban com as minhas regras e quando ele encontra algo adiciona de forma automatica na lista negra do meu Nginx e dava um reload.
Como utiliza o Nginx para gerenciar conexões de TCP/UDP tambem, exemplo RDP ou SSH.

Não sou da area, e quando o servidor estava recebendo as chamadas, no final de semana, foi dessa forma que mitiguei.
Depois passei para o setor responsavel e não sei como ficou, mas no momento do BO resolveu.

1

A solução é boa, mas mesmo que seu servidor drope tudo perfeitamente com iptables, o link de internet do datacenter já vai cair antes porque os pacotes são descartados depois de terem consumido a banda causando uma sobrecarregando a rede da mesma forma em ataques grandes como TCP, UDP flood, ICMP flood (esses dois últimos nem estão mitigados nas configurações de iptables mandou).

Se sofrer um ataque acima de 10Gbs não adiante somente iptables... para ataques menores pode sim mitigar essas regras estando o seu servidor em um DataCenter razoavelmente bom com BGP bem configurado.

A solução melhor para esses casos acima disso é ainda Cloudflare com Anycast global e o seu servidor estar em um datacenter com proteção DDoS de Banda acima de 50Gbps e regras para BGP Blackhole ( onde seu provedor ou DataCenter anuncia uma rota nula).

Aproveitando atualizei o script para incluir regras de UDP e ICMP segue:

INTERFACE=ens33
IPTABLES=/sbin/iptables
ACTION="DROP"

# Limpeza
$IPTABLES -F
$IPTABLES -t raw -F
$IPTABLES -t mangle -F

$IPTABLES -I INPUT -i $INTERFACE -p tcp --syn -m multiport --dports 80,443 \
          -m recent --set --name HTTP

$IPTABLES -I INPUT -i $INTERFACE -p tcp --syn -m multiport --dports 80,443 \
          -m recent --update --seconds 60 --hitcount 250 --name HTTP -j $ACTION

$IPTABLES -I INPUT -i $INTERFACE -p udp \
          -m recent --set --name UDPFLOOD

$IPTABLES -I INPUT -i $INTERFACE -p udp \
          -m recent --update --seconds 1 --hitcount 100 --name UDPFLOOD -j $ACTION

$IPTABLES -I INPUT -i $INTERFACE -p icmp --icmp-type echo-request \
          -m recent --set --name PINGFLOOD

$IPTABLES -I INPUT -i $INTERFACE -p icmp --icmp-type echo-request \
          -m recent --update --seconds 1 --hitcount 10 --name PINGFLOOD -j $ACTION

$IPTABLES -I INPUT -i $INTERFACE -p icmp \
          -m recent --update --seconds 60 --hitcount 50 --name BADGUY -j $ACTION