Alcune delle variabili in /proc/sys/net sono particolarmente importanti dal nostro punto di vista in quanto ci consentono di proteggere il kernel da diversi tipi di attacchi.
Di base, la directory che più ci interessa di /proc/sys/net è sicuramente ipv4.
In quest directory, dovreste trovare alcuni file tra cui:
Con una cinquantina di byte, vi manderebbe contro circa 16 milioni di risposte al ping... (fortunatamente, la maggior parte dei computer in rete non rispondono a ping di broadcast).
Questa variabile viene principalmente utilizzata all'interno di net/ipv4/icmp.c:icmp_rcv.
Questa macchina si doveva quindi prodigare per ricomporre il puzzle riordinando e riunendo i pacchetti nel corretto ordine, sovraccaricando notevolmente la cpu arrivando persino a bloccare la macchina.
Per rimediare, in linux si utilizzano proprio i file ipfrag_*. In pratica, si stabiliscono dei limiti oltrepassati i quali linux si ``arrenderà'' nel tentare di riordinare i pacchetti, evitando di bloccarsi su questo compito. I valori di default di tali limiti sono ben tarati, anche se potrebbe rendersi necessario abbassarli, a seconda della tipologia di macchina utilizzata e a secondo dell'attacco cui si è soggetti.
Capita raramente poi, che per migliorare le prestazioni di alcuni servizi, come per esempio NFS, tali limiti debbano essere alzati.
Questi limiti sono utilizzati principalmente in net/ipv4/ip_fragment.c:ip_defrag ed ip_evictor.
Facendo un paio di grossolani conti, considerando che esistono 65535 porte e che per ogni porta devono poter essere accettate più connessioni, è abbastanza evidente che il kernel di un qualsiasi sistema operativo non può permettersi di ricordarsi tutti i pacchetti di inizio delle connessioni ricevuti. In pratica, per ogni porta viene creata una coda di dimensioni molto piccole (si parla di numeri nell'ordine delle decine o centinaia). Quando questa coda è piena, la porta non può più accettare pacchetti. A peggiorare la situazione, le rfc indicano un timeout abbastanza alto (nell'ordine dei minuti) prima che il kernel possa buttare via questi pacchetti, svuotando la coda e dedicandosi ad altro. E' quindi abbastanza facile dimostrare che un attaccante, mandando pochi kilobyte di syn al secondo con un semplice modem 56k, può rendere inutilizzabile una porta di un qualsiasi server, senza nemmeno alzare il carico della cpu né saturare la banda.
Le soluzioni sono diverse, ma poche si sono rivelate veramente valide:
In questo modo, un syn flood andrebbe a colpire solo il firewall proteggendo molto efficacemente i server.
Firewall di questo tipo sono poi strutturati in modo da resistere molto bene a dei syn flood anche con un numero molto alto di syn al secondo, utilizzando tabelle più grosse di quanto si possa permettere un normale server e creando delle infrastrutture dinamiche in grado di gestire tali situazioni.
Il syn però, deve continuare ad essere difficilmente indovinabile ed aumentare di pacchetto in pacchetto (non avrebbe ragione di esistere altrimenti, e sono condizioni imposte dall'rfc 793). Vengono quindi normalmente utilizzate delle funzioni one-way o degli hash che rispecchino queste caratteristiche, e l'informazione inviata si riduce normalmente in un ``connessione inizializzata correttamente'' (per maggiori informazioni, potete vedere il file net/ipv4/tcp_ipv4.c, in particolare la funzione tcp_v4_conn_request, oppure il file drivers/char/random.c funzione secure_tcp_syn_cookie per sapere come un syn cookie viene calcolato). Il problema è che è stato dimostrato che in particolari condizioni con particolari versioni del kernel linux era possibile indovinare questi syn e fare spoofing delle connessioni tcp. Sebbene attacchi di questo tipo siano stati raramente (se mai) utilizzati (non mi riferisco allo spoofing in generale, pratica largamente utilizzata, ma all'indovinare i syn grazie a questo bug nella creazione dei syn cookies), è bene abilitare i syn cookies solo su kernel relativamente recenti (dal 2.4.6 in su funzionano sicuramente correttamente), o in particolari condizioni (quando si è sotto attacco, per esempio).
Ultima cosa da dire a proposito dei syn cookies è che questi vengono considerati da alcuni violare lo standard del tcp (ci sono state diverse discussioni in proposito, si veda per esempio il sito http://cr.yp.to/syncookies.html, di Dan Bernstein) e possono quindi introdurre dei problemi. I syn cookies, se abilitati, verranno quindi utilizzati da linux soltanto nel caso in cui la famosa coda si riempia.
Rimane soltanto da aggiungere una cosa: come si fa a rendersi conto di essere sotto syn flood? Beh, con i syn cookies disabilitati, potreste dare un comando come:
# netstat -npla |grep SYN_RECV
Normalmente, dovreste vedere non più di 1-2 connessioni provenienti da
indirizzi ip diversi. Se ne vedete più di una trentina, allora è molto
probabile che vi troviate sotto syn flood. Per esperienza, posso dirvi che con
un kernel 2.2 senza i syn cookies abilitati con circa 110-120 connessioni in
SYN_RECV la porta attaccata diventava irraggiungibile.
Per avere una ulteriore conferma, potreste infine verificare con tcpdump... se arrivano dei nuovi syn da uno stesso ip prima ancora che voi abbiate risposto con un altro syn-ack o dopo aver temporaneamente bloccato l'ip o il demone responsabile della porta, allora siete sotto syn-flood. Anche questa prova però non può essere considerata definitiva: il syn-flood viene considerato un blind attack, ovvero un attacco che non ha bisogno di ricevere le risposte per poter essere effettuato, per cui è estremamente semplice utilizzare dei ``mittenti'' falsificati nei pacchetti (ed utilizzare quindi ip multipli e differenti). L'ip che vedete in netstat o tcpdump potrebbe quindi essere quello di qualcuno che nulla ha a che vedere con l'attacco. L'unica condizione perchè un ip possa essere utilizzato è infatti che questo risulti irraggiungibile dalla vostra macchina (altrimenti manderebbe un reset dopo il vostro syn-ack). Infine, nel caso in cui il kernel si trovi a dover far uso dei syn cookies, dovreste vedere dei messaggi nei file di log.
Diamo quindi un'occhiata alla directory all (o eth0, o lo, o...):