Soy un novato total, este es mi primer experimento con redes de kernel. Estoy intentando crear un puente entre dos tap
interfaces e intentar enviar tráfico a través de él. Es más un experimento que un propósito en particular.
$ brctl showstp br0
br0
bridge id 8000.46846e0c0ff9
designated root 8000.46846e0c0ff9
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 2.00 bridge hello time 2.00
forward delay 15.00 bridge forward delay 15.00
ageing time 300.00
hello timer 1.98 tcn timer 0.00
topology change timer 0.00 gc timer 115.04
flags
tap1 (1)
port id 8001 state forwarding
designated root 8000.46846e0c0ff9 path cost 100
designated bridge 8000.46846e0c0ff9 message age timer 0.00
designated port 8001 forward delay timer 10.34
designated cost 0 hold timer 0.98
flags
tap2 (2)
port id 8002 state forwarding
designated root 8000.46846e0c0ff9 path cost 100
designated bridge 8000.46846e0c0ff9 message age timer 0.00
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.98
flags
Tengo el puente br0
creado, con ambos tap1
y tap2
agregado. Tengo un programa que inyecta paquetes ARP en el tap1
uso libpcap
. Wireshark muestra correctamente los paquetes que ingresan tap1
. Sin embargo, no aparece ningún paquete en tap2
. Intenté agregar la siguiente regla en ebtables:
sudo ebtables -I INPUT --log --log-level debug
No aparece ningún paquete en los registros. Agradeceré cualquier aporte.
EDITAR: Agregar más información. Inyectar paquetes falsos es de hecho la aplicación. Mi intención aquí es simular, completamente en software y sin máquinas virtuales, cómo se reenvían los paquetes a través de la pila del kernel de Linux. No estoy creando ningún espacio de nombres de red nuevo. ¿Quizás ese sea el problema?
Solo tengo dos procesos. El proceso de "lectura" tiene un descriptor de archivo abierto tap2
e intenta leerlo constantemente. El proceso de escritura tiene un descriptor de archivo abierto tap1
y espera que el usuario le solicite enviar la consulta ARP. La consulta ARP tiene una dirección IP de origen aleatoria. La dirección MAC de origen se establece como la dirección MAC de tap1
. Aquí está el resultado de tcpdump:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap1, link-type EN10MB (Ethernet), capture size 262144 bytes
^[[A07:19:57.752990 ARP, Request who-has google-public-dns-a.google.com tell 0.0.248.17, length 28
0x0000: ffff ffff ffff ba9c 0589 16ad 0806 0001
0x0010: 0800 0604 0001 ba9c 0589 16ad 0000 f811
0x0020: 0000 0000 0000 0808 0808
Lo he configurado tap1
y tap2
para no tener direcciones IP. ¿Podría ser el problema?
brctl addbr br0
ip tuntap add name tap1 mode tap
ip tuntap add name tap2 mode tap
brctl addif br0 tap1
brctl addif br0 tap2
ifconfig tap1 0.0.0.0 up
ifconfig tap2 0.0.0.0 up
ifconfig br0 10.0.1.1 netmask 255.255.255.0 broadcast 10.0.1.255
ip link set br0 up
ip link set tap1 up
ip link set tap2 up
Según la respuesta, verifiqué cómo adjuntar varias aplicaciones a tap2
. Noto esto: cuando ninguna aplicación usa tap1
o tap2
, ambas interfaces no tienen el indicador LOWER_UP configurado.
4: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
Cuando inicio las aplicaciones, el indicador LOWER_UP se establece:
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
Lamento que esto esté resultando largo, solo espero que haya suficiente información para entender el problema.
Respuesta1
Por si acaso, porque dijiste que eres un novato total: una interfaz tun (capa 3) o tap (capa 2) es el punto final de la interfaz de red de una aplicación, y la aplicación puede leer y escribir paquetes desde esta interfaz de red. Lo que creas ip tuntap add ...
o lo obsoleto tunctl
sonnombres persistentespara dichos puntos finales, normalmente seguirá ejecutando la aplicación y no hará nada a menos que la ejecute.
Como la aplicación interactúa con la interfaz de red como una cuestión de diseño, no hay necesidad de "inyectar" paquetes con una aplicación de terceros, a menos que se refiera a "inyectar" esta interacción normal que describí.
Además, si quieres jugar con las redes, te recomiendo usarespacios de nombres de redyquintos pares. Básicamente, puedes configurar muchas computadoras virtuales en tu computadora que pueden imitar la comunicación entre computadoras reales en una red.
Entonces, si desea hacer eso y no quiere jugar con su propia aplicación creando y recibiendo paquetes, no necesita una interfaz tun/tap.
Dicho esto, acabo de probar tu configuración, con una ligera variación porque no dijiste qué usas para "inyectar" paquetes: usé dos socat
s para crear el punto final de tap tap0a
y tap1a
luego los uní y usé otros dos socat
s en dos espacios de nombres diferentes para crear los paquetes correctos para mí. Deben estar en un espacio de nombres diferente, ya que los paquetes locales siempre se entregarán mediante loopback lo
.
Y como era de esperar, los dispositivos de derivación en puente funcionan bien.
Entonces supongo que el problema está en el paquete que está inyectando: dirección Ethernet incorrecta o no hay transmisión. Edite su pregunta con el tcpdump -xx ...
resultado cuando inyecte el paquete ARP.
¿O posiblemente le gustaría crear espacios de nombres de red y unir dos puntos finales de dos pares veth? Eso es mucho más sencillo.
Editar
El paquete ARP se ve bien. Parece que no hay ninguna aplicación conectada tap2
. Si lo hace ip link
, no debería ver una LOWER_UP
bandera para tap2
. Adivina: El puente detecta que el dispositivo está parcialmente activo y no envía paquetes a este puerto.
Intenta reemplazarlo con uno tap
quetieneuna aplicación conectada a él, algo así como
sudo socat TUN:10.0.2.2/24,tun-name=tapx,tun-type=tap,iff-up - | hexdump -C
(la 10.0.2.2/24
dirección no hace nada, pero socat
no funcionará si no especifica una dirección), y en otra terminal
sudo ip link set tapx master br0
(que reemplaza brctl addif
), luego inyecte su paquete varias veces y vea si obtiene un volcado hexadecimal en la primera ventana. Consulte también LOWER_UP
con ip link show dev tapx
.
Por cierto, ifconfig
y brctl
están desactualizados. Utilice ip
y bridge
en su lugar.
No asignar direcciones IP a los puertos del puente no importa, porque los puertos del puenteno tengo direcciones IP(Si se les asignó algo antes de ser esclavizados por un puente, se ignoran). Ver por ejemploaquí.
Respuesta2
Luché mucho con esto y creo que llegué a una solución. O, al menos, una mejor comprensión de lo que está pasando.
Es importante tener en cuenta que la única forma de entregar un paquete a una interfaz tap en el lado de recepción ("RX") es escribiendo ese paquete en el descriptor del socket.creado por el proceso que abrió el grifo(vía open("/dev/net/tun",...)
y ioctl
). Sólo un proceso puede tener este descriptor de archivo a la vez. Si un dispositivo de grifo está abierto y otro proceso intenta volver a abrir otro dispositivo de grifo con el mismo nombre, esa llamada al sistema fallará.
Entonces, cuando tienes cualquier otro proceso, como Wireshark, abrir un socket sin formato y luego vincularloesoa tap0
, sólo es capaz de escribir tráficoafueradel sistema (desde la perspectiva del núcleo). Es decir, Wireshark debería superar el TX
contador de tap0
y solo RX
los paquetes se reenviarán a la interfaz puenteada.
Puedes consultar los contadores de cada me gusta:
#!/bin/bash
for if in tap{0,1}; do
stats=/sys/class/net/$if/statistics/
rx=$(cat $stats/rx_packets)
tx=$(cat $stats/tx_packets)
echo "$if: rx=$rx, tx=$tx"
done
que genera algo como:
tap0: rx=0, tx=6
tap1: rx=0, tx=5
Entonces, en tu caso específico, sospecho que el problema está aquí:
Tengo un programa que inyecta
ARP
paquetestap1
usando libpcap. Wireshark muestra correctamente los paquetes que ingresantap1
. Sin embargo, no aparece ningún paquete entap2
.
¿Cómo se inyectan paquetes ARP en tap1? Supongo que Wireshark no está llamando fd = open("/dev/net/tun", ...)
y ioctl(fd, TUNSETIFF, ...)
, por lo que los paquetes enviados serán TX y, por lo tanto, no estarán puenteados.
Necesitará el programa que se abre tap0
para escribir paquetes en tap0
el descriptor de archivo de para que esos paquetes se reenvíen br0
y aparezcan en tap1
.