NAT en GNU/Linux

En el capítulo de OpenVPN Germán escribió un comentario en eduardocollado.com y decía literalmente «A ver si puedes hablar en algún capítulo sobre IP masquerade«, pues bien Germán, aquí está ese capítulo, hoy voy a tratar el tema que propones, que además es muy interesante y útil.

Voy a tratar el tema de NAT con iptables incluyendo masquerade, obviamente no todo iptables, ya que es un tema muy extenso y es complicado, y lo que quiero no es un audio en el que algo parezca complicado, así que vamos a ver cómo me apaño con todo esto.

Lo primero es saber qué es NAT. NAT viene de Network Address Translation y así en frío podemos definirlo como un sistema para compartir una dirección IP. Sí, lo se puede parecer una definición muy vaga pero si lo pensáis es eso ¿no?

En vuestra casa tenéis un router que hace NAT y todos los equipos de la red salen a Internet con la IP del router, así pues están compartiendo la dirección del router.

En linux vamos a tener Source NAT, Destination NAT y Port Address Translation y realmente todo cabe ahí dentro, vamos a ir uno por uno.

En Static NAT la IP origen se sustituye por otra, lo normal es que la IP de origen sea privada y la IP que sustituye sea pública y aquí es donde cuadra el tema propuesto por German, tenemos SNAT o Static NAT y Masquerade, la diferencia consiste en que la dirección traducida en masquerade es dinámica y en SNAT es estática.

En SNAT la traducción de direcciones es una a una, normalmente una IP privada contra una IP pública. En masquerade se genera una tabla de traducciones donde a cada socket (ip y puerto) se le asigna una conexión y puerto para identificarla.

En Destination NAT lo que tenemos es un puerto que está asignado a un puerto de una ip interna, por ejemplo el puerto 8080 del router puede estar asignado al puerto 80 de una máquina con IP privada.

Y el Port Address Tranlation no es más que asignar un puerto a otro puerto de la misma máquina, por ejemplo, lo que reciba en el puerto 8080 lo atiendo por el puerto 80. Y no hay que confundirlo con el Destination NAT.

En iptables hay varias tablas, pero a nosotros ahora sólo nos interesa la tabla nat y luego vamos a tener tres cadenas PREROUTING, OUTPUT y POSTROUTING.

En PREROUTING modificamos los paquetes antes de saber por donde van a ir, en OUTPUT modificamos los paquetes generados por el equipo después de encaminarlos y POSTROUTING los paquetes se modifican justo antes de abandonar el equipo y después de tomar la decisión de encaminamiento.

Con esto ya tenemos la parte teórica necesaria para trabajar con NAT en nuestro sistema.

Para empezar a crear comandos es interesante habilitar el forwarding en nuestro equipo ejecutando como root:

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

Tened en cuenta que esto que acabamos de decir sólo tiene sentido una vez y al reiniciar el sistema perderemos esa configuración, para que el bit de forwarding se quede activo tendremos que modificar el fichero /etc/sysctl.conf y descomentaremos la línea

# net.ipv4.ip_forward=1

Le quitaremos el numeral y recargaremos con

sudo sysctl -p

Antes os he comentado que hoy sólo íbamos a tocar la tabla de NAT, así que cualquier comando que ejecutemos para este fin empezará con

iptables -t nat

Ahora podemos añadir al final con -A o al principio si no indicamos donde con -I en la cadena que queramos, por ejemplo.

iptables -t nat -A POSTROUTING

Con esteo le decimos al iptables que trabaje con la tabla nat y que añada al final de las reflas de la cadena POSTROUTING, es decir, una vez decidido por donde va a ir el tráfico.

Ahora podemos seguir trabajando con esa regla e indicar que todo lo que venga desde la red 192.168.1.0/24 lo saque por la ethernet 0 haciendo NAT y como la eth0 tiene una IP dinámica tendrá que saltar o ir a la etiqueta MASQUERADE.

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

Si la IP fuera fija no sería un MASQUERADE, sino un SNAT.

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to 217.18.41.24

Aquí ya hemos dicho que haga Static NAT a la IP 217.18.41.24.

Hasta aquí quizás lo más complicado no son los comandos, sino entender que esta acción se está realizando después de hacer el routing de los paquetes, es decir, yo estoy en una red local y quiero salir a Internet, desde mi PC le mando al router, el servidor que hace el nat, un paquete y el router ve que el paquete tiene que sealir por la conexión a Internet y después de determinar por donde tiene que salir y a quien hay que enviárselo es cuando hace el NAT. Esta es la parte más complicada de ver.

Luego tenemos el caso contrario, el PREROUTING, en el que se hace el NAT antes de determinar por donde va a salir el paquete.

Este caso se da en el momento en el que recibimos un paquete en un puerto y nuestro router determina que si lo recibimos por un puerto realmente el paquete va a ir a una máquina de la red local a ese mismo puerto o a otro.

Este es el tipico ejemplo del mapeo de puertos o de DNAT. Un ejemplo concreto sería

iptables -t nat -A PREROUTING -p tcp --dport 80 -i eth0 -j DNAT --to 192.168.1.25

Ahora, ¿cómo haríamos para tener un NAT 1:1?, simplemente combinando las de antes y sin indicar puertos

iptables -t nat -A POSTROUTING -o eth0 -s 192.168.1.10 -j SNAT --to 217.18.41.25
iptables -t nat -A PREROUTING -i eth0 -d 217.18.41.25 -j DNAT --to 192.168.1.10

Vosotros pensar que aquí la limitación básicamente consiste en tener muchas direcciones IP públicas para poder hacer NATs específicos, así podríamos crear DMZs, haciendo nats por puerto además mejoraríamos la seguridad, porque quizás no necesitamos que todo el tráfico se redirija al servidor interno, las posibilidades son infinitas.