Questa mattina ad un certo punto il server web che ospita antirez.com
ha cessato completamente di funzionare. La causa e' un attacco informatico di proporzioni abbastanza severe, e questo e' un piccolo resoconto su cosa e' successo e su come ho momentaneamente posto fine ai problemi, nella speranza che possa essere utile agli altri.
Il problema
- Quando mi sono loggato sul server via SSH il carico mostrato da top era di... 330!
- Nei log di Apache c'erano due elementi che facevano capire subito di cosa si trattava: un warning in cui Apache mi avvisava che MaxClients era stato superato (era impostato a 200), e il fatto che in error.log era pieno di messaggi simili al seguente:
request failed: erroneous characters after protocol string: $MyNick
(comhem)Dzij|$Lock EXTENDEDPROTOCOLABCABCABCABCABCABC
Pk=DCPLUSPLUS0.690ABCABC|
Una veloce ricerca su google ha evidenziato come queste stringhe siano parte del protocollo
dei client peer to peer Direct Connect, dunque il povero server era stato preso d'assalto da migliaia di client p2p che eseguivano
centinaia di richieste al secondo sulla porta 80.
In queste condizioni ci sono due possibili scenari:
- Con MaxClients troppo alto il server si pianta completamente
- Con MaxClients ragionevole il server smette di servire le pagine perche' oltre le 200 (nel mio caso specifico) mette gli altri client in coda.
Insomma il web server non serviva piu' una pagina... i client continuavano (e stanno continuando) a bombardare il server da migliaia di IP diversi. Come fronteggiare la situazione?
Firewalling
Il firewalling da solo non mi aiutava molto, i client infatti accedevano ad una porta nota, e la porta di origine era anche assolutamente normale, come quella di un normale web browser. L'unico modo per filtrare sarebbe stato utilizzare una regola di firewalling che cercasse dentro il pacchetto pezzi del protocollo binario (la stringa EXTENDEDPROTOCOL .... non veniva spedita sempre infatti, molto spesso le richieste sembravano di tipo binario).
Cio' era abbastanza complesso da fare al volo perche' era necessario andarsi a studiare il protocollo e se mi ricordo bene
iptables non e' in grado di andare a fare il match tra i byte del pacchetto.
Tcpdump e un piccolo programma in Tcl
La soluzione finale e' stata di utilizzare l'output di tcpdump e un piccolo programma in Tcl scritto sul momento per aggiungere al volo regole di firewalling che filtrassero tutti i client che stavano eseguendo piu' di 50 richieste al web server in poco tempo.
Ecco lo script in questione:
debian:~# cat p2p.tcl
while {[gets stdin line]} {
regexp {IP ([0-9\.]+) >} $line => ip
if {[string first 62.149.233.114 $ip] == -1} {
set s [split $ip .]
set ip [join [lrange $s 0 3] .]
if {![info exists x($ip)]} {
# puts $ip
set x($ip) 0
} else {
incr x($ip)
if {$x($ip) == 50} {
puts $ip
exec iptables -I INPUT -p tcp --dport 80 -s $ip -j DROP
}
}
}
}
Anche questo poneva un problema: infatti quando l'attacco iniziava a scemare, i client veri potevano accedere e rapidamente scambiavano 50 pacchetti col server, entrando nella blacklist anche loro.
Per risolvere questo problema e' bastato spegnere Apache, in modo che i client legittimati avrebbero visto la pagina di rifiuto di connessione senza scambiare altri dati con il server, mentre
i client malvagi avrebbero continuato a provare incessantemente.
Infatti l'esecuzione di questo script per alcuni minuti ha creato alcune migliaia di regole che filtrano gran parte dei client p2p che tentano di accedere al server. Il risultato e' che la macchina e' nuovamente up.
A questo ho aggiunto una piccola modifica al file di configurazione di Apache:
#Timeout 300
Timeout 10
Insomma il Timeout per mancato scambio dati in una connessione e' stato portato da 300 a 10 secondi temporaneamente, in modo da far andare in timeout i client p2p che non sono riuscito a filtrare perche' stanno facendo troppe poche richieste al secondo e dunque liberare spazio piu' velocemente per i client reali che non rimangono appesi ad aspettare.
Domande
Ne ho un bel po'
- Chi e' stato ;)
- Come e' possibile far credere a migliaia di client che il mio Server e' un client che ha qualcosa che tutti vogliono condividere o che e' un server della rete (non so quale delle due tecniche sia stata usata)
- E' stato doloso o un errore?
Penso che finiro' per custodire questo script sul server per la prossima volta... anche se sarebbe piu' simpatico non finire nuovamente sotto attacco in breve tempo ;)
In ogni caso sono ancora pesantemente sotto attacco... e il traffico e' enorme, gli IP man mano cambiano, dunque niente di strano che ogni tanto devo rimettere il server down per filtrare nuovamente gli IP maligni.
Quando finira'?
Aggiornamento: Ho settato MaxClients a 500 e Timeout a 5 nella speranza di riuscire a tenere un carico di attacco maggiore.
Edit 27 Maggio 2007: Ecco
la spiegazione di come e' stato eseguito l'attacco.