Dasselbe Netzwerk auf einer anderen Schnittstelle

Dasselbe Netzwerk auf einer anderen Schnittstelle

Wir arbeiten mit Geräten, die (werkseitig) per TFTP über eine USB-Netzwerkverbindung geflasht werden.

Der Server hat eine feste Adresse von 192.168.2.100 und das Gerät eine feste Adresse von 192.168.2.101. Beim Start stellt es eine Verbindung her, um die Firmware herunterzuladen.

Im aktuellen Setup kann nur ein Gerät gleichzeitig funktionieren. Aber ich möchte es möglich machen, so viele Geräte zu flashen, wie wir anschließen können (weil wir einen enormen Flash-Bedarf haben können).

Um das Routing-Problem zu umgehen, habe ich eine xinetd-Version erstellt, die ein Setsockopt auf SO_BIND_DEVICE setzt.

Was ich jedoch nicht erwartet hatte, ist, dass Linux nicht in der Lage ist, die ARP-Anfragen auf beiden Schnittstellen gleichzeitig zu verarbeiten.

Wenn ich gleichzeitig „ping 192.168.2.101 -I usb0“ und „ping 192.168.2.101 -I usb1“ ausführe, funktioniert es auf einer Schnittstelle:

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

Aber andererseits wird es das nicht:

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

Der Server scheint nicht auf die ARP-Anfrage zu antworten.

So wird die Verbindung vom Gerät auf dem Server mit einem /etc/network/if-up.d/000-first-Skript gehandhabt:

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 

Hier ist die geänderte xinetd-Version: https://github.com/fclairamb/xinetd/commit/1f5c1e8f9944e372b137e6aa46247f8de807bece#L8R253

Antwort1

Wenn Sie Proxy-ARP noch nicht allein ausprobiert haben, sollten Sie es zunächst mit Proxy-ARP versuchen.

echo 1 > /proc/sys/net/ipv4/conf/all/proxy_arp

Option 1: einige Connmark/Policy-Routenmanipulationen

Wenn Proxy-ARP allein nicht funktioniert hat, kann ich nicht garantieren, dass das hier funktioniert, aber ich denke, einen Versuch ist es wert. Ich werde jetzt beschreiben, wie man Policy Routing einrichtet, um Antworten basierend auf der Eingabeschnittstelle mit Conntrack zu binden. Ich werde beschreiben, wie man es für zwei Schnittstellen einrichtet, und es sollte einfach genug sein, es auf eine beliebige Zahl zu erweitern. Andererseits kann es, anstatt zu funktionieren, einfach nur mächtig durcheinander geraten und überhaupt nichts tun (wahrscheinlich, weil die Kernel-ARP-Tabelle nicht weiß, dass sie IP/Mac-Paare pro Gerät zwischenspeichern soll). Wenn das passiert, versuchen Sie die zweite, hässlichere Methode.

Richten Sie zunächst einige Connmark-Mangle-Regeln ein:

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

Fügen Sie in /etc/iproute2/rt_tables zwei Tabellen hinzu, 100 und 101, und beschriften Sie sie mit usb0 und usb1

100    usb0
101    usb1

Fügen Sie für jede dieser Tabellen Folgendes hinzu (ersetzen Sie <N> durch die entsprechende Nummer):

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>

Ich bin nicht sicher, aber Sie müssen möglicherweise eine Dummy-Schnittstelle wie die folgende einrichten, auf der Ihr TFTP-Daemon lauschen kann:

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

Testen Sie nun mit zwei Geräten. Wenn es funktioniert, ausgezeichnet, andernfalls versuchen Sie die nächste Methode:

Option 2: KVM-Container pro USB-Netzgerät

Option 2 ist hässlicher und erfordert einige Überbrückungen und QEMU/KVM. virt-managerDies ist wahrscheinlich die einfachste Möglichkeit, diese Dinge zu erstellen.

Erstellen Sie TAP-Geräte und Bridges, eines pro USB-Schnittstelle.

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.

Erstellen Sie eine KVM-Image-Datei oder eine Boot-CD, die schreibgeschützt ist und Ihren TFTP-Server und Ihr Image hostet. Oder lassen Sie den Schreibschutz weg und erstellen Sie eine Image-Datei pro VM (besser wäre es, hierfür Snapshots zu verwenden, aber das geht über den Rahmen dieser Antwort hinaus).

Führen Sie einen KVM mit der TAP-Schnittstelle und Ihrer Image-Datei aus und testen Sie die USB-Netzwerkkonnektivität.

Vergleich

Wenn Connmark/Policy Route funktioniert, ist es viel einfacher, das TFTP-Repository synchron zu verwalten. Bei KVM benötigen Sie möglicherweise ein Repository pro VM-Image (es sei denn, Sie geben ein schreibgeschütztes Verzeichnis an jede VM weiter, was machbar ist). Connmark/Policy Route ist etwas komplizierter, erfordert aber auch nur einen TFTP-Server. Wenn Ihre Ports jedoch nicht zufällig genug sind, könnte Conntrack durcheinander kommen und überschreiben, wenn es eine Portüberlappung gibt (oder auch nicht). Andererseits erfordert die Überbrückung zu KVMs viel mehr Speicher; eine ganze VM pro angeschlossenem USB-Gerät, aber es ist viel wahrscheinlicher, dass es jedes Mal funktioniert, da die VM mit einem ganzen isolierten Netzwerkstapel arbeiten kann, während der Host-Kernel nur Pakete über eine Brücke hin und her schicken muss, was insbesondere dann gilt, wenn die Brückenfilterung ausgeschaltet ist.

Hoffentlich funktioniert eine dieser beiden für Sie.

verwandte Informationen