Trabajamos con dispositivos que están flasheados (de fábrica) mediante TFTP en una conexión de red USB.
El servidor tiene una dirección fija 192.168.2.100 y el dispositivo una dirección fija 192.168.2.101. Cuando arranca se conecta para descargar el firmware.
En la configuración actual, sólo un dispositivo puede funcionar al mismo tiempo. Pero me gustaría hacer posible flashear tantos dispositivos como podamos conectar (porque podemos tener requisitos de flasheo enormes).
Para evitar el problema de enrutamiento, hice una versión de xinetd que establece setsockopt en SO_BIND_DEVICE.
Pero lo que no hice fue que Linux no puede manejar las solicitudes ARP en ambas interfaces al mismo tiempo.
Si hago "ping 192.168.2.101 -I usb0" y "ping 192.168.2.101 -I usb1" al mismo tiempo, funcionará en una interfaz:
ARP, Request who-has sk tell 192.168.2.100, length 28
ARP, Reply 192.168.2.101 is-at 7a:0f:66:7c:fc:2c (oui Unknown), length 28
IP 192.168.2.100 > 192.168.2.101: ICMP echo request, id 21807, seq 1, length 64
IP 192.168.2.101 > 192.168.2.100: ICMP echo reply, id 21807, seq 1, length 64
Pero por otro lado no lo hará:
IP 192.168.2.100 > 192.168.2.101: ICMP echo request, id 31071, seq 1, length 64
ARP, Request who-has 192.168.2.100 tell 192.168.2.101, length 28
ARP, Request who-has 192.168.2.100 tell 192.168.2.101, length 28
IP 192.168.2.100 > 192.168.2.101: ICMP echo request, id 31071, seq 2, length 64
IP 192.168.2.100 > 192.168.2.101: ICMP echo request, id 31077, seq 1, length 64
ARP, Request who-has 192.168.2.100 tell 192.168.2.101, length 28
El servidor no parece responder a la solicitud ARP.
Así es como se maneja la conexión desde el dispositivo en el servidor con un script /etc/network/if-up.d/000-first:
ifconfig $IFACE up
ifconfig $IFACE 192.168.2.100
PID=/var/run/xinetd-$IFACE.pid
# this is the modified xinetd version to bind on one address
kill -9 `cat $PID`
xinetd -pidfile $PID -interface $IFACE
# I tried this to force the handling of ARP table per interface, but it doesn't change anything:
# /usr/sbin/arpd -b /tmp/$IFACE.db -a 3 -k $IFACE
Aquí está la versión modificada de xinetd: https://github.com/fclairamb/xinetd/commit/1f5c1e8f9944e372b137e6aa46247f8de807bece#L8R253
Respuesta1
Primero, si no ha probado proxy arp por sí solo, debería probar proxy arp.
echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp
Opción 1: alteración de alguna ruta de marca/política
Si el proxy arp por sí solo no funcionó, no puedo garantizar que funcione, pero creo que vale la pena intentarlo. Lo que voy a describir es cómo configurar el enrutamiento de políticas para vincular respuestas basadas en la interfaz de entrada usando conntrack. Describiré cómo configurarlo para dos interfaces y debería ser bastante fácil expandirlo a cualquier número. Por otro lado, en lugar de funcionar, puede simplemente confundirse enormemente y no hacer nada (probablemente porque la tabla arp del kernel no sabe que debe almacenar en caché los pares ip/mac por dispositivo). Si eso sucede, prueba el segundo método, más feo.
Primero, configure algunas reglas de mangle de connmark:
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j ACCEPT
En /etc/iproute2/rt_tables agregue dos tablas, 100 y 101, etiquételas usb0 y usb1
100 usb0
101 usb1
Para cada una de estas tablas agregue lo siguiente (reemplace <N> con el número apropiado):
ip route add 192.168.2.0/24 dev usb<N> table usb<N>
ip rule add fw <N> table usb<N>
iptables -t mangle -A PREROUTING -i usb<N> -j MARK --set-mark <N>
No estoy seguro, pero es posible que necesites configurar una interfaz ficticia como esta para que tu demonio tftp escuche:
modprobe dummy
ifconfig dummy0 192.168.2.100/32 up
echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp
sysctl net.ipv4.ip_forward=1
iptables -I FORWARD -s 192.168.2.100 -j ACCEPT
iptables -I FORWARD -d 192.168.2.100 -j ACCEPT
Ahora prueba con dos dispositivos. Si funciona, excelente, de lo contrario prueba el siguiente método:
Opción 2: contenedor kvm por dispositivo de red usb
La opción 2 es más fea e implica algunos puentes y qemu/kvm. virt-manager
Es probablemente la forma más sencilla de crear estas cosas.
Cree dispositivos tap y puentes, uno por interfaz USB.
tunctl -t tap<N>
brctl addbr usb<N>br
brctl addif usb<N>br tap<N>
brctl addif usb<N>br usb<N> # this may need to be done each time the usb device is connected/disconnected.
Cree un archivo de imagen kvm o un CD de arranque diseñado para ser de solo lectura y que aloje su servidor tftp y su imagen... u omita el modo de solo lectura y cree un archivo de imagen por máquina virtual (sería mejor usar instantáneas para esto, pero eso es más). de alcance que el que tiene esta respuesta).
Ejecute un kvm usando la interfaz tap y su archivo de imagen y pruebe la conectividad de red USB.
Comparación
Si la ruta connmark/policy funcionó, es mucho más fácil mantener sincrónicamente el repositorio tftp. Con KVM, es posible que necesite tener un repositorio por imagen de VM (a menos que pase un directorio de solo lectura a cada VM, lo cual es factible). La ruta Connmark/policy es un poco más complicada, pero también solo requiere un servidor tftp, aunque si sus puertos no son lo suficientemente aleatorios, conntrack podría confundirse y sobrescribirse si hay una superposición de puertos (o puede que no). Por otro lado, la conexión a kvms requiere mucha más memoria; una máquina virtual completa por dispositivo USB conectado, pero es mucho más probable que funcione siempre porque la máquina virtual tiene una pila de red aislada completa con la que trabajar, mientras que el kernel del host solo tiene que pasar paquetes de un lado a otro a través de un puente, especialmente si se trata de un filtrado de puentes. esta apagado.
Esperemos que uno de estos dos funcione para usted.