Cómo hacer que todo el tráfico pase por una interfaz en Linux

12

Tengo una interfaz autoescrita tun0 ( basada en TUN / TAP ) que emite lo que recibe.
Necesito que todo el tráfico del sistema fluya a través de esta interfaz.
El papel de la interfaz es:

  1. Para averiguar los paquetes que probablemente serán censurados y tunelizarlos.
  2. Pase el resto del tráfico sin tocar.

Como supones, estoy tratando de construir una herramienta anticensura.
La decisión sobre la tunelización debe tomarse dentro del proceso tun0
porque solo allí podemos usar DNS de confianza.

Necesito su ayuda para mostrarme cómo hacer que todo el tráfico fluya a través de una interfaz autoescrita tun0. Si tun0 necesita cambios, le pido que proporcione dichos cambios.

A continuación se muestra cómo intenté hacer que todo el tráfico pasara por tun0 y fallé (los pings fallan).

Compilando

  1. gcc tun0.c
  2. sudo ./a.out

Configurando

  1. sudo ip addr add 10.0.0.1/24 dev tun0
  2. crear tabla John

    $ cat /etc/iproute2/rt_tables 
    #
    # reserved values
    #
    255     local
    254     main
    253     default
    0       unspec
    #
    # local
    #
    #1      inr.ruhep
    
    200 John
    

El orden es importante:

  1. sudo ip rule add from all lookup John
  2. sudo ip route add default dev tun0 table John
  3. sudo ip rule add iif tun0 lookup main priority 500

    $ ip rule
    0:      from all lookup local 
    500:    from all iif tun0 lookup main 
    32765:  from all lookup John 
    32766:  from all lookup main 
    35000:  from all lookup default 
    

Solución de problemas

  1. sudo tcpdump -i wlp2s0 -qtln icmpy luego ping -I tun0 8.8.8.8no muestra ningún paquete capturado, significa que no se transmiten paquetes desde tun0 a wlp2s0 a través de la iif tun0 lookup mainregla.

  2. Cuando lo reemplacé tun0por lotodas partes, funcionó para mí.

También probé

  1. Desactivar el filtrado de ruta inversa, rp_filter=0en/etc/sysctl.conf

Respondida Solución de problemas

iptables -I FORWARD -j LOG --log-prefix "filter/FORWARD " 
iptables -t nat -I OUTPUT -j LOG --log-prefix "nat/OUTPUT " 
iptables -t nat -I PREROUTING -j LOG --log-prefix "nat/PREROUTING " 
iptables -t nat -I POSTROUTING -j LOG --log-prefix "nat/POSTROUTNG "
tail -f /var/log/syslog

Las fuentes modificadas de la respuesta también están aquí .

ilyaigpetrov
fuente

Respuestas:

10

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 tun0interfaz y su dirección local es 10.0.0.1). Capturas los paquetes, todo está bien hasta ahora.
Ahora, tun0envía los paquetes más lejos. La dirección de origen es 10.0.0.1y desea que los paquetes salgan a través de una interfaz diferente ( wlp2s0en 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 tcpdumppara wlp2s0que pueda notar los paquetes salen con la dirección de origen 10.0.0.1y 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 FORWARDcadena tenga una ACCEPTpolí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 tun0interfaz a wlp2s0. netfilter debería cambiar la IP de origen 10.0.0.1a la wlp2s0direcció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 wlp2s0direcció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 OUTPUTcadena y luego se enruta y llega a la PREROUTINGcadena. Al menos en Debian 8 box no funciona.
La mejor manera de solucionar problemas de netfilter es la TRACEcaracterí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 FORWARDcadena (y no está siendo atrapado por la nat/POSTROUTINGcadena 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.caplicació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.ccon 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.clanzamiento:

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: tun0solo 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 SNATantes de que el paquete llegue a la tun0interfaz. 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 tun0dispositivo. tun0.cel 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/POSTROUTINGcadena en la wlp2s0interfaz 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 SNATpero se le capturar paquetes sólo salientes:
En primer lugar tenemos que desactivar el camino inverso filtrado para tun0porque 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.

tifssoft
fuente
Tenía que usar -j SNAT, no-s SNAT
ilyaigpetrov
Funciona, pero el rendimiento es muy intermitente (puede detenerse durante 10 segundos y luego continuar funcionando). Voy a averiguar por qué sucede y cómo solucionarlo.
ilyaigpetrov
1
Lo siento, fue mi error tipográfico. Agregué otro enfoque a mi respuesta. No tengo idea sobre el problema de rendimiento. Por cierto, ¿por qué no utilizar un proxy transparente con iptables DNAT para filtrar y desviar el tráfico?
tifssoft
No puedo reproducir su enfoque de marca, solo lo he agregado sudo ip rule add iif tun0 lookup main priority 500, pero aún así no funcionó. Me gusta este enfoque, lástima que no pueda reproducirlo.
ilyaigpetrov
1
Gracias por su nuevo enfoque, lo seguí paso a paso y funcionó perfectamente. Sin embargo, no entiendo por qué necesitamos cambiar los ips, lo más importante es que funciona. En caso de que mis planes con el proxy TCP fallen, podré volver a su respuesta. Usted mostró muchas habilidades de redes aquí y no dudo que sus habilidades serán codiciadas. ¡Buena suerte!
ilyaigpetrov