Contromisure agli attacchi DoS e DDoS

In questo post abbiamo visto cosa si intende per attacchi DoS e DDoS. Ora vedremo come si possono prevenire (dove possibile), riconoscere ed eventualmente bloccare (o mitigare).

In generale, possiamo affermare che esistono tre linee di difesa contro gli attacchi DoS e DDoS:

1) Prevenzione e cognizione: questa fase si sviluppa prima dell’attacco vero e proprio e comprende tutti quei meccanismi che consentono all’host vittima di resistere ai tentativi di negazione del servizio, continuando a garantire l’accesso da parte degli utenti legittimi.

2) Rilevazione degli attacchi e filtraggio: tale fase prevede un’accurata anlisi dei log, in modo da identificare le varie sorgenti dell’attacco, i servizi presi di mira (ad esempio il protocollo HTTP), e la tipologia di traffico (TCP oppure UDP);

3) Risalire alla sorgente dell’attacco: tale operazione è sicuramente la più complessa, in quanto il vero attaccante non si espone quasi mai direttamente, ma usa tutta una serie di tecniche di bouncing (basate su proxy anonimi) che gli consentono di mantenere un certo anonimato. A questo va ad aggiungersi l’utilizzo delle macchine zombie come front-end, rendendo ancora più difficile l’individuazione del vero colpevole.

Dopo questa breve introduzione prettamente teorica andiamo ad analizzare, uno per uno, i vari punti citati precedentemente, in modo tale da fornire degli esempi pratici che possono certamente tornare utili ai vari utenti/amministratori di sistema che si ritrovano a dover fronteggiare gli attacchi in questione. Occorre comunque fare una premessa: le varie tecniche descritte in questo post riguardano la configurazione di alcuni firewall hardware (PIX/ASA Cisco) e di alcuni firewall software, quali IPTABLES.

Ma veniamo a noi. Per prevenire gli effetti nefasti di un attacco DoS o DDoS basato sulla tecnica SYN-flood (e quindi sulle connessioni half-open) occorre operare sul numero di connessioni che il firewall può accettare. A tal proposito, nell’ambito dei firewall PIX/ASA possono essere utilizzati i seguenti comandi:

Per prima cosa definisco una class-map, in modo da rispettare l’approccio modulare tanto caldeggiato da Cisco:

hostname(config)# class-map <nome>

Inoltre, faccio in modo che in questa class-map venga controllato il traffico tcp diretto alla porta 80 (HTTP):

hostname(config)# match port tcp eq 80

Successivamente definisco una policy-map, alla quale assocerò la class-map creata in precedenza:

hostname(config)# policy-map <nome>
hostname(config-pmap)# class <nome>

A questo punto non mi resta che definire alcuni parametri, quali il numero massimo di connessioni attive, il numero massimo di nuove connessioni (embryonic, leggasi half-open) che il firewall può accettare, il numero massimo di connessioni embryonic per ogni host sorgente, il numero massimo di connessioni attive per ogni host sorgente ed infine l’eventuale uso di un numero di sequenza random:

hostname(config-pmap-c)# set connection {[conn-max number] [embryonic-conn-max number] [per-client-embryonic-max number] [per-client-max number][random-sequence-number {enable | disable}}

Procedo dunque con il settaggio dei timeout relativi ai vari tipi di connessione (già instaurate, half-open, half-closed e quelle basate sul protocollo tcp):

hostname(config-pmap-c)# set connection {[embryonic hh[:mm[:ss--] [half-closed hh[:mm[:ss--] [tcp hh[:mm[:ss--]}

Non ci resta che associare la policy-map appena creata a tutte le interfacce (global) oppure ad un’interfaccia specifica:

hostname(config)# service-policy policymap_name {global | interface <nome>}

A titolo di esempio, ecco una possibile configurazione del nostro PIX/ASA:

 firewall(config)# class-map tcp_syn
 firewall(config-cmap)# match port tcp eq 80
 firewall(config-cmap)# exit
 firewall(config)# policy-map tcpmap
 firewall(config-pmap)# class tcp_syn
 firewall(config-pmap-c)# set connection conn-max 100
 firewall(config-pmap-c)# set connection embryonic-conn-max 200
 firewall(config-pmap-c)# set connection per-client-embryonic-max 10
 firewall(config-pmap-c)# set connection per-client-max 5
 firewall(config-pmap-c)# set connection random-sequence-number enable
 firewall(config-pmap-c)# set connection timeout embryonic 0:0:45
 firewall(config-pmap-c)# set connection timeout half-closed 0:25:0
 firewall(config-pmap-c)# set connection timeout tcp 2:0:0
 firewall(config-pmap-c)# exit
 firewall(config-pmap)# exit
 firewall(config)# service-policy tcpmap interface outside

Vediamo ora una configurazione piuttosto semplice, ma comunque funzionale, relativa ad IPTABLES. Come già detto per i PIX/ASA, la configurazione che andremo a vedere ha come scopo principale quello di mitigare gli attacchi SYN-flood:

iptables -A INPUT -p tcp --syn -m limit --limit 5/s --limit-burst 10 -j DROP

con questa regola associata alla catena INPUT scarteremo tutti i segmenti tcp contenenti come flag syn nel caso in cui il firewall ne riceva più di 5 al secondo (oppure nel caso in cui ne riceva più di 10 consecutivamente).

Possiamo inoltre limitare ed eventualmente loggare i tentativi di port-scan, sui quali si basano alcuni attacchi DDoS già descritti nel post precedente.

Per fare ciò utilizziamo la rule:

iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -m limit --limit 1/s -j DROP

In particolare, con questa regola stiamo droppando tutti i segmenti con flag SYN, ACK, FIN ed RST ricevuti dal firewall, nel caso in cui la loro frequenza sia superiore ad 1 al secondo. Da notare che tali flag vengono costantemente usate da nmap per “aggirare” i filtri imposti dal firewall (l’opzione -sS vi dice qualcosa?).

Infine, possiamo loggare il traffico matchato dalla catena INPUT mediante la seguente regola:

iptables -A INPUT -j LOG --log-prefix "Traffico in ingresso: "

Tali log verranno salvati in /var/log/syslog e saranno identificati dal prefisso “Traffico in ingresso: “ definito in precedenza. Infine, per quanto riguarda il logging degli hit relativi alle regole IPTABLES occorre fare una precisazione: nel caso in cui il firewall debba gestire un quantitativo di traffico in ingresso non indifferente (mediante la catena INPUT), loggare tutto quanto indiscriminatamente è una pratica piuttosto sconveniente, in quanto i file di log potrebbero assumere delle dimensioni eccessive e quindi riempire in poco tempo lo spazio su disco.

Proprio per evitare ciò, occorrerebbe definire delle catene dedicate, una che si occupi esclusivamente del controllo relativo agli attacchi syn-flood e l’altra dei port-scan. Ad esempio:

#SYN-flood

iptables -N SYN_FLOODS
iptables -A SYN_FLOOD -p tcp --syn -m limit --limit 5/s --limit-burst 10 -j RETURN
iptables -A SYN_FLOOD ! -p tcp  -j RETURN
iptables -A SYN_FLOOD -p tcp ! --syn  -j RETURN
iptables -A SYN_FLOOD -j LOG --log-prefix "SYN_FLOOD: "
iptables -A SYN_FLOOD -j DROP
iptables -A INPUT -p tcp --syn -j SYN_FLOOD

#Port-scan

iptables -N PORT-SCAN
iptables -A PORT-SCAN -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -m limit --limit 1/s -j RETURN
iptables -A PORT-SCAN -j LOG --log-prefix "PORT_SCAN: "
iptables -A PORT-SCAN -j DROP
iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST SYN -j PORT-SCAN

Passiamo ora alla fase 2, ovvero alla rilevazione degli attacchi e filtraggio. Per prima cosa occorre individuare la tipologia di traffico su cui si basa l’attacco (ovvero se si tratta di segmenti TCP oppure di segmenti UDP). In secondo luogo è necessario identificare la porta (e quindi il servizio) a cui il DDoS sta puntando. Entrambe le operazioni possono essere effettuate grazie ad un’analisi delle connessioni in ingresso e dei log.

Per ciò che concerne i firewall PIX/ASA possiamo visualizzare le connessioni inbound mediante il comando:

sh conn

specificando, se è il caso, una particolare porta in modo da scremare l’output:

sh conn port 80

Nel caso in cui le connessioni instaurate con l’esterno siano prossime al numero massimo supportato dal firewall, possiamo digitare il comando:

clear conn port 80

e cancellarle in un colpo solo.

Per quanto riguarda i log, invece, essi possono essere visualizzati mendiante il comando:

sh log

Ora, occorre precisare che l’analisi dei log è di estrema importanza, in quanto ci consente di individuare abbastanza velocemente gli IP che hanno superato il numero massimo di connessioni consentite dalla policy-map impostata in precedenza. Quasi sicuramente tali IP saranno quelli associati alle macchine che stanno scagliando l’attacco.

Non ci resta quindi che creare un ACL (Access Control List) apposita da associare all’interfaccia outside. Personalmente ritengo che in questi casi conviene usare sempre e comunque le ACL nominali, in quanto consentono la cancellazione delle singole rule, senza dover ricreare ex-novo l’intera ACL.

Possiamo creare l’ACL nominale che chiameremo no_ddos mediante il comando:

firewall(config)# access-list no_ddos
firewall(config)# access-list no_ddos line 1 deny ip host <IP Sorgente dell'attacco> any
firewall(config)# access-list no_ddos line 2 deny ip host <altro IP Sorgente dell'attacco> any

e così via. In questo modo stiamo negando agli IP sorgenti dell’attacco qualunque possibilità di connessione al nostro firewall. Poichè le ACL hanno come policy di default il deny any any implicito, occorre consentire esplicitamente tutto il traffico legittimo. Se ad esempio abbiamo a che fare con un server Web che non prevede la pubblicazione di nessun altro servizio, possiamo definire la rule:

firewall(config)# access-list no_ddos line 3 premit tcp any any eq 80

Ovviamente, tale regola ha senso solo se sul server Web non vi sono contenuti multimediali. Nel caso in cui i contenuti multimediali siano presenti, oltre a permettere il traffico TCP occorrerà consentire anche quello UDP. Possiamo consentire il traffico basato su entrambi i protocolli mediante una sola regola, ovvero:

firewall(config)# access-list no_ddos line 3 premit ip any any eq 80

Per verificare che effettivamente gli IP filtrati dalla nostra ACL siano quelli che generano il maggior quantitativo di traffico basta usare il comando:

sh access-list no_ddos | include <IP>

L’output ci mostrerà il cosiddetto hitcount (abbreviato in hitcnt), ovvero quante volte il traffico in ingresso ha matchato la specifica rule dell’ACL. Valori elevati associati all’hitcount ci daranno la conferma che gli IP filtrati sono effettivamente quelli che stanno generando l’attacco.

A questo punto occorre fare alcune considerazioni. Come abbiamo già detto gli attacchi DDoS possono fare uso di macchine zombie, ovvero di macchine infettate da un applicativo malevolo che consente all’attaccante di ottenerne il controllo, in modo del tutto trasparente all’utente legittimo. Ci sono altri casi, però, in cui non si fa uso di macchine zombie, bensì di shell regolarmente acquistate. Tali shell hanno IP pubblico statico, ciò significa che ogni qual volta si connetteranno ad Internet, l’ISP assegnerà loro sempre lo stesso indirizzo IP. Questo rappresenta per noi, come è facile intuire, il caso migliore, in quanto si ha la certezza che bannando uno specifico indirizzo IP, una delle macchine della dosnet sarà permanentemente bloccata dal firewall.

Nel caso in cui la dosnet sia formata da macchine zombie le cose si fanno un pò più complesse. Poichè parliamo di normalissimi pc connessi ad Internet, è quasi certo che usino degli indirizzi IP dinamici. Questo significa che inserire il loro indirizzo IP all’interno dell’ACL rappresenta una soluzione temporanea, in quanto ad ogni riconnessione lo stesso pc infetto utilizzerà un nuovo indirizzo IP pubblico. Cosa fare dunque? Per prima cosa dobbiamo porci alcune domande:

1) I tentativi di attacco provengono da IP italiani o stranieri?

2) I contenuti pubblicati sul nostro server Web si riferiscono ad un utenza nazionale o internazionale?

Per rispondere alla prima domanda basta fare un copia incolla degli IP incriminati su una shell *nix ed utilizzare il comando host, oppure, più semplicemente, copiarlo in uno dei tanti siti sparsi per la rete che consentono, a partire dall’indirizzo IP, di risalire all’hostname.

Ora, mettiamo che gli attacchi vengano effettivamente sferrati da IP stranieri (come succede nel 99% dei casi). Cosa fare? E qui possiamo andare direttamente al punto 2): se l’utenza del sito è nazionale si potrebbe bannare esplicitamente l’intera classe IP incriminata, oppure (soluzione più drastica) consentire il traffico proveniente dai netblock italiani e droppare tutto il resto. A tal proposito ho trovato una lista (non so quanto aggiornata) dei vari AS italiani con relativi netblock (potrete trovarla qui).

Per quanto riguarda le ACL occorre fare delle precisazioni. C’è da dire che, nonostante le ACL nominali vengano applicate il più vicino possibile alla sorgente del traffico, quindi all’interfaccia outbound del firewall, esse richiedono un minimo di carico computazionale, in quanto devono analizzare il pacchetto in ingresso, identificare l’indirizzo IP sorgente (presente nell’header) ed eventualmente scartarlo o instradarlo verso l’interfaccia inbound. Se il traffico diretto al nostro firewall raggiunge proporzioni non indifferenti e le caratteristiche hardware di quest’ultimo sono abbastanza pietose (leggasi CPU poco performante e pochi MB di RAM), corriamo seriamente il rischio che il firewall stesso si schianti in men che non si dica.

Per ciò che concerne invece IPTABLES, il ban esplicito degli indirizzi IP può essere applicato direttamente sulla chain INPUT, utilizzando la seguente regola:

iptables -A INPUT -s <ip sorgente dell'attacco> -j DROP

Possiamo inoltre consentire il traffico HTTP diretto sulla porta 80 mediante la rule:

iptables -A INPUT -p tcp --dport 80 -j ACCEPT

e negare tutto il resto mediante la policy di default associata alla catena in questione:

iptables -P INPUT DROP

Anche in questo caso è essenziale l’analisi dei log (sia del firewall che del server Web) e l’analisi delle connessioni in ingresso (facilmente realizzabile mediante il comando netstat ed eventualmente grep).

Veniamo ora alla fase più complessa, ovvero a quella in cui si tenta di risalire al vero autore dell’attacco. Risalire alla sorgente dell’attacco prevede una mole di lavoro non indifferente, che spesso non da alcun risultato utile. Vi sono comunque, a mio avviso, diversi modi di operare:

1) Si potrebbe cercare di ottenere (durante l’attacco vero e proprio) l’accesso ad una delle macchine zombie. In questo modo, facendo un semplice netstat si riuscirebbe ad individuare tutti gli utenti connessi al pc e ad identificare altre macchine zombie oppure possibili proxy anonimi utilizzati dal vero attaccante. Con un pò di fortuna, se il proxy non è poi tanto anonimo come dice di essere e registra le connessioni in ingresso, da una semplice analisi dei log si potrebbe ottenere l’indirizzo IP del vero autore dell’attacco.

2) Si potrebbe notare l’accesso sistematico al portale Web da parte di un determinato indirizzo IP, in alcuni “momenti chiave”, ad esempio poco prima dell’attacco, durante l’attacco e poco dopo l’attacco. Per conteggiare gli accessi dell’IP sospetto si potrebbe impostare una regola in cima all’ACL no_ddos, ad esempio:

firewall(config)# access-list no_ddos line 1 permit ip host <IP sospetto> any

Discorso simile vale per IPTABLES:

iptables -A INPUT -s <ip sospetto> -j LOG --log-prefix "IP_SOSPETTO: "

e successivamente spulciare il file di log con l’ausilio di grep.

Spero di essere stato chiaro e utile, anche se sono ben conscio del fatto che non esiste un modus operandi standard per contrastare questi attacchi, in quanto le variabili in gioco sono davvero troppe.

Ci aggiorniamo, a presto.

Contromisure agli attacchi DoS e DDoSultima modifica: 2012-01-29T11:05:08+01:00da nazarenolatella
Reposta per primo quest’articolo

11 pensieri su “Contromisure agli attacchi DoS e DDoS

  1. complimenti per l’articolo,non ho compreso tutto causa delle scarse conoscenze. avrei una domanda quante sono le connessioni che conviene impostare su un checkpoint 500 alla voce:Network Quota? onde evitare possibili attacchi Dos /Dddos,le impostazioni di fabbrica sono su 100,adesso ho impostato 80.ciò può essere causa di problemi di navigazione? grazie

  2. Ciao, grazie per i complimenti. Sinceramente non conosco questo prodotto, quindi non sono in grado di risponderti con assoluta certezza. Il numero massimo di connessioni che dovrai impostare dipende fortemente dalla mole di traffico in ingresso. Per intenderci: se tramite un port forwarding hai pubblicato all’esterno la porta 80 o 443 (server Web) ed il relativo sito (o siti) ospitato ha molte hit giornaliere (accessi), devi utilizzare una soglia di connessioni un pò più ampia di quella di default (100). Se invece si tratta solo di una piccola LAN in cui non vi sono servizi pubblicati all’esterno, 80 connessioni credo che siano più che sufficienti. Per avere la certezza devi fare delle prove e nel caso in cui gli utenti lamentassero “lentezza” in fase di navigazione, devi alzare tale soglia.
    Ciao.

  3. 1000 grazie,per inciso,ho un solo pc uso home,nessun port forwarding,utilizzo 2 browser web in contemporanea con 6/10 pagine aperte.tramite wifi talvolta uso un eepc ma nulla di stravagante,solo per avere doppio accesso su siti con restrizioni (chat).sono approdato al checkpoint dopo uno zyxel 2wg e un D-link entrambi con problemi di connessione al wizard.purtroppo la suddetta azienda non fà assistenza ai privati,ma solo con abbonamento a possessori di partita iva.quindi non posso sapere nulla da loro,sto cercando di imparare tramite ricerche sul web come configurare per la massima sicurezza e una buona ampiezza di banda.(in passato ho subito attacchi da un hacker cinese).comunque lascio 80 perché sembra che funzioni tutto ugualmente.se per connessioni si intende a quanti siti internet si è collegati con un pc (o due in questo caso) di sicuro non arrivo neanche a 40.(paranoico della sicurezza?) grazie. buona domenica

  4. Per connessioni può intendersi qualunque operazione che coinvolge i pc della LAN ed Internet (sia in ingresso che in uscita). Quindi se navighi e basta, la soglia di 80 connessioni simultanee va più che bene, se usi client p2p mi sa che 80 è troppo poco (ma non è il tuo caso visto che non usi il port forwarding). E per finire, la sicurezza non è mai troppa 😛

  5. meno male che qualcuno è incoraggiante!solitamente leggo di persone che non si preoccupano molto, a loro dire :” io navigo e basta”.e poi si ritrovano il pc che va lentissimo e formattano una volta a settimana e poi: “io ho l’antivirus fa tutto lui”, magari fosse vero.grazie per le delucidazioni.studierò con molto interesse gli articoli pubblicati su questo blog ma arrivare a capire tutto sarà un’impresa,sarà l’eta? grazie. saluti

  6. Ciao, come sempre seguo assiduamente il blog, continuo a capirci poco (ovvio) però è estremamente interessante e ogni tanto qualcosa di nuovo imparo, se avessi tutto il giorno sicuramente sarebbe meglio 😀

    Scusa l’OT ma hai mai usato delle powerline? Io sono sempre dell’idee che il cavo è meglio di tutto, soprattutto del wifi, ma senza dover cablare una casa e farci tutte le tracce (!!!), se è possibile usarle, queste powerline fanno sicuramente un gran lavoro!!! Ne hai testata qualcuna? A breve dovrei avere un kit di netgear xavb5001, spero riescano a funzionare e darmi banda sufficiente almeno per l’adsl ma dovrò fare dei veri test di trasferimento file, ti terrò informato, magari interessa anche a qualcun’altro!!!

  7. Ciao Stefano, grazie per l’assidua frequentazione del mio blog 😀
    Purtroppo non ho mai utilizzato le powerline, ma su un punto sono daccordo con te, ovvero che le reti cablate sono molto più affidabili e sicure delle reti wireless. Proprio per questo motivo, quando il badget lo consente, tendo ad utilizzare la prima tecnologia anzichè la seconda.
    Resto in attesa dei risultati che otterrai durante i tuoi “esperimenti”.
    Buona giornata.

Lascia un commento