Dnat Policyrouting
Dnat Policyrouting
Dnat Policyrouting
Los que hayais intentado dar servicio por dos líneas en un linux que también redirige algunos puertos
(DNAT) a máquinas internas seguro que os habreis encontrado con el problema de que las
conexiones del exterior hacia una de las IPs públicas funciona, pero las de la otra IP pública, no. ¡Y
eso que teneis el policy routing y las reglas de IPTables bien configuradas!
Los que os esteis encontrando este problema podeis saltaros la introducción e ir directamente a la sección Solución 2.
¿Y DNAT?
DNAT son las siglas de Destination Network Address Translation. Muy por encima, y en el caso que nos ocupa en este
artículo, el DNAT nos permite redirigir puertos hacia máquinas internas. Para más información podeis visitar esta
introducción al NAT(1).
En el esquema tenemos una red, llamemosle interna, conectada a Internet por dos líneas/ISPs. El firewall es un
GNU/linux con IPTables.
Lo que queremos conseguir es que se puedan usar las dos líneas para que usuarios se puedan conectar a nuestros
servidores (ya sean web, de correo, etc.)
Entrando un poco más en detalle, alrededor del firewall tenemos dos LANs, la pública y la privada. Supondremos las
siguientes direcciones:
1/5
BULMA: Haciendo funcionar el Policy Routing junto a DNAT
Nota: Yo siempre que puedo utilizo la eth0 como la red externa y la eth1 como la interna. La regla pnemotécnica es:
de eth0, el 0 se parece a O de Outside, de eth1, el 1 se parece a la I de Inside :−)
Preliminares
Para poder utilizar el policy routing es necesario tener las correspondientes opciones compiladas en el kernel, ya sea
dentro del mismo o como módulos. Para el NAT, hay que compilar tamben el soporte de netfiler. Importante, porque lo
necesitaremos más adelante, compilar el soporte para "Connection tracking march support".
Opciones imprescindibles:
Añadimos los nombres de las tablas para poder trabajar con nombres descriptivos en lugar de con números # echo
101 isp1 >> /etc/iproute2/rt_tables # echo 102 isp2 >> /etc/iproute2/rt_tables
Rutas para la línea del ISP1 # ip route add 10.0.0.0/24 dev eth0 src 10.0.0.2 table isp1
# ip route add default via 10.0.0.1 table isp1
Rutas para la línea del ISP2 # ip route add 10.0.1.0/24 dev eth0 src 10.0.1.2 table isp2
# ip route add default via 10.0.1.1 table isp2
Rutas principales # ip route add 10.0.0.0/24 dev eth0 src 10.0.0.2 # ip route add
10.0.1.0/24 dev eth0 src 10.0.1.2 # ip route add default via 10.0.0.1 (o
2/5
BULMA: Haciendo funcionar el Policy Routing junto a DNAT
10.0.1.1 si queremos que por defecto se envie el trafico por la línea del ISP2)
Finalmente añadimos las reglas de policy routing, lo que salga del router con origen 10.0.0.2 lo enviamos hacia el
router del ISP1 y lo que salga con origen 10.0.1.2, lo enviamos al router del ISP2. # ip rule add from
10.0.0.2 table isp1 # ip rule add from 10.0.1.2 table isp2
Para comprobar el policy routing, usaremos el traceroute indicandole con que IP origen queremos que haga las trazas: #
traceroute −n −s 10.0.0.2 www.cisco.com (debería salir por la linea del ISP1) # traceroute −n −s 10.0.1.2
www.cisco.com (debería salir por la linea del ISP2)
Con un 'tcpdump −e −i eth0', si nos fijamos en las MACs, veremos que el firewall está enviando los paquetes con
dirección origen 10.0.1.2 hacia el router que no toca, el 10.0.0.1. ¿Y como es eso? ¿A caso no hemos comprobado
anteriormente el policy routing desde el firewall y había funcionado? La pequeña gran diferencia es que en este caso
tenemos un DNAT.
Explicación
Para entender el motivo por el que no funciona hay que tener claro el camino que sigue el paquete dentro del kernel del
firewall. El siguiente esquema está sacado del IPTables tutorial(4):
3/5
BULMA: Haciendo funcionar el Policy Routing junto a DNAT
Cuando un paquete va del cliente al servidor, lo primero que se encuentra (que sea relevante para esta explicación) es la
lista PREROUTING de la tabla nat, donde se hace el DNAT. En el DNAT se cambia la dirección destino del paquete, y
al enrutarse posteriormente, como el kernel ve que va dirigido al servidor, mete el paquete hacia la red interna.
El problema está en que cuando las respuestas del servidor hacia el cliente pasan por el firewall, no se deshace el
DNAT antes del enrutado. El kernel primero enrutará el paquete y luego le cambiará la IP origen, deshaciendo el
DNAT. ¡Pero nuestro policy routing estaba enrutando según la dirección origen! Ahí esta el problema, no podemos
enrutar por dirección origen los paquetes que son respuesta de otro que sufrió un proceso de DNAT.
4/5
BULMA: Haciendo funcionar el Policy Routing junto a DNAT
De las características del modulo conntrack, a nosotros nos interesa la capacidad de poder marcar los paquetes según la
dirección destino que tenían los paquetes que iniciaron la conexión cuando estos llegaron al firewall provenientes del
cliente, antes de aplicarle el DNAT. Es decir, según la dirección a la que el cliente se estaba intentando conectar. Las
reglas de IPTables que nos solucionaran el entuerto son: # iptables −t mangle −A PREROUTING −m
conntrack −−ctorigdst 10.0.0.2 −j MARK −−set−mark=1 # iptables −t mangle −A
PREROUTING −m conntrack −−ctorigdst 10.0.1.2 −j MARK −−set−mark=2
Ahora solo hace falta que enrutemos según la marca del paquete: # ip rule add fwmark 1 table isp1 #
ip rule add fwmark 2 table isp2
1. http://linux−ip.net/html/nat−overview.html
2. http://bulma.net/body.phtml?nIdNoticia=1522
3. http://lartc.org/howto/lartc.rpdb.multiple−links.html
4. http://iptables−tutorial.frozentux.net/iptables−tutorial.html
5. http://bulma.net/body.phtml?nIdNoticia=1615
5/5