Tra Ottobre 2011 e Gennaio 2012 presso il Politecnico di Milano ho avuto modo di studiare finalmente un po’ i fondamenti delle reti di telecomunicazioni e Internet (Ethernet, IP, TCP, etc…). Durante il corso mi sono accorto che i libri erano diversi e un po’ tutti incompleti (soprattutto per la seconda parte del corso), quindi alla fine ho deciso di preparare dei miei appunti “fatti come si deve”, dai quali è nata una sorta di dispensa.
Visto che ho svolto molto lavoro e penso possa tornare utile anche ad altri, ho pensato di pubblicarla qua, anche se è un po’ incompleta nelle sue ultime parti. Spero di trovare il tempo di estenderla un po’!

Potete trovarla qua


(Dato che alcune persone me l’hanno chiesto mi sembra utile ripetere qua parte del “trucco” che avevo utilizzato per il bonding.)

Può capitarci spesso questa situazione: abbiamo il nostro sistema Linux collegato ad internet normalmente e con una VPN aperta. La route di default di sistema punta al gateway “normale” verso internet.

Diciamo che abbiamo quindi l’interfaccia TAP verso la nostra vpn ed è tutto configurato sul server della vpn per nattare il traffico in uscita cioè possiamo impostare, se vogliamo, il server della VPN come gateway di default.
Vogliamo però uscire su internet normalmente e utilizzare la vpn solo per alcune applicazioni.

Come fare a far uscire sulla vpn solo il traffico di una specifica applicazione?

Per riconoscere i pacchetti in uscita da un determinato processo ci servirebbe la funzionalità di mark by pid che però, purtroppo, non è più supportata in iptables da diversi anni (io mi sto attualmente occupando di re-implementarla). Fortunatamente possiamo sfruttare un workaround sfruttando i gruppi.

Iniziamo con il creare un gruppo apposito per tutti i programmi che vogliamo far uscire sulla VPN:
addgroup vpn
A questo punto diciamo a iptables di marcare i pacchetti in uscita dal sistema con un “mark” specifico. I mark di iptables potete immaginarli come delle etichette che vengono messe su tutti i pacchetti che soddisfano i nostri target. Useremo queste etichette per riconoscere i pacchetti speciali e utilizzare il routing corretto.
iptables -t mangle -A OUTPUT -m owner --gid-owner vpn -j MARK --set-mark 42
Il marcatore scelto (in questo caso 42) è del tutto arbitrario.
In questo modo abbiamo “etichettato” tutti i pacchetti in uscita da processi con GID (Group ID) pari a quello del gruppo vpn.

Ora possiamo procedere a definire una tabella di routing alternativa a quella di default. Non tutti sanno infatti che su Linux non esiste un’unica tabella di routing, ma ne possono essere definite diverse e poi utilizzarle a seconda del contesto.
ip rule add fwmark 42 table 42
In questo modo abbiamo “creato” la tabella di routing numero 42, che si attiverà per tutti i pacchetti con fwmark (cioè la nostra “etichettta”) pari a 42.

Passiamo quindi a aggiungere in questa tabella l’operazione di routing che dovrà essere svolta alternativa a quella standard:
ip route add default via 10.0.0.1 dev tap0 table 42
Tutto ciò supponendo che il server della nostra vpn sia 10.0.0.1 e l’interfaccia sia tap0.

Ci manca ancora una cosa però. A causa del workaround che abbiamo scelto i pacchetti in uscita avranno ancora come sorgente l’ip dell’interfaccia utilizzata per il routing di default. Per questo motivo dobbiamo sostituirlo con il nostro indirizzo della vpn:
iptables -t nat -A POSTROUTING -m mark --mark 42 -j SNAT --to-source 10.0.0.2
(Supponendo che l’ip del nostro client della vpn sia 10.0.0.2)
In questo modo guardiamo tutti i pacchetti con l’etichetta 42 e mettiamo a posto l’indirizzo sorgente.

Ora abbiamo tutto pronto. Come facciamo però a fare in modo che un processo utilizzi il GID (Group ID) che abbiamo scelto per la regola?
Su Linux è possibile lanciare un programma con un GID specifico utilizzando il comando sg (set group):
sg vpn -c "programma_che_fa_uso_della_rete"
Se l’utente con cui avviate sg non è parte del gruppo vpn, dovrete lanciare il comando da root. Per aggiungere il vostro utente al gruppo vpn:
adduser vostro_utente vpn
Come ultima nota vi ricordo che quando lanciate un programma in questo modo, anche le richieste DNS viaggeranno all’interno della VPN, assicuratevi quindi di utilizzare come server DNS dei server raggiungibili sia dalla vpn che da fuori! In alternativa inserite due server DNS in /etc/resolv.conf per gestire entrambi i casi separatamente.


Per tutti gli appassionati, ho creato sul mio canale youtube una playlist con tutti i video girati in Giappone negli ultimi anni: http://www.youtube.com/playlist?list=PL5A4B2AAFE8E49FFF&feature=plcp
Buona visione!


P.S: Scusatemi se non sono stato molto preciso in alcuni dettagli ma non sono proprio espertissimo, eventualmente mandatemi un feedback che aggiusto l’articolo.

Gli indirizzi IPv4 sono scarsi. Agli albori di internet 2^32 indirizzi possibili sembravano una infinità. Ad oggi la ICANN (la società no-profit che si occupa di gestire indirizzi e regole ufficiali di Internet) ha esaurito tutti i “blocchi” di indirizzi IP assegnabili alle autorità “regionali” delle varie zone del pianeta. Questo ed altri motivi hanno condotto alla creazione di un nuovo standard, IPv6, che permette l’utilizzo di 2^128 indirizzi, che per svariati motivi sono stati calcolati come sufficienti per parecchio tempo.
Il processo di migrazione, già iniziato ufficialmente nel 2008, proseguirà per alcuni anni probabilmente e già da tanti anni si utilizzano due tecniche per ovviare al problema che alcune persone ritengono comode, ma io voglio mostrarvi quanto siano brutte, intefficenti e contro gli standard.

Già dagli anni 90′ però molte persone si erano accorte di questo problema ed è stato inventato il NAT (Network Address Translation).

Il NAT puro consiste nella semplice traduzione di indirizzi IPv4 da una classe di indirizzi privati a una classe di indirizzi pubblici e viceversa.
Supponiamo ad esempio di avere un gateway/router con due interfacce: una verso Internet e una verso una rete locale LAN che utilizza indirizzi IPv4 privati. Supponiamo di avere 10 computer nella LAN e 10 indirizzi IP disponibili sul router. Il NAT ci permette di fare un assegnamento IP Pubblico <-> IP privato. Quindi modificando la configurazione del router (e non dei computer) possiamo cambiare gli indirizzi pubblici di ciascun computer.
Questo può essere utile in qualche caso, ad esempio se abbiamo molti computer, pochi dei quali sono però accesi contemporaneamente. Allora possiamo tenere meno indirizzi IP pubblici rispetto al numero di computer nella LAN e utilizzare gli indirizzi a rotazione. Utile ma neanche tanto.

Quello che oramai da anni e anni va invece molto più di moda è il NAPT (Network Address and Port  Translation).

Il NAPT funziona in questo modo: supponiamo di avere una rete sempre con un router centrale che da un lato ha Internet e dall’altro una rete locale. Supponiamo adesso di avere un solo IP pubblico sul router e 10 computer nella rete locale. Come facciamo a far uscire i 10 computer su internet? Ammettiamo che ciascun computer vuole inviare/ricevere pacchetti TCP e UDP. Ciascun pacchetto TCP e UDP è caratterizzato da due numeri di “porta”, una porta sorgente ed una porta destinazione. La porta sorgente è un identificatore per capire da quale applicazione della macchina che invia il pacchetto si è originata la connessione, mentre la porta destinazione identifica il processo da contattare sulla macchina di destinazione, che provvederà a mandare le risposte alla porta sorgente del mittente.
Per riuscire a far funzionare tutto, il NAPT guarda la porta sorgente del pacchetto TCP che vuole instaurare la connessione verso un host di Internet e controlla le porte sorgenti libere relative all’indirizzo IP pubblico che ha a disposizione. Il router sceglie quindi una porta sorgente libera per il suo ip pubblico e in una tabella si segna: “il computer della rete locale con indirizzo ip privato x.y.z.w ha stabilito una connessione verso un host remoto e tutti i pacchetti con porta sorgente X che mi arrivano da lui devo sostituirli con la mia porta sorgente Y”. Ovviamente questo procedimento verrà fatto anche al contrario quando il router riceverà dei pacchetti di risposta. In questo modo l’accrocchio funziona e si riesce a utilizzare un solo indirizzo IPv4 per far collegare molti host in rete.
Il NAPT può anche essere effettuato mettendo più di un indirizzo IP sul router che utilizzamo, di modo da aumentare il numero di connessioni contemporanee, come vedremo dopo.

Sebbene questo sistema permetta in un certo senso di risolvere il problema della scarsità di indirizzi IPv4, molti nella comunità di Internet lo considerano un vero e proprio abominio. Ecco alcune delle obiezioni:

8 Motivi per cui il NAPT non andrebbe utilizzato:

  1. NAPT viola la più importante regola di stratificazione dei protocolli, secondo la quale un protocollo di livello k non dovrebbe fare nessuna assunzione riguardo a protocolli di livello k+1. Un router normalmente dovrebbe solo prendere i pacchetti IP che arrivano ed instradarli, invece con il NAPT deve anche andare a controllare il carico del pacchetto IP per verificare il numero di porta, cosa che non dovrebbe fare per le regole sulla stratificazione dei protocolli. Questo causa inoltre overhead non previsto su un apparato che dovrebbe solo instradare e invece deve iniziare anche a tenere traccia di tutte le connessioni che lo attraversano
  2. NAPT viola il modello gerarchico di IP, che afferma che ogni macchina collegata in rete è identificata in modo univoco a livello mondiale da un indirizzo IP. In certi casi questo può essere un vantaggio per il nostro anonimato, ma se stiamo parlando di rintracciabilità non è certamente una garanzia.
  3. I processi su Internet non sono obbligati ad utilizzare TCP e UDP. Se un utente dietro ad una NAT decide di utilizzare un diverso protocollo di livello 4 non potrà funzionare, perchè il NAPT si basa sull’idea di controllare i numeri di porta, che in alcuni protocolli di livello 4 potrebbero non esistere. ICMP, il protocollo per il controllo del funzionamento di IP e per la diagnostica di rete, non utilizza numeri di porta ed è stato necessario implementare nei router che fanno il NAPT dei particolari workaround per permettere di inviare e ricevere i pacchetti correttamente. Questo ovviamente è tutto altro carico sulle spalle del router. Non dimentichiamoci che ogni volta che aggiungiamo qualcosa da fare ai router, aumenta il carico di lavoro per ogni pacchetto e le linee potrebbero subire leggeri ritardi che aumentano la frequenza di congestioni. Questo potrebbe richiedere hardware più potente e quindi costi più alti! È un ragionamento tirato abbastanza per gli estremi, ma se il traffico è molto elevato questo è un overhead che pesa.
  4. Il numero di connessioni contemporanee diminuisce. Poichè il router del NAPT deve allocare una delle sue porte sorgente per ciascuna connessione, essendo le porte utilizzabili 2^16 (in realtà le prime 4096 sono riservate ad usi speciali), non possiamo avere più di 61440 connessioni contemporanee per ogni indirizzo IP pubblico utilizzato dal router. Possono sembrare una valanga ma se usiamo un solo ip per la rete di una azienda o una università e magari qualcuno inizia a fare port-scanning o altre brutte cose che consumano un sacco di connessioni, il router satura subito le porte libere. Se abbiamo 614 computer dietro il nat, ciascuno potrà fare circa 100 connessioni contemporanee, dopo di che il NAPT non ha più numeri di porta liberi. Allora dobbiamo tenerci un pool di indirizzi IP al posto di uno unico… Ma a questo punto aveva veramente senso fare il NAT se avevamo degli indirizzi? Se parliamo della rete di un ateneo sì, ma se parliamo di piccoli uffici forse no.
  5. NAPT trasforma Internet da una rete ad assenza di connessione, in un tipo di rete orientata alle connessioni, perchè il dispositivo NAPT deve conservare le informazioni relative ad ogni connessione che lo attraversa. Se un dispositivo NAPT si blocca e la sua tabella di mappatura si perde, tutte le sue connessioni TCP/UDP verranno distrutte. In assenza di NAPT, i guasti ai router non hanno effetto su TCP/UDP, perchè il processo di ritrasmissione si attiva dopo il timeout di alcuni secondi. State scaricando un file e qualcuno riavvia il router che effettua il NAPT per manutenzione? La connessione verrà persa perché il router dopo il riavvio non è in grado di effettuare di nuovo le traduzioni di porta e né il mittente né il destinatario si accorgeranno del problema, la connessione resta in uno stato di zombie… Con un normale router senza NAPT e una connessione TCP si sarebbe notato solo un lag di pochi secondi (il tempo di riavvio del router).
  6. Solitamente ogni host collegato su internet può effettuare delle connessioni a dei server, oppure esporre dei propri servizi alla rete e permettere ad altri di collegarvisi. Purtroppo con l’introduzione del NAPT, se ad esempio nella rete locale ci sono due host con server web sulla porta 80, non è possibile esporre entrambi quei servizi sullo stesso indirizzo sulla stessa porta 80, quindi l’unica soluzione possibile (quando viene manualmente abilitata con il così detto Port Forwarding), è di assegnare due porte distinte dell’indirizzo pubblico ai due servizi dietro al NAPT, quindi ad esempio la porta 80 per uno dei due server web e la porta 81 per l’altro. Così facendo ovviamente il servizi che i vari host della rete locale possono esporre si riduce notevolemente. Se poi teniamo conto che gli stessi numeri di porta devono anche essere usati come porte sorgenti per le connessioni in uscita, la situazione è sempre peggiore. (Anche) per colpa del NAPT, Internet sta diventando sempre più una rete quasi esclusivamente per “scaricare” contenuti, questo sarà un problema più “filosofico” che tecnico, ma secondo me il bello di Internet, fin dai primi giorni in cui esiste, è proprio la possibilità per chiunque di esporre un suo servizio a tutti, in qualunque parte del mondo, senza dover dipendere obbligatoriamente da terze parti per farne “hosting”.
  7. Molti protocolli a livello applicativo, tra cui DCC e il notissimo FTP (in modalità attiva) fanno uso degli indirizzi IP degli host da cui si originano le connessioni all’interno dei messaggi scambiati a livello applicativo per avvertire il server a cui si collegano di inviare i dati da scaricare su una certa porta del client. Il NAPT non sa nulla di tutto questo e il risultato è che questi protocolli non sono più in grado di funzionare perché i server FTP tentano di inviare i dati a porte sul router NAPT che non è a conoscenza di questa operazione in corso e non permette il passaggio. Su alcuni router sono stati implementati dei meccanismi per intercettare il traffico a livello applicativo di questi protocolli e sbloccare le porte in ingresso per mettergli di funzionare. Questo è ancora più grave del primo punto perché con questo problema il router non deve solo andare a vedere il livello protocollare 4, ma addirittura anche i dati sul livello 7. Questo genera un overhead esagerato sulle operazioni di cui deve tenere traccia il povero router. Se questo non vi basta ancora, forse dovreste leggere dei magheggi che si sono dovuti inventare i realizzatori di IPsec per riuscire a farlo funzionare con il NAPT. IPsec infatti si basa sull’idea di “firmare” o cifrare il contenuto di pacchetti IP in modo da renderli sicuri e con sorgente affidabile. Per raggiungere questo scopo viene preso tutto il contenuto del pacchetto IP e firmato digitalmente ad esempio. Peccato che con il NAPT dei campi che dovrebbero essere fissi (aka porte TCP e/o UDP) diventano mutabili e quindi la firma non sarà più valida. Per poi non parlare dei pacchetti cifrati con IPsec, che ovviamente non potranno normalmente varcare il NAPT dato che non c’è modo di leggerli per fare la traduzione di porte.
  8. Il NAPT non permette di mantenere connessioni aperte in stato idle. Spesso può capitare di dover tenere una connessione aperta dove non passa neanche un bit per ore o settimane. TCP supporta questa cosa senza problemi ma il NAPT avendo pochi numeri di porta sorgente a disposizione non può permettersi di “sprecarli” per connessioni che non fanno nulla, quindi quando non viene rilevata attività per un po’ di tempo in molte implementazioni di NAPT si è obbligati a cancellare dalla tabella del NAPT la connessione. La cosa peggiore di questa cosa è che (in alcune implementazioni) i due host credono di essere ancora collegati tra loro, perché il NAPT non avvisa nè mittente nè destinatario che ha cancellato la riga nella tabella, quindi il client che ha aperto la connessione non vedrà nessun dato arrivargli anche se il server ha tentato di inviarli senza ricevere risposta. Invece una connessione TCP sopra IP inattiva, senza un NAT di mezzo, può resistere a qualunque problema di rete. Possiamo spegnere router, cambiare linee di collegamento, cambiare instradamento per arrivare il router, possiamo mettere in standby l’host, tagliare le fibre ottiche nell’atlantico e ricollegarci via saltellite. Possiamo fare quel cavolo che ci pare, quando torneremo nella nostra connessione, se gli indirizzi IP degli endpoint non sono cambiati saremo ancora collegati e potremo ancora mandare dati nella stessa connessione, tutto grazie a TCP/IP. Viene spontaneo chiedersi: come si fa allora con il NAT a tenere aperte connessioni persistenti? Ci sono tanti metodi. Quello più ovvio è di inviare dei messaggi di ping, e relative risposte (pong) a livello applicativo “ogni tanto” (come fa IRC, websocket etc etc…). In alternativa è possibile utilizzare un workaround (TCP-Keepalive) per inviare dei pacchetti TCP vuoti ogni tanto all’interno della connessione, come segno di “attività” e per evitare che il NAPT cancelli la regola di traduzione.

Il mito del NAT come firewall

Non dobbiamo nascondere che molto spesso, il NAPT, per come funziona, viene sfruttato impropriamente come meccanismo di firewalling. Ad esempio immaginiamo una rete di una università. Vogliamo evitare che la gente accenda server SMTP per iniziare attività di spamming o altre cose simili, come evitare che gente possa esporre servizi su internet ma possa allo stesso tempo collegarsi? Beh facciamo un bel NAPT. Questa è una porcheria bella e buona, specialmente quando viene fatta su reti relativamente piccole dove ci possono essere abbastanza indirizzi pubblici per tutti senza problemi. Il NAPT non serve a quello, per bloccare le connessioni in ingresso si possono utilizzare regole di firewalling sui router per non permettere a host di Internet di stabilire connessioni verso la rete locale con una cosa del genere con iptables:

echo 1 > /proc/sys/net/ipv4/ip_forward

iptables -P FORWARD DROP

iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT #Permettiamo a tutto di uscire dalla interfaccia della rete locale ad internet

iptables -A FORWARD -i eth0 -o eth1 -m state –state RELATED,ESTABLISHED -j ACCEPT

Con queste 4 righe in realtà comunque il router deve andare a tenere conto di alcuni dettagli sul livello 4, ma è sempre meglio di usare il NAPT, per gli altri motivi sopra citati.

Alcune persone provano una falsa sensazione di sicurezza stando dietro al proprio NAPT, pensando di essere al sicuro. In realtà si sbagliano di grosso.

  • Su alcuni router “casalinghi” molto economici, dove viene implementato il NAPT, può succedere per vari motivi che quando arriva un pacchetto da internet, con IP sorgente spoofato (modificato da un attaccante) per essere nella classe degli indirizzi privati (ad esempio arriva un pacchetto UDP con sorgente 192.168.0.1), il router non si interessa del fatto che il pacchetto arriva dall’interfaccia “sbagliata” (cioè quella verso Internet e non quella della rete locale), ma invece lo guarda e lo instrada nella rete locale. Ovviamente poi le risposte non torneranno indietro all’attaccante, ma con questo metodo si può già iniziare a tentare qualche attacco. Se non sbaglio diversi anni fa con questo metodo si riusciva ad attaccare un sistema di RPC su Windows e quindi con una serie di meccanismi ad ottenere anche delle risposte e quindi attaccare completamente la macchina bucando il NAT.
  • Su altri router, vengono abilitati dei moduli particolari (presenti anche come moduli di iptables per il kernel Linux) per permettere a FTP, DCC e altri protcolli citati prima di funzionare. Questo è certamente un bene ma espone anche dei problemi di sicurezza perché con attacchi particolari è possibile sfruttuare questi meccanismi per aprire arbitrariamente delle porte del NAPT verso una porta di un host della rete locale. Ad esempio preparando una particolare pagina web e facendola visitare ad un utente ignaro, è possibile instaurare una finta connessione IRC sopra HTTP e quindi fare una richiesta DCC e sbloccare una porta in ingresso. Questo metodo viene mostrato tra altre cose in questo video.