Network Address Translation: an abomination and horror

IPv4 addresses are not so many. When Internet started a long time ago, 2^32 addresses (more than 4 billion) seemed to be a lot. Today the ICANN (the USA company which administrate addresses and “numbers” of the Internet) had already completly assigned all IPv4 address blocks to all “regional” authorities of several parts of the planet.
For this and other reasons we are now inside a migration-process to the new IPv6 protocol, which provide 128-bit addresses. A lot of estimations shown that this new kind of addresses will be enough for a lot of time, even we will use them in a very “bad-way”.
The migration-process already started officially in 2008 and will go ahead for several years maybe. We are already using a lot of migration-techniques on several networks (which provide both IPv4 and IPv6 connectivity).

Actually this lack of addresses was already predicted and known during the 90′ and the NAT (Network Address Translation) was created on purpose of “temporarily” solve the problem. This “temporarily” has been very long, because we still use it today and more than ever.

But, first of all, let me clarify some definitions. Plain “NAT” means the translation of a subnet of public addresses to a subnet of private addresses and vice-versa. This means that we do a one-to-one association. For each public address we associate a private address.
For example, let’s suppose that we have a router with two interfaces, one to the Internet and one to a local LAN network which uses IPv4 addresses.
Let’s also suppose we have 10 computers on the LAN and 10 public IP address available for Internet use. The plain NAT means that we could use 10 private addesses on the computers on the LAN and program the router in a way that, for each incoming IPv4 packet it will change the destination IP address with a private address and vice-versa, based on a association table. This permits to esely change public IP addresses of all machines (for example when we change ISP provider). This is actually a problem but there are serveral solution instead of duing a NAT.

But this “plain NAT” it’s quite never used today, what I want to talk about is the NAPT (Network Address and Port Translation) , which is often called just “NAT”, giving origin to this ambiguity.

The NAPT works in this way: let’s suppose we have again a local network and a router as before. Now let’s suppose we just have one public IP address and 10 computers on the local network. How can we connect all computers to the Internet? So first let’s do a step back and let’s see in a very easy way how a connection works.
Every computer wants to send/receive TCP and UDP packets. Each TCP and UDP packets it’s characterized by two “port” numbers, a source port and a destination port. The source port is an identifier to understand from which applicaton of the host from which the packet came, while the destination port is an identifier of the application to connect on the destination host. The destination host will swap destination and source port numbers in order to send back responses.

So, we will use private IP addresses as before on the local network and we will keep the public IP address on the router. The router will employ the NAPT, so when an initial packet came from the local network the router will check the source port of the TCP packet and it will check the free source port numbers on its address. The router will then choose a free source port for its address and will note on a table: “the local network host with address x.y.z.w has established a connection to a remote host k.h.j.l and all packets coming from x.y.z.w  with source port X must be rewritten with my source port Y and my public address as source”. In a similar way it will read on reverse-way the previous route when a packet comes from the Internet. When a packet comes from the Internet, the router will check if the destination address is its public IP, if so it will then check the destination port and see if that port is used for some NAPT mapping. If the port is part of a NAPT mapping rule, it will find the row in the table, change the destination port y with the previously changed port X and the destination address with the private address x.y.z.w of the LAN host.All this system could be also deployed using more than one public address on the router, in order to increase the number of parallel connections (we will see that later).

Even if this system allow you to “solve” the IPv4 exhaustion problem, a lot of network administrators and people in the Internet commuity think that this is really an abomination and horror for TCP/IP network protocol suite. Here I write some of my thoughts about this:

8 Reasons for which NAPT (NAT) should not be used:

  1. NAPT goes against the most important rule about protocol layering, which says that a protocol of level k should not do any assumption about protocols of level k+1. A router usually should just take IP packets coming and route them using a route table. Instead of this, using NAPT,  the router has also to check the IP packet payload (the TCP/UDP protocol header) in order to check port numbers. This should not be done according to the layering rule and it also cause a not expected overhead on a embedded device which should just forward packets but also starts to trace all TCP/UDP connections going over.
  2. NAPT is against the hierarchic model of IP, which says that any host connected to the Internet is identified globally in unique way by an IP address. In some cases this could be a good thing for our anonymity, but surely not a warranty that we could not be traced anyway in serveral other ways.
  3. Internet application should not be obliged to use TCP and UDP. If a user behing a NAT decides to use a different (layer 4) transport protocol, he will not be able to use it, because NAPT works only on TCP and UDP checking port numbers. On some transport protocol there are no port numbers. ICMP for example, the control protocol for IP workings and network diagnostics, does not use port numbers but it’s necessary anyway. For this reason NAPT routers employ several workarounds in order to send/receive packets correctly (whatching other numbers inside the ICMP packets). This is obviously again other “hard” work for the router. We should not forget that each time that we add something to do on the router side, the workload for each packet increase and some network lines could slowly increase latency and congestions.
    This means that manufacturers may need powerful hardware and so high costs (and energy consumption). I understand that this is a bit exaggerated view of the probolem, but if we have really a lot of traffic (and not just 10 computers),  we should start to consider also this problems.
  4. The parallel number of connections decrease. This is because the NAPT router should use one of its free source ports for each connection, since the available ports are 2^16 (actually the first 4096 should not be used for NAPT), we can’t have mort than 65535 connections for each public IP address used by the NAPT router. You could think that it’s a big number, but if we use just one IP address for the network of a small company or a university campus (and maybe someone is doing port-scanning or other bad things), the router will exhaust port numbers and the network will not accept new connections. If we have 100 computers behind the NAPT, each one could do around 655 connections. Try to open a p2p software on some of them and see what happens.
    So for this reasons, manly on corporate networks, we start to use not just one IP address, but a pool of IP addresses, in order to have more parallel connections available. So at this point, was it really necessary to use NAPT if we had other public addresses? Maybe for a university campus the answer would be “yes”, but for a small office could be “no”.
  5. NAPT transform Internet from a connectionless network, to a connection-oriented network. This is because the NAPT device must keep track of all informations related to a connection going over it. If a NAPT router goes down and its NAPT mapping table goes away, all TCP/UDP/ICMP connection will not be able to continue when the router cames back online. Instead, without NAPT, when a router goes down and then up, the endpoints using a TCP connection will see just a short lag (router’s reboot time) in communication. Also UDP has problems, let’s say for example that we are doing a VoIP call when someone reboots the router. VoIP usually works over RTP protocol (which runs over UDP). If we are using a norma router we will just have a short absence of communication, then the audio will come back. Instead, using the NAPT, the VoIP call will be lost and we should call back again. I know, it’s not a so common scenario, but it shows how much NAPT is evil.
  6. Usually each host connected to the Internet is able to connect to some servers or expose some services on the network, so that other people could connect. Sadly, using the NAPT we can’t get incoming connections to our host. You could say that it’s possible to configure the NAPT router to forward some ports. So let’s say I have two hosts on the LAN who want to expose a HTTP webserver (TCP port 80). We just have 1 public IP address and we can use the TCP port 80 just one time, so we could in any case provide access to just one of the two hosts, the other one should use a non-standard port. I think that (also) because of the NAPT, Internet is becoming everyday more a “download-only” network. This is more a philosophical problem instead of a technical one, but I think that the good side of the Internet (since its first days of existance) is the possibility to expose to anyone a self-hosted service, in any point on the world, without the neet to ask to someone else to host it.
  7. A lot of application-level protocols (DCC and FTP in active mode for example) use IP addresses of hosts inside application-level messages (to notice the server where to send some data). The NAPT doesn’t know anything about this and the result is that these protocols does not works anymore today. On some routers there are some deep packet inspection sytems which are able to recognize this messages and alter them while opening ports in the NAPT mapping (a lot of NAPT routers do that for FTP active mode for example). I think this is even worse of what we were talking before. This is because now the router does not just have to check for layer-4 messages, but even layer-7 messages! Rebuilding TCP packets to search for a byte sequence it’s not a fast/easy thing to do for a router, it adds a lot of overhead. If you aren’t still convinced about this problem maybe you should read the workarounds that IPsec creators made for using IPsec over NAPT. IPsec can sign or crypt the payload of IP packets in order to make them secure and with reliable source. IPsec, in order to add this feature, sign all the IP payload. This is a problem because some fields which should be fixed (port numbers) are changed by the NAPT and the sign check fail. Also, if the packet it’s encrypted the NAPT can’t read port numbers!
  8. NAPT doesn’t let you able to keep open idle connections. Often could be useful to keep an open connection where any data comes for hours or weeks (let’s think about today populars websockets or IMAP with IDLE command). TCP/IP supports this feature without problems since the connection state is keep just by endpoints. But the NAPT, since it has few free port numbers to use, can’t just keep them allocated forever (for connections bad-closed and DoS attacks to the NAPT). So, for these reasons the NAPT closes some connections when are not “active” and reallocate port numbers for new connections. The worst thing about this is that (on some NAPT implementations), the two hosts does not recive any notification of this “disconnection” by the NAPT, so they still think to be connected but they aren’t, and they will discover that just when trying to send something to the other host.
    On the other hand, without NAPT, we could shutdown the router, change communication lines, change the way we connect to the router, put the host in standby, cut fiber optics cables in the Atlantic ocean and wait. We could do whatever we want, when we will be back online, if the addresses of endpoints are not changed, we are still “connected” to the other host and we are still able to send data on the same connection, that’s all thanks to TCP/IP.
    Someone could ask “so how can I keep open idle connections over NAPT?”, there are many answers, maybe the most popular is to use something like “ping/pong” messages like IRC does sometimes. Another answer could be to use a workaround called “TCP-Keepalive” which sends some empty TCP packets sometimes inside the connection in order to show to the NAPT that we are active and that it should not delete the mapping rule.

The NAT is not a firewall

A lot of people think that the NAPT, for how it works, it could be used (improperly) as a firewall technique. Let’s imagine, for example, a university campus network. We don’t want that students turn on SMTP servers in order to start spamming or other stuff like that. How could we prevent this? Some people say “let’s take up a NAT so they can just connect outside”. This could work but it’s not the purpose of NAPT and I consider a bad idea, in particular on small networks where we have public addresses for everyone. The purpose of NAPT is not that, to block incoming connections it’s possible to implement a stateful firewall on the router or a separate machine, in order to prevent LAN hosts to expose services to the Internet.
Let’s say an example of how to implement this on iptables:

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

iptables -P FORWARD DROP

iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT #We permit anything to go outside from our local network

iptables -A FORWARD -i eth0 -o eth1 -m conntrack –ctstate RELATED,ESTABLISHED -j ACCEPT #We accept just connection related or established

Actually using this setup, the firewall will anyway use level 4 informations and we have some similar problems as stated before, but it’s still better than using the NAPT, for the other reasons we said.

Some people says that NAPT protects them from network attacks. Really?

  • On some NAPT cheap routers can happen that, for several reasons, the WAN and LAN interface are actually the same physical card, so if you send a packet to the WAN interface, it will go inside the LAN.
  • On some routers are enabled some modules in order to gen FTP active mode and DCC protocols working (as we stated before). This is good but it also gives you some security issues. Using some special attack techniques it’s possibile to use this mechanism in oder to open an arbitrary port on the NAPT to an arbitrary host in the local network. For example using a special webpage with a java or flash application (see for example here)
  • Some local networks implement the UPnP protocol on the main router (using the so called “IGD” service). Using the IGD service, an host on the local network could ask to the router to add a port-mapping rule in oder to get incoming connections from outside. It turns out that some routers accept this kind of requests also from the WAN interface (see this paper)

Other bad things

Did you know? Some ISP providers started to give you private addresses instead of public ones. This is called Carrier-Grade NAT and it’s still bad because it again breaks the end-to-end connectivity.

[Linux] Catturare il traffico di rete di un singolo processo usando i namespace di rete

L’altro giorno dovevo controllare il traffico generato da un programma (Skype). La mia macchina ovviamente sputa fuori un sacco di dati in rete (firefox aperto con diverse tab con connessioni http, client di chat, lettori di feed).

L’approccio classico per questo tipo di cose è: apro tcpdump/wireshark, penso un po’ alle porte tcp/udp e indirizzi che mi aspetto grossomodo di vedere uscire dal programma e filtro su quello. Oppure avvio tutto senza filtri e spero nella valanga di roba che esce di beccare quello che mi interessa (tanti auguri quando avete molto traffico…). Oppure se proprio voglio sprecare risorse avvio una macchina virtuale (solo per questo? really?).

Un altro approccio è lanciare il programma interessato con un GID (creato appositamente per l’applicazione) diverso da quello normale e poi, utilizzando il modulo owner  (-m owner --gid) di iptables, identificare tutti i pacchetti di quel gruppo e con il target ULOG tirarci fuori un file pcap.

Sinceramente però avevo poca voglia di fare così e ho appena imparato ad usare i namespace di rete su Linux (thanks Max!), quindi ho provato un altro modo un po’ come “esercizio di stile” (cit.). Non prendetela troppo come una roba per final users, ma semmai per p0w3r u5erZ.

Su Linux sono stati introdotti, ormai da un po’, diversi namespace. In particolare per quanto riguarda la rete, abbiamo la possibilità di avviare un processo in un namespace di rete diverso da quello di default. In questo modo il processo non vedrà nessuna interfaccia, nessuna regola di routing, nessun indirizzo ip, nessuna regola di iptables. In pratica è come se, esclusivamente dal punto di vista della rete, il processo si trova in un sistema “nuovo”. Tra l’altro questo fatto coinvolge anche tutti i processi figli. Poi volendo ci sono anche i namespace PID, UID, mount, …, insomma usandoli tutti possiamo fare più o meno una macchina virtuale “leggera”, che gira sempre sopra lo stesso kernel.

Detto questo bisogna sapere che è anche possibile creare delle interfacce di rete “tunnel” tra un namespace di rete e l’altro.

Utilizzeremo un tool per “maneggiare” i namespace nel kernel Linux (basta avere una versione del kernel >=2.6.26). Il tool è “unshare” e dovreste trovarlo già installato all’interno della vostra distribuzione. Fa solitamente parte del pacchetto util-linux. Un tool molto simile (alternativo) che ha qualche funzionalità in più è “vspace” del pacchetto “util-vserver” (che però dovete installare quasi sicuramente a parte).

A questo punto possiamo aprire un processo bash all’interno di un nuovo namespace:
$ sudo unshare --net /bin/bash
sudo è necessario perché viene fatta una syscall (per la precisione la clone con flags=CLONE_VFORK|CLONE_NEWNET|SIGCHLD ) che richiede privilegi di superutente.

Ok, ora nella bash che abbiamo lanciato noteremo l’ assenza di interfaccie di rete (eccetto il loopback, che comunque mancherà di indirizzo ip):

$ ip link show
5: lo: mtu 16436 qdisc noop state DOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

Di regole di routing:

$ ip route show
$

E di regole di iptables

$ iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination


$ ip6tables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination

Possiamo per prima cosa assegnare un indirizzo (IPv4 e IPv6) all’interfaccia di loopback, che potrebbe servire per IPC tra processi:

$ ip addr add 127.0.0.1/8 dev lo
$ ip addr add ::1/128 dev lo
$ ip link set dev lo up

Adesso ci serve tirare su una comunicazione verso l’esterno, quindi utilizzeremo due interfacce di rete virtuali, che faranno da “ponte” tra il namespace che abbiamo creato e quello “globale” (quello “solito” insomma).

Quindi da un altro terminale fuori dal namespace che abbiamo creato, facciamo un:
$ sudo ip link add name antani0 type veth peer name antani1
Questo ci creerà nel namespace “globale” due interfacce: antani0 e antani1, “finte” ethernet, collegate tra di loro in un unico dominio di collisione. Ora abbiamo la possibilità di spostare una delle interfacce che abbiamo creato, all’interno del nuovo namespace.
Per identificare il namespace di rete che abbiamo creato, possiamo cercare nella lista dei processi il PID del nostro bash “speciale” e segnarcelo. A questo punto facendo:
$ sudo ip link set dev antani1 netns /proc/$PID_BASH/ns/net
Diremo di spostare l’interfaccia antani1 all’interno del namespace di rete utilizzato dal nostro processo bash “speciale”.

E ora è tutto semplice dato che abbiamo un collegamento con il mondo “esterno” al namespace. Possiamo mettere in bridge l’interfaccia con una fisica o fare un NAT. Mostrerò questa seconda soluzione (che è quella che ho provato io per poter fare degli esperimenti appunto con NAT e skype). Questo non significa che sia una buona idea fare un NAT.

Diamo un indirizzo all’interfaccia fuori dal namespace e diamo qualche comando per abilitare il NAT:
$ sudo ip addr add 172.16.0.1/24 dev antani0

$ sudo ip link set dev antani0 up

$ sudo su -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

$ sudo iptables -P FORWARD ACCEPT      # Per semplicità, se avete la policy drop aggiungete quelle due regole in più..

$ sudo iptables -t nat -A POSTROUTING -s 172.16.0.0/24 -j MASQUERADE
E dentro la nostra bash speciale, dove vedremo comparsa la nuova interfaccia, assegnamo un altro ip e impostiamo il gateway di default:
$ sudo ip addr add 172.16.0.2/24 dev antani1

$ sudo ip link set dev antani1 up

$ sudo ip route add default via 172.16.0.1 dev wlan0
A questo punto ci basta avviare fuori dal namespace tcpdump o wireshark in ascolto sull’interfaccia antani0 e lanciare dalla nostra bash “speciale” skype (o qualunque altro programma di cui vogliamo catturare il traffico).

In realtà se notate ho lasciato sottointeso un passaggio: skype e qualunque altro programma lancerete nel nuovo namespace utilizzerà sempre le solite informazioni per il DNS, quelle salvate in /etc/resolv.conf  e /etc/hosts. Queste informazioni risiedono sul filesystem e quindi non sono affette dal namespace di rete, saranno dunque uguali al namespace “globale”.
A me serviva però avere dei DNS diversi per skype, rispetto a quelli globali di sistema. D’altro canto non volevo cambiare quelli di sistema perché poi mi avrebbero rallentato la risoluzione nomi di tutti i programmi.

Fortunatamente c’è anche un modo per risolvere questo problema! Ed è grazie al namespace di mount!
Infatti oltre al namespace di rete potete abilitare anche il namespace di mount. Questo significa che quando lanciate un programma in un nuovo namespace di mount, vedrete tutti i mount “soliti”, però quelli nuovi che farete dall’interno del namespace saranno visibili solo a voi e non all’esterno.

Quindi rifacciamo la procedura di prima cambiando il primo comando in:
sudo unshare --net --mount /bin/bash
E avremo sia un nuovo namespace di rete che un nuovo namespace di mount.

Ma perché voglio usare il namespace di mount? Pochi sanno (e non lo sapevo neanche io) che è possibile montare un singolo file sopra un’altro già esistente, usando mount –bind. Montando un file sopra uno esistente, il risultato sarà che accedendo a quel file vedremo solo l’ultima “versione” montata.
Possiamo allora creare da qualche parte una versione sostituiva di /etc/resolv.conf, ad esempio in /tmp/, e scriverci dentro quel cavolo che ci pare, poi, dall’interno del nostro namespace di mount (e rete) faremo tipo:
mount --bind /tmp/resolv.conf /etc/resolv.conf
Ed è fatta! In questo modo abbiamo messo una versione “nuova” di /etc/resolv.conf sopra a quella vecchia, nascondendola, e questa modifica sarà visibile solo dall’interno del nostro bash speciale, dato che stiamo operando, come già detto, in un namespace di mount diverso. Fuori dal namespace di mount nuovo continueremo a vedere la vecchia versione del file. Ci serve farlo anche per /etc/host o /etc/nsswitch.conf (altro file interrogato per risolvere i DNS)? Basta ripetere il mount anche per quegli altri files!

Tra l’altro, se siete interessati, è possibile anche spostare una interfaccia di rete esistente, tipo eth0, sfruttando lo stesso comando visto prima per “spostare” le interfacce! Anche questo può tornare molto utile

Tutto questo non è fantastico?

Tra l’altro unendo queste cose con anche il namespace PID e user penso sia possibile creare una sandbox seria per skype. Se qualcuno si sta chiedendo perché sandboxare skype forse è meglio che vada a informarsi su cosa è successo un po’ di mesi fa quando una versione deoffuscata del programma è girata in rete… Oltre a questo resta il fatto che è un software proprietario con codice offuscato e che funziona in modo abbastanza strano. Farlo girare in una VM forse è esagerato (e anche scomodo), però con questi trucchetti si possono fare (a mio parere) cose molto interessanti, sia per sandboxare programmi che per fare test di networking vari.

In partenza, again!

Sono nuovamente in partenza, destinazione Kyoto. Settimana prossima tornerò in Giappone per fare 6 mesi di università presso la Doshisha University di Kyoto, in realtà mi troverò in un campus leggermente periferico rispetto a Kyoto, sarò a Kyotanabe.
Pubblicherò sicuramente qualche aggiornamento e soprattutto nuovi articoli di informatica!
A presto!

Appunti del corso “Reti di telecomunicazioni ed Internet”

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

Routing “ad-hoc” per alcuni programmi

(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.

Playlist su Youtube – Video in Giappone

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!

Network Address Translation: un abominio

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.

Iscriviti

Ricevi al tuo indirizzo email tutti i nuovi post del sito.