Terror da Internet, os ataques de DDoS ficaram em evidência ultimamente por causa dos grupos AnonOps e LuzSec, que atacaram vários sites usando essa técnica.
DDoS nada mais é que um ataque do tipo "estouro de boiada". Utilizando máquinas contaminadas, usa-se um programa "administrador" que envia o agendamento do ataque, com data e horário, para uma máquina de destino. No caso esse destino foi num dos servidores que administro. Por acaso onde está o serviço do http://eri.cx entre outros.
O ataque não foi dirigido diretamente à mim, mas um dos sites hospedados lá (não, não foi pro eri.cx). Durante um ataque DDoS, isso não importa muito pois tudo que está hospedado no servidor é afetado juntamente. Ou os serviços tornam-se indisponíveis ou a máquina pode travar, o que não deveria acontecer. Mas um ataque DDoS não abre brechas pra invasão ou algo do gênero.
Felizmente conseguimos mitigar o ataque e minizar seus efeitos com algumas medidas bem simples, que são descritos aqui.
Comecei a suspeitar que algo estava errado quando recebi a mensagem abaixo, da lista de discussão que é mantida nesse servidor.
From: Mail Delivery System <This email address is being protected from spambots. You need JavaScript enabled to view it. >
Date: 2011/7/1
Subject: Undelivered Mail Returned to Sender
To: This email address is being protected from spambots. You need JavaScript enabled to view it.
This is the mail system at host domain.server.com.
I'm sorry to have to inform you that your message could not
be delivered to one or more recipients. It's attached below.
For further assistance, please send mail to postmaster.
If you do so, please include this problem report. You can
delete your own text from the attached returned message.
The mail system
<This email address is being protected from spambots. You need JavaScript enabled to view it. >: Command time limit exceeded: "/var/lib/mailman/mail/mailman
post list"
Imediatamente tentei conectar no servidor e... nada. Página web igualmente fora do ar. Achei que poderia ser algum problema de hardware ou mesmo da máquina virtual. Entrei em contato com a pessoa que tinha o acesso console na máquina e pedi para verificar o que estava acontecendo.
Momentos depois recebi o contato da pessoa avisando que a máquina estava travada e não conseguia dar boot: ela voltava a travar instantes depois. Nesse momento imaginei que podia ser um ataque.
Pedi então para dar boot em "single mode" e desabilitar acesso ao apache e mysql e tentar o boot normalmente. Felizmente deu certo, pois ataques DDoS são fortes em volume, mas não muito inteligentes e refinados.
Utilizando o tcpdump, demos uma olhada no tipo de tráfego que chega e vimos que o ataque era direcionado prioritariamente à porta 80 (web):
17:57:01.220234 IP 115.214.63.123.2844 > server.80: Flags [.], ack 1863118067, win 65306, length 0
17:57:01.237522 IP 115.214.63.123.2844 > server.80: Flags [F.], seq 0, ack 1, win 65306, length 0
17:57:01.237582 IP server.80 > 115.214.63.123.2844: Flags [.], ack 1, win 6432, length 0
17:57:01.241481 IP 86.96.227.91.39237 > server.80: Flags [.], ack 1882163284, win 65535, length 0
17:57:01.241527 IP 86.96.227.91.39237 > server.80: Flags [P.], seq 0:285, ack 1, win 65535, length 285
17:57:01.241573 IP server.80 > 86.96.227.91.39237: Flags [.], ack 285, win 6432, length 0
17:57:01.269729 IP server.80 > 86.96.227.91.39237: Flags [.], seq 1:1461, ack 285, win 6432, length 1460
17:57:01.269774 IP server.80 > 86.96.227.91.39237: Flags [P.], seq 1461:2802, ack 285, win 6432, length 1341
Vários pedidos de início de conexão, sem resposta.
O efeito do ataque pode ser visto nesse gráfico, entre as semanas 26 e 27:
Olhando nos logs do apache, pudemos identificar qual o domínio que estava sob ataque. Confirmamos com tcpdump também que boa parte do ataque buscava tal domínio pelo DNS, verificando o tráfego na porta 53. Então tomei a primeira providência para mitigar o ataque: troquei os IPs do domínio no DNS para 127.0.0.1 (loopback).
Como anúncios de DNS demoram um pouco para serem propagados, essa solução começou a mostrar um pouco mais de eficiência somente depois de 1 hora. Mas isso reduziu o ataque na ordem de 60%, ou até mais.
O DNS seria suficiente, mas o ataque poderia voltar buscando somente o IP e esse truque não iria ajudar muito. Então comecei a olhar como estava configurado o servidor Apache, pois um servidor Unix (ou Linux no caso) não pode travar por conta de um ataque desses, a menos que tenha alguma configuração incorreta.
Como o gráfico mostra, o servidor Apache com suas configurações padrão não foi afetado pelo ataque. Vários processos foram criados, mas finalizados em seguida.
Tentei então verificar como estava o sistema durante o ataque, para tentar identificar o que o ataque tinha ocasionado para travar.
Como os gráficos mostram, o ataque não causou nenhum uso excessivo de CPU ou do sistema. Nada que pudesse levar a máquina ao travamento. Mas o servidor travava com o serviço do Apache ligado. Então resolvi olhar os parâmetros TCP do sistema.
Essa imagem me deu a noção clara que os recursos de redes estavam sendo usados em excesso. Mas mesmo isso não deveria causar o travamento de servidor.
Então resolvi olhar como estava o firewall.
A imagem que ajudou a entender o problema foi a de ipconntrack. Como o netfilter (iptables) utiliza um modo "stateful", cada pacote que entra no sistema ocupa uma posição de memória, para poder identificar (e liberar) as conexões restantes vindas dessa origem. Como o sistema estava sob ataque, a posição era alocada, mas ficava parada aguardando o fim da conexão, que não acontecia. Pra piorar a situação, o firewall alocava memória e recursos do sistema em kernel level, motivo pelo qual o sistema travava.
Para mitigar esse problema, alteramos os parâmetros de kernel com sysctl da seguinte forma:
net.netfilter.nf_conntrack_generic_timeout=5
net.netfilter.nf_conntrack_tcp_timeout_syn_sent=120
net.netfilter.nf_conntrack_tcp_timeout_syn_recv=10
net.netfilter.nf_conntrack_tcp_timeout_established=10
net.netfilter.nf_conntrack_tcp_timeout_fin_wait=5
net.netfilter.nf_conntrack_tcp_timeout_close_wait=3
net.netfilter.nf_conntrack_tcp_timeout_last_ack=10
net.netfilter.nf_conntrack_tcp_timeout_time_wait=5
net.netfilter.nf_conntrack_tcp_timeout_close=10
net.netfilter.nf_conntrack_tcp_timeout_max_retrans=300
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged=300
net.netfilter.nf_conntrack_tcp_loose=1
net.netfilter.nf_conntrack_tcp_be_liberal=0
net.netfilter.nf_conntrack_tcp_max_retrans=3
net.netfilter.nf_conntrack_udp_timeout=30
net.netfilter.nf_conntrack_udp_timeout_stream=180
net.netfilter.nf_conntrack_icmp_timeout=30
net.netfilter.nf_conntrack_icmpv6_timeout=30
net.netfilter.nf_conntrack_frag6_timeout=60
net.netfilter.nf_conntrack_frag6_low_thresh=196608
net.netfilter.nf_conntrack_frag6_high_thresh=262144
net.netfilter.nf_conntrack_acct=1
net.netfilter.nf_conntrack_events=1
net.netfilter.nf_conntrack_events_retry_timeout=15
net.netfilter.nf_conntrack_max=15876
net.netfilter.nf_conntrack_count=254
net.netfilter.nf_conntrack_buckets=4096
net.netfilter.nf_conntrack_checksum=1
net.netfilter.nf_conntrack_log_invalid=0
net.netfilter.nf_conntrack_expect_max=64
net.core.somaxconn=128
net.ipv4.netfilter.ip_conntrack_generic_timeout=5
net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_sent=120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_sent2=120
net.ipv4.netfilter.ip_conntrack_tcp_timeout_syn_recv=20
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established=10
net.ipv4.netfilter.ip_conntrack_tcp_timeout_fin_wait=5
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close_wait=3
net.ipv4.netfilter.ip_conntrack_tcp_timeout_last_ack=10
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait=5
net.ipv4.netfilter.ip_conntrack_tcp_timeout_close=10
net.ipv4.netfilter.ip_conntrack_tcp_timeout_max_retrans=300
net.ipv4.netfilter.ip_conntrack_tcp_loose=1
net.ipv4.netfilter.ip_conntrack_tcp_be_liberal=0
net.ipv4.netfilter.ip_conntrack_tcp_max_retrans=3
net.ipv4.netfilter.ip_conntrack_udp_timeout=30
net.ipv4.netfilter.ip_conntrack_udp_timeout_stream=180
net.ipv4.netfilter.ip_conntrack_icmp_timeout=30
net.ipv4.netfilter.ip_conntrack_max=15876
net.ipv4.netfilter.ip_conntrack_count=254
net.ipv4.netfilter.ip_conntrack_buckets=4096
net.ipv4.netfilter.ip_conntrack_checksum=1
net.ipv4.netfilter.ip_conntrack_log_invalid=0
net.nf_conntrack_max=15876
O padrão de timeout para TCP é de 2 horas. Alterei para alguns segundos. Com isso pudemos reiniciar todos os serviços e mitigar totalmente o ataque, tendo a certeza que o servidor não travaria novamente.
Vírus, spammers, cavalos de tróia, etc. Os caminhos da Internet são cheios de bestas mitológicas, tão devastadores quanto os das epopéias gregas. Arrasando tudo a sua frente, sem dó, sem misericórdia.
E finalmente chegou meu dia de saborear tal destino. Conseguiram invadir esse site e fazer um "defacement", ou em bom português, desfigurar o site.
Como já dizia o dito popular: "em casa de ferreiro, o espeto é de pau". O site é baseado no CMS Mambo Server, de onde o Joomla surgiu. Como uso o Mambo desde 2005 (o primeiro post tem data de "Apr 27, 2005 at 12:06 PM"), por sugestão do meu caro amigo Eduardo Maçan que também o utilizava na época, nunca me incomodei em atualizar muito ou migrar pra outra plataforma. Comecei com a versão 4.5.0, mas tinha atualizado para 4.5.1, quando fiz a "cara" verdinha do site. A mudança foi justamente por motivo de segurança.
E agora, finalmente, fui atacado com sucesso. O ataque foi através do uso de um script chamado Fx29PHPBot. Não achei muita informação sobre o mesmo, mas deve estar baseado em algum sql injection ou coisa do tipo. Isso deixou alguns arquivos extras no servidor:
fx29id2.txt fx29bot.txt fx.php
além do próprio index.php, que foi sobrescrito.
Como o sistema é hospedado e não tenho acesso aos logs... só me restou buscar um backup do site, e carregar em read-only, até descobrir como o ataque ocorreu e, o mais importante, como impedir. Agora posso voltar a postar, utilizando a última versão do Mambo server, 4.6.2. O upgrade foi meio traumático, mas aparentemente com sucesso.
Aparentemente a Telefonica mudou de opinião sobre a politica de bloqueio das portas dentro do range dos "well know services". Recentemente realizei um teste por acaso e descobri minha porta 80, 443 e outras completamente disponíveis na rede. Verificando os logs via webalizer, vi que a quantidade de acessos aumento significante. Olhando cuidadosamente os logs, verifiquei que os ataques também. Mas entre os ataques e a portas liberadas, eu prefiro a segunda alternativa.
Um link interessante sobre WPA2 e AES para autenticação com sistema de chaves assimétricas e geração de chaves aleatórias. Substitui com muito mais segurança o factível WEP. Infelizmente sua implementação não é tão fácil assim e nem todos equipamentos funcionam a contento. Mas aqui fica a referência.
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.0.4 (GNU/Linux)
Comment: For info see http://www.gnupg.org
mQGiBDraRLcRBAC4uqV5SMZdf+Y5gWzUSU5ohPpa2j21y0kHW415LkkqOY3q6dFa
Rre89QqMhr5aDe20Xzn1v+8l4XsY0JfvIEX3nIM7BEKd70JQVILb9KTbi++EzTUw
vART4u8hO/eeor3HxN3VcEMTGCsQB0ZDMTGv6+nSLWiZdyVgmmXaLQAdQwCgpBmw
0N1vJJOfJXW/FAq+W6RUujsEALU3lp16K5cIoXRHp89b0tKX27odr98csJh/WZms
VoXSfmXt10ZedEql74+CLKyB2oFdY8TRUI3WvjUXvFLfGyuYf/f8QfICaKRDODQv
bF7i1ve4OCbcNO4imy072fF2e2rQEHXu/kNAsJAYG/8Zb0HBif4XM8gwGJKbSINd
bU4EA/91xYZ4E6eIGAzaOhSzpyBv3UQAi8nc9bobo2bo/XdCUo+oEP9P7y2voDdW
KV8SklXChX2VqfwMonQwif7Yh/Zp3NIxg/UlJnkYr4E4YIMtfOKpEezTJLSLQNgb
04ldy9iTaimwyK7EgB6mwSEnCXlMf54lOrd4mnrjGA9VTEfNA7RJSMOpbGlvIEFs
ZXhhbmRyZSBMb3BlcyBMb3VyZWlybyAoZGVmYXVsdCBhZGRyZXNzKSA8aGVsaW9A
bG91cmVpcm8uZW5nLmJyPohXBBMRAgAXBQI62kS3BQsHCgMEAxUDAgMWAgECF4AA
CgkQIiqRMftZctHe1gCZAXwBIPVnWdIxU2K8+uXU4qqvp/MAn23gjT0Snqy4oZU5
cUv/N2FrOCWXuQINBDraRWUQCAD5p1JeGVMdWy5SUWVw+ldSLwGXwXXqeSg7ynb7
4ghsPOfLGFqzwabGRtUR8A3rtqwm3e4XqUhD8SX6a9HAwCuAiwpCZBvFocf2/59b
QW3NCAkQ0L2H7UigO0ZRpGEHtsFyerFnW2ftx75iPFh8kVwBh+1NKHASIOP87R5V
DgbUdvwdCSEOqyZiS43DyFIW68WU9H430g2Yo6Zy+HHV9MKVGK2Ki6hiTDecYTBz
JmOdawQvBzCZeDE5hivWMoFPJnYVOjD0jhQolF0lc0Fbpd76NYcmw5dxK5c9i8kn
KJTYLE8QlXTTzrim8KekoDE2TkEK+uo7Jr/WtebTPdV5mF5rAAMGB/wIAtSiCC0b
IXLBaAPCoPTifdGsyH+xaxkbzqr+Gntnvnic+vB7a15lkHMnZ7bmllPSohQTtX6R
pHj0jDOK2EJs4KcB5HWcH9XgQJWQ/e+Ht18kQ2Y3dnhFH4HoDbV8DhSt4gJIpBtf
C+77Wh5aa+7SSixmV8oiHTjEsP3wmxR5EmSMhVKyhHGYCeGXYi3ft4+/2qu/pZxJ
pjoPf2bKqa0UuxN7V1dhD/ofIGgwm3rJ9PXhr+UfM8ZUi5McDmKNwnkODlnPwT8H
1qJLzzZSyY1uCx4NPyS0OZ6xGBSgk8K6wZ2udjDPYV5Oyf/PZ2i/Ep3tv8wSajKv
nTFgwo1yWTJziEYEGBECAAYFAjraRWUACgkQIiqRMftZctENRQCggW0qwNf4ct3n
tidjmTCUEGKspecAnA+VoQo5aTrcjLLTKRDfRWKXVOTI
=1yPG
-----END PGP PUBLIC KEY BLOCK-----