Forzar el tráfico IP local a una interfaz externa

30

Tengo una máquina con varias interfaces que puedo configurar como quiera, por ejemplo:

  • eth1: 192.168.1.1
  • eth2: 192.168.2.2

Me gustaría reenviar todo el tráfico enviado a una de estas direcciones locales a través de la otra interfaz. Por ejemplo, todas las solicitudes a un servidor http iperf, ftp, en 192.168.1.1 no solo deben enrutarse internamente, sino que deben enviarse a través de eth2 (y la red externa se encargará de redirigir el paquete a eth1).

Intenté y miré varios comandos, como iptables, ip route, etc ... pero nada funcionó.

El comportamiento más cercano que pude conseguir se hizo con:

ip route change to 192.168.1.1/24 dev eth2

que envían todos los 192.168.1.x en eth2, excepto 192.168.1.1 que todavía se enruta internamente. ¿Podría entonces hacer el reenvío NAT de todo el tráfico dirigido a 192.168.1.2 falso en eth1, redirigido a 192.168.1.1 internamente? En realidad estoy luchando con iptables, pero es demasiado difícil para mí.

El objetivo de esta configuración es hacer una prueba de controlador de interfaz sin usar dos PC.

Estoy usando Linux, pero si sabes cómo hacerlo con Windows, ¡lo compraré!

Editar:

La red externa es solo un cable cruzado entre eth1 y eth2. Digamos que tengo un servidor http en mi máquina. Ahora quiero acceder a este servidor desde la misma máquina, pero quiero forzar al tráfico TCP / IP a pasar por este cable eth1 / eth2. ¿Cómo debo configurar mis interfaces para esto?

calandoa
fuente
¿Está diciendo que desea que todo el tráfico se refleje a través de la interfaz 1 y 2 pero que solo se devuelva a la interfaz 2 desde otro enrutador? ¿No podría eso hacer algunas cosas bastante extrañas en la red? ¿Sería mejor dirigir el tráfico reflejado desde la interfaz 2 a otro sistema que acaba de eliminar el tráfico y luego puede monitorearlo o usar un software de virtualización para capturar el tráfico? Tal vez me falta algo en la descripción.
Bart Silverstrim
Parece que quiere generar un paquete para, digamos, 192.168.1.1, que es la IP de eth1. Pero en lugar de que la pila de Linux reciba ese paquete completamente internamente, quiere que el paquete se expulse eth2 (que se enviará externamente a eth1 y luego a la pila de Linux). No estoy seguro de si esto es posible; Una vez que la capa de red detecta que la dirección es una interfaz interna, tendrá pocas razones para mirar las tablas de enrutamiento. Alguien más puede saber mejor.
PP.

Respuestas:

14

Extendí la respuesta de Caladona ya que no podía ver los paquetes de respuesta. Para este ejemplo:

  1. En mi PC local tengo NIC en diferentes subredes, 192.168.1 / 24 , 192.168.2 / 24
  2. Hay un enrutador / PC externo que tiene acceso a ambas subredes.
  3. Quiero enviar tráfico bidireccional a través de las NIC en la PC local.
  4. La configuración requiere dos direcciones IP no utilizadas para cada subred.

Las rutas iptable de la PC local están configuradas para el tráfico saliente SNAT y DNAT a la IP 'falsa'.

iptables -t nat -A POSTROUTING -d 192.168.1.100 -s 192.168.2.0/24 -j SNAT --to-source      192.168.2.100
iptables -t nat -A PREROUTING  -d 192.168.1.100 -i eth0           -j DNAT --to-destination 192.168.1.1
iptables -t nat -A POSTROUTING -d 192.168.2.100 -s 192.168.1.0/24 -j SNAT --to-source      192.168.1.100
iptables -t nat -A PREROUTING  -d 192.168.2.100 -i eth1           -j DNAT --to-destination 192.168.2.1

Las reglas hacen lo siguiente:

  1. Reescriba la fuente 192.168.2.1 a 192.168.2.100 en los paquetes salientes
  2. Reescribe el destino 192.168.1.100 a 192.168.1.1 en los paquetes entrantes
  3. Reescriba la fuente 192.168.1.1 a 192.168.1.100 en los paquetes salientes
  4. Reescribe el destino 192.168.2.100 a 192.168.2.1 en los paquetes entrantes

Para resumir, el sistema local ahora puede comunicarse con una máquina 'virtual' con las direcciones 192.168.1.100 y 192.168.2.100.

Luego, debe forzar a su PC local a usar el enrutador externo para alcanzar su IP falsa. Para ello, crea una ruta directa a las IP a través del enrutador. Desea asegurarse de forzar los paquetes en el lado opuesto de la subred de destino.

ip route 192.168.1.100 via $ROUTER_2_SUBNET_IP 
ip route 192.168.2.100 via $ROUTER_1_SUBNET_IP

Finalmente, para que todo funcione, el enrutador externo necesita saber cómo llegar a las IP falsificadas en su PC local. Puede hacer cosas delgadas activando los ARP proxy para su sistema.

echo 1 | sudo tee /proc/sys/net/ipv4/conf/all/proxy_arp
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward

Con esta configuración, ahora puede tratar las IP falsas como un sistema real en su PC local. El envío de datos a la subred .1 forzará a los paquetes a salir de la interfaz .2. El envío de datos a la subred .2 forzará a los paquetes a salir de la interfaz .1.

ping 192.168.1.100
ping 192.168.2.100
cmcginty
fuente
Mucho mejor a tu manera! Tenga en cuenta que también necesito un ip_forward para que funcione el material ARP: echo 1> / proc / sys / net / ipv4 / ip_forward
calandoa
28

Utilicé con éxito lo siguiente en Linux para probar el rendimiento en una nueva tarjeta de 10 Gbps de doble puerto en modo "loopback", es decir, un puerto conectado directamente al otro. Todo esto es solo un poco de vudú solo para forzar los paquetes a salir del cable, pero si no lo hace, Linux solo cortocircuitará el tráfico a través del núcleo (de ahí la pregunta del OP). En la respuesta de Casey anterior, no estoy seguro de si era realmente necesario tener un enrutador externo o no, pero lo siguiente es completamente autónomo. Las dos interfaces son eth2 y eth3.

Proporcione IP a las interfaces y colóquelas en redes separadas:

ifconfig eth2 10.50.0.1/24
ifconfig eth3 10.50.1.1/24

A continuación, configuraremos un escenario NAT doble: dos redes falsas nuevas utilizadas para llegar a la otra. Al salir, obtenga NAT de su red falsa. En el camino, arregle el destino. Y viceversa para la otra red:

# nat source IP 10.50.0.1 -> 10.60.0.1 when going to 10.60.1.1
iptables -t nat -A POSTROUTING -s 10.50.0.1 -d 10.60.1.1 -j SNAT --to-source 10.60.0.1

# nat inbound 10.60.0.1 -> 10.50.0.1
iptables -t nat -A PREROUTING -d 10.60.0.1 -j DNAT --to-destination 10.50.0.1

# nat source IP 10.50.1.1 -> 10.60.1.1 when going to 10.60.0.1
iptables -t nat -A POSTROUTING -s 10.50.1.1 -d 10.60.0.1 -j SNAT --to-source 10.60.1.1

# nat inbound 10.60.1.1 -> 10.50.1.1
iptables -t nat -A PREROUTING -d 10.60.1.1 -j DNAT --to-destination 10.50.1.1

Ahora dígale al sistema cómo llegar a cada red falsa y rellene previamente las entradas arp (asegúrese de sustituir sus direcciones MAC, no use las mías):

ip route add 10.60.1.1 dev eth2
arp -i eth2 -s 10.60.1.1 00:1B:21:C1:F6:0F # eth3's mac address

ip route add 10.60.0.1 dev eth3 
arp -i eth3 -s 10.60.0.1 00:1B:21:C1:F6:0E # eth2's mac address

Esto engaña a Linux lo suficiente como para poner paquetes en el cable. Por ejemplo:

ping 10.60.1.1

sale eth2, la IP de origen 10.50.0.1 obtiene NATted a 10.60.0.1, y cuando entra eth3, el destino 10.60.1.1 obtiene NATted a 10.50.1.1. Y la respuesta toma un viaje similar.

Ahora use iperf para probar el rendimiento. Vincula las IP correctas y asegúrate de qué IP estás contactando (la dirección falsa del otro extremo):

# server
./iperf -B 10.50.1.1 -s

# client: your destination is the other end's fake address
./iperf -B 10.50.0.1 -c 10.60.1.1 -t 60 -i 10

Asegúrese de que el tráfico realmente esté saliendo al cable:

tcpdump -nn -i eth2 -c 500

También puede mirar / proc / interrupciones solo para estar absolutamente seguro de que la tarjeta se está utilizando:

while true ; do egrep 'eth2|eth3' /proc/interrupts ; sleep 1 ; done

De todos modos, encontré esta publicación buscando cómo hacer esto, gracias por los chicos de preguntas y respuestas, y espero que esto ayude a cualquier persona a encontrar esta publicación en el futuro.

Steve Kehlet
fuente
+1 Gran solución: ¡esto ni siquiera requiere activar el reenvío de IP! Esto es justo lo que necesitaba en este momento (para pruebas de 10 GB a través de loopback).
Nils
16

Como siempre, llego un poco tarde, pero hoy en día uno podría usar espacios de nombres de red para aislar las interfaces y evitar cualquier reenvío local (y jugar con iptables :)).

Cree espacios de nombres (todo hecho con los permisos requeridos, por ejemplo, como root):

ip netns add ns_server
ip netns add ns_client

Tenga en cuenta que ahora se debe acceder al estado / configuración de las interfaces dentro del contexto del espacio de nombres asignado, por lo que no aparecerán si ejecuta un enlace ip desnudo, ya que se ejecuta en el contexto del espacio de nombres predeterminado. La ejecución de un comando dentro de un espacio de nombres se puede hacer usando

ip netns exec <namespace-name> <command>

como prefijo

Ahora asigne espacios de nombres a las interfaces, aplique la configuración y configure las interfaces:

ip link set eth1 netns ns_server
ip netns exec ns_server ip addr add dev eth1 192.168.1.1/24
ip netns exec ns_server ip link set dev eth1 up
ip link set eth2 netns ns_client
ip netns exec ns_client ip addr add dev eth2 192.168.1.2/24
ip netns exec ns_client ip link set dev eth2 up

Ahora puede ejecutar las aplicaciones dentro del espacio de nombres; para ejecutar el servidor iperf

ip netns exec ns_server iperf -s -B 192.168.1.1

y el cliente:

ip netns exec ns_client iperf -c 192.168.1.1 -B 192.168.1.2

El tráfico ahora se enviará a través de las interfaces físicas, ya que todo el stack de red, la interfaz, el enrutamiento ... está aislado por los espacios de nombres, por lo que el núcleo no puede hacer coincidir las direcciones utilizadas dentro del tráfico con las interfaces locales (disponibles).

Si ha terminado con sus experimentos, simplemente elimine los espacios de nombres:

ip netns del <namespace-name>

Las interfaces se reasignarán al espacio de nombres predeterminado y toda la configuración realizada dentro del espacio de nombres desaparecerá (por ejemplo, no es necesario eliminar las direcciones IP asignadas).

Thomas Tannhäuser
fuente
Esto es mucho más directo que la magia de doble nat que se sugiere, y no requiere ninguna coordinación de otras computadoras en la red ni asumir ninguna topología física. Mi única solicitud sería que agregue comandos para agregar rutas.
Huckle
2

Ok, finalmente logré configurar mi configuración.

La idea es usar otra dirección falsa, forzar la ruta de esta dirección falsa a la interfaz 2, luego traducir la dirección falsa con la dirección real 2 con NAT / iptables.

Mi configuración en realidad está hecha de un enrutador que puedo hacer telnet entre IF1 (interfaz 1) e IF2

En mi configuración, FAKE_ADDR e IF1_ADDR están en la misma subred.

ifconfig $IF1 $IF1_ADDR netmask 255.255.255.0
ifconfig $IF2 $IF2_ADDR netmask 255.255.255.0

iptables -t nat -A PREROUTING -d $FAKE_ADDR -i $IF2 -j DNAT --to-destination $IF2_ADDR
iptables -t nat -A POSTROUTING -s $IF2_ADDR -d $IF1_ADDR/24 -j SNAT --to-source $FAKE_ADDR

route add $FAKE_ADDR gw $ROUTER_ADDR

Y en el enrutador:

route add $FAKE_ADDR gw $IF2_ADDR

Si envío algo a FAKE_ADDR, pkt se reenvía a través de IF1 al enrutador, se reenvía nuevamente a IF2, luego FAKE_IP se reemplaza por IF2_ADDR. El servidor procesa el paquete, el resultado se devuelve a IF1_ADDR, desde IF2_ADDR, que se reemplaza por FAKE_ADDR.

Puede ser posible utilizar una configuración más simple con un solo cable cruzado, pero como no lo intenté, prefiero dar mi solución de trabajo.

calandoa
fuente
si el enrutador está enviando $ FAKE_ADDR a $ IF2_ADDR, ¿no es necesario que su regla DNAT sea "-i $ IF2" en lugar de "-i $ IF1"?
cmcginty
Tienes razón Casey, corrección hecha.
calandoa
1

¡La respuesta dada por Thomas Tannhäuser fue acertada!

Tuve una situación similar: una sola máquina con dos interfaces enet. Mi plan era usar una interfaz como servidor (receptor) y la otra como cliente (remitente). Cada interfaz se conectaría al enrutador e iperf conduciría el tráfico a través del enrutador para medir el rendimiento, el PPS, el retraso, etc.

Desafortunadamente, el enfoque de iptables no era intuitivo y estaba lleno de problemas. Después de unas horas frustrantes, abandoné este plan de ataque. Inspirado por la sugerencia de Thomas, hice un poco de tarea en los espacios de nombres IP de Linux y comencé a apreciar la simplicidad y elegancia de esta solución.

A continuación hay una lista de los comandos exactos que utilicé para configurar mi Fedora FC26 para servir en esta capacidad. Las dos interfaces son enp1s0 y enp3s0. El enrutador tiene dos interfaces con las direcciones 192.168.2.112 y 172.16.16.2. Cada conector FC26 ENET está conectado directamente a la interfaz del enrutador correspondiente.

# How to configure the IP Namespaces
ip netns add iperf-server
ip netns add iperf-client
ip link set enp1s0 netns iperf-server
ip link set enp3s0 netns iperf-client
ip netns exec iperf-server ip addr add dev enp1s0 192.168.2.139/20
ip netns exec iperf-client ip addr add dev enp3s0 172.16.16.2/24
ip netns exec iperf-client ip link set dev enp3s0 up
ip netns exec iperf-server ip link set dev enp1s0 up
ip netns exec iperf-server route add default gw 192.168.2.112
ip netns exec iperf-client route add default gw 172.16.16.1

# Test the interfaces and network using ping
ip netns exec iperf-client ping -c1 172.16.16.1
ip netns exec iperf-server ping -c1 192.168.2.112
ip netns exec iperf-server ping -c1 172.16.16.2
ip netns exec iperf-client ping -c1 192.168.2.139

# Start Iperf Server for UDP test
ip netns exec iperf-server iperf -u -s
# Run Client against Iperf server for UDP test
ip netns exec iperf-client iperf -u -c 192.168.2.139
RarkyMan
fuente
0

Parece que desea convertir su caja de Linux en una caja de tipo enrutador / puente / puerta de enlace / firewall. Los siguientes recursos pueden ser lo que está buscando:

El proyecto de enrutador Linux

Lista de distribuciones de enrutadores o cortafuegos

Linux LiveCD Router

Linux Journal - El enrutador Linux

Actualización basada en más información:

No creo que puedas hacer lo que quieras. El sistema operativo siempre va a mirar su tabla de enrutamiento interno y 'ver' ambas direcciones IP localmente. Luego enrutará el tráfico dentro del sistema operativo y nunca lo pondrá en el cable. Necesitará una segunda máquina o dos máquinas virtuales (consulte Xen ).

Peter
fuente
0

Hay muchas cosas por las que pasar por aquí, así que no puedo garantizar totalmente mi precisión, pero la pregunta original parece estar buscando lo que se conoce como técnica de "envío a sí mismo" . La búsqueda vinculada muestra lo que creo que es el parche de kernel mejor mantenido como enlace principal + discusiones y parches con otros enfoques en varias listas de correo, especialmente. LKML

Creo que uno también debería mirar los espacios de nombres de red , hecho con "ip netns" de iproute2 . Esto también requiere un poco de interfaz adicional y magia de enrutamiento, por lo que podría no ser menos complejo que el enorme alboroto de iptables en las otras respuestas.

Los comentarios definitivamente son bienvenidos si alguien encuentra algo útil con estos: el cómo, el qué, el dónde acerca de su implementación.

lkraav
fuente
-1

así es como lo hice funcionar para IPV6

ips estáticos asignados

/sbin/ifconfig eth1 inet6 add 2001:db8::1/127 
/sbin/ifconfig eth3 inet6 add 2001:db8::2/127 

configurar rutas de host solo a direcciones "FALSAS"

ip -6 route add 2001:db8::2/128 dev eth1 metric 1
ip -6 route add 2001:db8::1/128 dev eth3 metric 1

poblado la tabla de vecinos ... como el arp

ip -6 neighbor add 2001:db8::1 lladdr 90:e2:ba:0d:75:e8 dev eth3 # eth1's mac address
ip -6 neighbor add 2001:db8::2 lladdr 90:e2:ba:0d:75:e9 dev eth1 # eth3's mac address

agregó las entradas de ip6tables

ip6tables -t nat -A POSTROUTING -s 2001:db8::1 -d 2013::2 -j SNAT --to-source 2001:db8::1
ip6tables -t nat -A PREROUTING -d 2001:db8::1 -j DNAT --to-destination 2001:db8::1
ip6tables -t nat -A POSTROUTING -s 2001:db8::2 -d 2013::1 -j SNAT --to-source 2001:db8::2
ip6tables -t nat -A PREROUTING -d 2001:db8::2 -j DNAT --to-destination 2001:db8::2
robar
fuente
¿Qué distribución estás usando? La última vez que lo revisé, el kernel no tiene una tabla NAT para IPv6.
fukawi2