Solución 1:
Utilicé con éxito lo siguiente en Linux para probar el rendimiento en una nueva tarjeta de 10 Gbps de doble puerto en modo de "bucle invertido", es decir, un puerto conectado directamente al otro. Todo esto es solo un poco de vudú solo para forzar la salida de paquetes, pero si no lo hace, Linux solo provocará un cortocircuito en el tráfico a través del kernel (de ahí la pregunta del OP). En la respuesta anterior de Casey, no estoy seguro de si era realmente necesario tener un enrutador externo o no, pero lo siguiente es completamente independiente. Las dos interfaces son eth2 y eth3.
Asigne direcciones 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 de doble NAT:dos nuevas redes falsas utilizadas para llegar a la otra. Al salir, envíe NAT a su red falsa. En el camino, fija 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 complete previamente las entradas arp (asegúrese de sustituir sus direcciones MAC, no use la mía):
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 recibe NAT en 10.60.0.1, y cuando entra en eth3, el destino 10.60.1.1 recibe NAT en 10.50.1.1. Y la respuesta hace un viaje similar.
Ahora use iperf para probar el rendimiento. Enlace a las IP correctas y asegúrese de con qué IP se está comunicando (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 vaya al cable:
tcpdump -nn -i eth2 -c 500
También puede ver /proc/interrupts 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 otra persona a encontrar esta publicación en el futuro.
Solución 2:
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 ip link simple. ya que esto se ejecuta en el contexto del espacio de nombres predeterminado. Se puede ejecutar un comando dentro de un espacio de nombres 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 la ejecución del 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 toda la pila de red, la interfaz, el enrutamiento ... está aislado por los espacios de nombres, por lo que el kernel 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).
Solución 3:
Amplié la respuesta de caladona ya que no pude ver los paquetes de respuesta. Para este ejemplo:
- En mi PC local tengo NIC en diferentes subredes, 192.168.1/24 ,
192.168.2/24
- Hay un enrutador/PC externo que tiene acceso a ambas subredes.
- Quiero enviar tráfico bidireccional a través de las NIC en la PC local.
- La configuración requiere dos direcciones IP sin usar para cada subred.
Las rutas iptable de la PC local se establecen en SNAT y el tráfico saliente de DNAT en 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:
- Reescriba la fuente 192.168.2.1 a 192.168.2.100 en los paquetes salientes
- Reescriba el destino 192.168.1.100 a 192.168.1.1 en los paquetes entrantes
- Reescriba la fuente 192.168.1.1 a 192.168.1.100 en los paquetes salientes
- Reescriba 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.
A continuación, debe obligar a su PC local a usar el enrutador externo para llegar a su IP falsa. Para ello, crea una ruta directa a las direcciones 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 esto funcione, el enrutador externo necesita saber cómo llegar a las direcciones IP falsas en su PC local. Puede hacer cosas activando ARP de 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á la salida de paquetes de la interfaz .2. Enviar datos a la subred .2 forzará la salida de paquetes de la interfaz .1.
ping 192.168.1.100
ping 192.168.2.100
Solución 4:
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 y 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, el paquete 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 envía de vuelta a IF1_ADDR, desde IF2_ADDR, que se reemplaza por FAKE_ADDR.
Tal vez sea posible usar una configuración más simple con solo un cable cruzado, pero como no lo intenté, prefiero dar mi solución de trabajo.