Ora si è appreso come selezionare i pacchetti che si vogliono manipolare. Per completare la propria regola è inoltre necessario specificare al kernel con precisione che cosa si vuole fare a questi pacchetti.
Se si vuole effettuare il Source NAT allora si deve cambiare l'indirizzo sorgente della connessione con qualcosa di differente. Questo però deve essere fatto nella catena POSTROUTING, appena prima che il pacchetto sia inviato. Questo è un dettaglio importante, perché solo così qualsiasi altra cosa nella Linux box (instradamento, filtraggio dei pacchetti) vedrà il pacchetto come invariato. Ciò significa inoltre che si potrà utilizzare l'opzione `-o' (interfaccia uscente).
Il Source NAT si specifica usando `-j SNAT', l'opzione `--to-source' permette di indicare un indirizzo o un intervallo di indirizzi IP e opzionalmente una o un intervallo di porte (però solo con i protocolli UDP e TCP).
## Cambia l'indirizzo sorgente in 1.2.3.4.
# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4
## Cambia l'indirizzo sorgente in 1.2.3.4, 1.2.3.5 oppure 1.2.3.6
# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4-1.2.3.6
## Cambia l'indirizzo sorgente in 1.2.3.4, porte 1-1023
# iptables -t nat -A POSTROUTING -p tcp -o eth0 -j SNAT --to 1.2.3.4:1-1023
Esiste un caso specializzato di Source NAT denominato mascheramento (masquerading): dovrebbe essere utilizzato solo se gli indirizzi IP sono assegnati dinamicamente, come ad esempio nel caso di connessione via modem (dial up), nel caso di indirizzi IP statici invece si usi il già citato SNAT.
Non è necessario con il mascheramento (masquerading) indicare esplicitamente l'indirizzo sorgente in quanto sarà utilizzato l'indirizzo dell'interfaccia da cui il pacchetto uscirà. Ancora più importante è il fatto che se il collegamento dovesse interrompersi, la connessione sarà dimenticata (sarebbe comunque persa), in questo modo non ci saranno grossi problemi quando la connessione sarà ristabilita, naturalmente con un nuovo indirizzo IP.
## Maschera qualsiasi cosa esca da ppp0.
# iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
Questo avviene nella catena PREROUTING, appena il pacchetto arriva; ciò significa che qualsiasi cosa nella Linux box (instradamento, filtraggio dei pacchetti) vedrà il pacchetto arrivato con il suo indirizzo di destinazione `reale'. Ciò permette di utilizzare l'opzione `-i' (interfaccia ingresso).
Destination NAT si specifica usando `-j DNAT', l'opzione `--to-destination' permette di specificare un indirizzo o un intervallo di indirizzi IP e opzionalmente una o un intervallo di porte (solo per i protocolli UDP e TCP).
## Cambia l'indirizzo di destinazione in 5.6.7.8
# iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 5.6.7.8
## Cambia l'indirizzo di destinazione in 5.6.7.8, 5.6.7.9 oppure 5.6.7.10.
# iptables -t nat -A PREROUTING -i eth0 -j DNAT --to 5.6.7.8-5.6.7.10
## Cambia l'indirizzo di destinazione del traffico web in 5.6.7.8, porta 8080.
# iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 \
-j DNAT --to 5.6.7.8:8080
Esiste un caso specializzato di Destination NAT chiamato redirection (redirezione), ed è semplicemente una comodità in più in quanto esattamente uguale al DNAT effettuato però esclusivamente sull'indirizzo associato all'interfaccia di ingresso.
## Invia i pacchetti diretti alla porta 80 verso il proxy (trasparente)
## squid
# iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 \
-j REDIRECT --to-port 3128
Si tenga presente che squid deve essere configurato in modo tale da sapere che deve agire come proxy trasparente!
Ci sono alcune sottigliezze nel NAT con cui la maggior parte delle persone non avrà mai a che fare. Queste sono documentate qui di seguito per i curiosi.
Se è dato un intervallo di indirizzi IP, l'indirizzo IP da usare è scelto in base all'IP correntemente meno utilizzato per le connessioni conosciute dalla macchina. Questo garantisce il load-balancing primitivo.
Si può utilizzare l'obiettivo `-j ACCEPT' per lasciare che la connessione prosegua senza che avvenga alcuna operazione di NAT.
Il comportamento standard è di alterare la connessione il meno possibile entro i vincoli delle regole date dall'utente. Questo significa che le porte non saranno rimappate a meno che non ce ne sia bisogno.
Anche quando il NAT non è richiesto per una connessione, la traduzione della porta sorgente può avvenire implicitamente se un'altra connessione è stata mappata sopra la nuova. Si consideri il caso del mascheramento che è comune:
Quando si ha questo mapping implicito della sorgente, le porte sono divise in tre classi:
Una porta non sarà mai mappata implicitamente in una classe differente.
Se non esiste un modo per mappare unicamente una connessione come richiede l'utente, allora sarà rifiutata. Questo accade anche ai pacchetti che non possono essere classificati come appartenenti ad una qualsiasi connessione, in quanto malformati o perché la box ha esaurito la memoria, ecc.
Si possono avere regole NAT che mappano i pacchetti sullo stesso intervallo; il codice del NAT è sufficientemente abile ad evitare conflitti. Perciò pur avendo due regole che mappano gli indirizzi sorgente 192.168.1.1 e 192.168.1.2 su 1.2.3.4 tutto funzionerà correttamente.
In aggiunta si possono mappare gli indirizzi IP reali usati, sempre che questi indirizzi attraversino la box che effettua il mapping. Quindi se si ha una rete assegnata (1.2.3.0/24) e una rete interna che usa questi indirizzi, e un'altra ancora che usa indirizzi internet privati del tipo 192.168.1.0/24, si può effettuare tranquillamente il NAT dei pacchetti con indirizzo sorgente 192.168.1.0/24 sulla rete 1.2.3.0, senza aver paura di eventuali sovrapposizioni.
# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 \
-j SNAT --to 1.2.3.0/24
La stessa logica si può applicare agli indirizzi usati dalla NAT box stessa: è così che funziona il masquerading (condividendo l'indirizzo dell'interfaccia tra pacchetti mascherati e pacchetti reali provenienti dalla box stessa).
Inoltre, si possono mappare gli stessi pacchetti su differenti obiettivi, ed essi saranno suddivisi. Per esempio, se non si vuole mappare nulla sopra 1.2.3.5, allora si può usare:
# iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth1 \
-j SNAT --to 1.2.3.0-1.2.3.4 --to 1.2.3.6-1.2.3.254
Il codice NAT consente di inserire delle regole nella catena OUTPUT ma ciò non è pienamente supportato nel kernel 2.4 (potrebbe esserlo ma richiederebbe una nuova opzione di configurazione, una fase di test e lo sviluppo di una buona quantità di codice, quindi fino a quando qualcuno non contatterà Rusty per realizzarlo esso non sarà disponibile in tempi brevi.
L'attuale limitazione consente di cambiare la destinazione solo verso la macchina locale (es. `j DNAT --to 127.0.0.1') e non verso una qualsiasi altra macchina. In caso contrario le risposte non saranno tradotte correttamente.