Entonces, en su configuración, todos los paquetes que intenta enviar a la red se originan inicialmente 10.0.0.1
(porque están pasando por la tun0
interfaz y su dirección local es 10.0.0.1
). Capturas los paquetes, todo está bien hasta ahora.
Ahora, tun0
envía los paquetes más lejos. La dirección de origen es 10.0.0.1
y desea que los paquetes salgan a través de una interfaz diferente ( wlp2s0
en su caso). Eso es enrutamiento, así que habilitemos el enrutamiento primero:
sysctl -w net.ipv4.ip_forward=1
Después de eso, si usted mira tcpdump
para wlp2s0
que pueda notar los paquetes salen con la dirección de origen 10.0.0.1
y no con la dirección de origen de la interfaz WLAN (lo que cabría esperar, supongo). Por lo tanto, debemos cambiar la dirección de origen y se llama NAT de origen . En Linux es fácil con la ayuda de netfilter / iptables :
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.1 -j MASQUERADE
También verifique que su FORWARD
cadena tenga una ACCEPT
política o que deba permitir el reenvío con algo como:
iptables -A FORWARD -i tun0 -o wlp2s0 -s 10.0.0.1 -j ACCEPT
iptables -A FORWARD -i wlp2s0 -o tun0 -d 10.0.0.1 -j ACCEPT
Todo debería funcionar ahora: Linux kernel hace el enrutamiento, mueve los paquetes de la tun0
interfaz a wlp2s0
. netfilter debería cambiar la IP de origen 10.0.0.1
a la wlp2s0
dirección asignada a su interfaz para los paquetes de salida. Memoriza todas las conexiones y cuando los paquetes de respuesta regresan (si lo hacen) cambia la dirección de destino de la wlp2s0
dirección asignada a la interfaz 10.0.0.1
(la función "conntrack").
Bueno, debería, pero no lo hace. Parece que netfilter se confunde con esta configuración de enrutamiento complicada y el hecho de que el mismo paquete primero atraviesa la OUTPUT
cadena y luego se enruta y llega a la PREROUTING
cadena. Al menos en Debian 8 box no funciona.
La mejor manera de solucionar problemas de netfilter es la TRACE
característica:
modprobe ipt_LOG
iptables -t raw -A OUTPUT -p icmp -j TRACE
iptables -t raw -A PREROUTING -p icmp -j TRACE
Solo habilito el rastreo para paquetes ICMP, puede usar otro filtro para depurar.
Mostrará a qué tablas y cadenas pasa el paquete. Y puedo ver que el paquete no va más allá de la FORWARD
cadena (y no está siendo atrapado por la nat/POSTROUTING
cadena que realmente lo hace SNAT
).
A continuación hay varios enfoques para hacer que esto funcione.
ENFOQUE # 1
La mejor manera de confundir netfilter es cambiar la dirección IP de origen de los paquetes en la tun0.c
aplicación. También es la forma más natural. Necesitamos cambiar 10.0.0.1 a 10.0.0.2 en el camino de ida y 10.0.0.2 a 10.0.0.1 en el camino de regreso.
He modificado tun0.c
con el código de cambio de dirección de origen. Aquí está el nuevo archivo y aquí está el archivo de parche para su tun0.c
. Los cambios en el encabezado IP también implican la corrección de la suma de verificación , por lo que tomé un código del proyecto OpenVPN . Aquí está la lista completa de comandos que ejecuto después de un reinicio limpio y tun0_changeip.c
lanzamiento:
ifconfig tun0 inet 10.0.0.1/30 up
sysctl -w net.ipv4.ip_forward=1
ip route add default dev tun0 table John
ip rule add from all lookup John
ip rule add from 10.0.0.2 lookup main priority 500
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.0.2 -j MASQUERADE
Tenga en cuenta que no necesita desactivar el filtro de ruta inversa en ese caso, porque todo es legal: tun0
solo recibe y envía paquetes que pertenecen a su subred. También puede hacer un enrutamiento basado en la fuente en lugar de una interfaz.
ENFOQUE # 2
Es posible hacerlo SNAT
antes de que el paquete llegue a la tun0
interfaz. Sin embargo, no es muy correcto. Definitivamente necesitará desactivar el filtrado de ruta inversa en este caso:
sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0
Ahora, haga SNAT
: iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source ip.address.of.your.wlan.interface
Aquí cambiamos la dirección de origen justo antes de que los paquetes lleguen al tun0
dispositivo. tun0.c
el código reenvía estos paquetes "tal cual" (con la dirección de origen modificada) y se enrutan correctamente a través de la interfaz wlan. Pero es posible que tenga una IP dinámica en la interfaz wlan y quiera usarla MASQUERADE
(para no especificar explícitamente la dirección de la interfaz). Así es como puedes hacer uso de MASQUERADE
:
iptables -t nat -A POSTROUTING -o tun0 -s 10.0.0.1 -j SNAT --to-source 10.0.55.1
iptables -t nat -A POSTROUTING -o wlp2s0 -s 10.0.55.1 -j MASQUERADE
Tenga en cuenta la " 10.0.55.1
" dirección IP, es diferente. Puede usar cualquier IP aquí, no importa. Los paquetes alcanzan la nat/POSTROUTING
cadena en la wlp2s0
interfaz si cambiamos la IP de origen antes. Y ahora no depende de una IP estática para la interfaz wlan.
ENFOQUE # 3
También puedes usar fwmark
. De esta manera no es necesario SNAT
pero se le capturar paquetes sólo salientes:
En primer lugar tenemos que desactivar el camino inverso filtrado para tun0
porque va a reenviar los paquetes que pertenecen a otra red:
sysctl -w net.ipv4.conf.tun0.rp_filter=0
# It won't work without also changing the "all" value
sysctl -w net.ipv4.conf.all.rp_filter=0
Now let's alter the routing rules a bit:
# Delete old rules
ip rule del iif tun0 lookup main
ip rule del from all lookup John
# Packets will start going from wlan interface so they will have source address of it
iptables -t mangle -A OUTPUT -o wlp2s0 -j MARK --set-mark 1
ip rule add fwmark 0x1 lookup John
Ese es otro "hack" para enrutamiento y filtro de red que funciona en mi caja Debian 8, pero aún así recomiendo tomar el primer enfoque, ya que es más natural y no utiliza ningún hack.
También puede considerar construir su aplicación como un proxy transparente . Creo que sería mucho más fácil en lugar de analizar paquetes desde el dispositivo tun.
-j SNAT
, no-s SNAT