Layer2 Loop aufspüren innerhalb eines BATMAN und Tunneldigger L2TP Netzes

Loops im Netzwerk finden und eliminieren

Entstehung von Loops

Loops entstehen, wenn man innerhalb eines Layer2 Netzes eine Schleife herstellt. Dies kann zum Beispiel passieren, wenn man zwei Freifunk Router mit einem Kabel an den Client Ports (beim 841 also die gelben Ports) miteinander verbindet.

Auswirkungen

Loops führen zu einer starken Einschränkung der Stabilität und Performanz des gesamten Netzwerkes.
Zusätzlich dazu kann man auf den Gateways folgende Zeile im dmesg beobachten:

ff-lev: received packet on mesh-lev with own address as source address (addr:02:ca:fe:76:03:01, vlan:0)

Die MAC-Addresse in Klammern sollte hierbei die MAC Addresse des Gateways sein.

Auf dem betroffenen Knoten kann man folgende (oder ähnliche) dmesg Zeile beobachten:

br-client: received packet on eth0 with own address as source address

Wie kann man nun aber identifizieren welcher Knoten im Netzwerk für den Loop verantwortlich ist?

Vorgehen

1. Verbindung mit dem betroffenen Netzwerk herstellen

Eine Verbindung, zum beispiel per WLAN, herstellen um eine Innensicht des Netzwekes zu erhalten.
Grundsätzlich ließe sich hier auch vom Gateway aus auf das Interface schauen.

2. Verwendung von Wireshark zur Identifikation, dass ein Loop besteht und welche MAC Adresse involviert ist.

Am einfachsten erkennbar wird ein Loop durch ARP Pakete mit der Mitteilung duplicate use of 10.76.1.3 detected!.
Die IP sollte entsprechend die IP eures Gateways sein.
Wireshark zeigt ebenfalls in den Details des Paketes an, welche MAC Addresse ebenfalls diese IP beansprucht. In diesem Fall ist dies die 16:6e:0e:76:03:01

3. Herausfinden über welchen Verbindungsweg der loopende Knoten am Gateway anliegt

Hierzu verwenden wir die batctl Tools.
Mithilfe von batctl tr können wir schauen welchen weg die Pakete zu der gefundenen MAC Addresse nehmen:

[felix@gw3 ~]$ sudo batctl -m mesh-lev tr 16:6e:0e:76:03:01
traceroute to 16:6e:0e:76:03:01 (ce:3b:36:ab:d2:5b), 50 hops max, 20 byte packets
 1: 02:ca:fe:76:01:00  0.636 ms  0.497 ms  0.649 ms
 2: ce:3b:36:ab:d2:5b  65.976 ms  95.890 ms  80.734 ms

Wie wir hier sehen können fühlt sich der Knoten mit der MAC Addresse ce:3b:36:ab:d2:5b ultimativ verantwortlich für alle Pakete, die an 16:6e:0e:76:03:01 gerichtet sind. Die Höhe des Pings sagt uns auch, dass der loopende Knoten vermutlich per VPN angebunden ist.
Jedoch sehen wir auch, dass ein weiterer Hop zwischen dem loopenden Knoten und unserem Gateway liegt. In diesem Fall ist das ein weiteres Gateway (gw1), über das der loopende Knoten tatsächlich angebunden ist. Zur weiteren Fehleranalyse müssen wir daher auf das gw1 zugreifen. Sollte im Traceroute nur ein Hop angezeigt werden bedeutet das, dass der loopende Knoten direkt mit dem Gateway verbunden ist auf dem wir gerade arbeiten.

4. Herausfinden an welchem Bridgeport der Router anliegt

Mit der MAC Addresse des loopenden Knotens im Gepäck schauen wir auf gw1 nach dem Bridgeport an dem die betreffende MAC anliegt:

[felix@gw1 ~]$ sudo brctl showmacs tun-lev | grep ce:3b:36:ab:d2:5b
  8	ce:3b:36:ab:d2:5b	no		   0.05

tun-lev ist hierbei die Bridge, in dem alle Tunneldigger L2TP Interfaces zusammengefasst sind.
Die erste Zahl in der Zeile benennt den Bridgeport (hier: Port 8).

5. Herausfinden welches L2TP Interface der Bridgeport ist

Mit der Nummer des Bridgeports alleine können wir nicht viel anfangen, wir müssen also herausfinden wie das L2TP Interface heißt, das sich hinter diesem Bridgeport verbirgt.
Hierbei hilft uns der Kernel und dmesg:

[felix@gw1 ~]$ dmesg | grep "port 8" | tail -n1
[11144.591846] tun-lev: port 8(l2tp162-162) entered forwarding state

6. Herausfinden welcher Knoten hinter dem L2TP Interface hängt

Hierzu kann das Syslog von Tunneldigger befragt werden:

[felix@gw1 ~]$ sudo journalctl -u tunneldigger-broker@leverkusen --since "10:00" | grep -E "Creating tunnel.+with id 162" | tail -n1
Jul 03 11:55:31 gw1.fflev.de python2[1314]: [INFO/tunneldigger.broker] Creating tunnel x.x.x.x:53001 (0019995fffff) with id 162.

Der problematische Knoten ist also 0019995fffff.
Über die Karte oder eine nodes.json lässt sich anhand der Knoten ID auch herausfinden welcher Knoten das ist und eventuell auch wo er steht und wie der Besitzer zu erreichen ist.
Beispiel-Link für Meshviewer: https://map.fflev.de/#/de/map/0019995fffff

6. Den Knoten per Tunneldigger Blackliste aussperren

Wie im L2TP/Tunneldigger Serverdoku-Thread beschrieben kann eine Blackliste im Up-Hook Skript des Tunneldiggers den entsprechenden Knoten anhand seiner ID aussperren um somit erst mal Ruhe im Netz zu haben.

Ggf. ist es notwendig mehr als einen Knoten auszusperren.

12 „Gefällt mir“

Wie bekomme ich die MAC vom Knoten mit loop denn vom GW aus?

tcpdump -i bridge -w debug.cap -c 100 arp
Dann die Datei herunter laden und in Wireshark öffnen, oder was meintest Du?

Direkt auf der Shell auf dem gw.

Dafür kannst du auch tcpdump heranziehen:
tcpdump -en -i ff-lev arp | grep "tell 10.76.1.3"
ff-lev ist das BATMAN Interface, 10.76.1.3 ist eine IP eines Gateways.

Im Falle eines Loops taucht mehr als eine Source MAC auf. Beispiel:

18:00:54.793240 02:ca:fe:76:03:01 > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 10.76.187.187 tell 10.76.1.3, length 28
18:00:54.798699 06:6e:0e:76:03:01 > Broadcast, ethertype ARP (0x0806), length 60: Request who-has 10.76.132.20 tell 10.76.1.3, length 46

Man beachte auch die größere length des Duplikates.

Mit diesen Infos kann mann dann ab Punkt 3 aus dem obigen Guide ansetzen.

1 „Gefällt mir“

Perfekt danke

Auf unseren debian 8 Gateways in Kiel ist /var/log/dmesg immer leer!

Wie kann ich auf dem gateway (am besten per script) eroieren ob es im Netz überhaupt loops gibt?

tail -f /var/log/messages
tail -f /var/log/syslog

oder auf aktuellen systemen

journctl -k
journctl -n

Am besten ginge tatsächlich sporadisch (vllt. alle 5 Minuten) ein Script für ein paar Sekunden laufen zu lassen, das für die IPv4 Addressen der Gateways prüft ob die zu erwartende MAC Addresse als Source MAC auftritt.

Hättest du aber einen Loop im Netzwerk wäre das durchaus sehr spürbar auf den Clients (extrem langsamer Seitenaufbau, Anlaufschwierigkeiten beim Speedtest).

Ein weiterer Effekt hierbei ist, dass bei einem Loop alle IP Addressen von Gateways gekapert werden, an denen der loopende Knoten nicht hängt.

Verwende mal den Befehl dmesg statt in das Log zu schauen. Vielleicht wird das nicht weggeschrieben bei euch.

on our vpn4 i got

$  dmesg -wH|grep  "received packet"
[Jul12 23:15] br-ffki: received packet on bat-ffki with own address as source address

So we have to do something there too?

Wenn das nachhaltig auftritt dann schon. Dann müsste das Vorgehen wie hier beschrieben eigentlich funktionieren.
Beachte, dass du den Loop allerdings nur aufspüren kannst solange er besteht.

Wie produziert man so eine Loop, also versehentlich?
Wie müsste man dort Router zusammenstöpseln?

Das passiert bei uns in den Flüchtlingsheimen manchmal, dass die Leute da bei Ausfällen wild an den Routern rumstöpseln, die im Publikumsverkehr hängen. Bzw. versuchen sie auch direkt Uplink mit ihren Endgeräten zu erhalten.
Je nach Installation liegt bei uns in den Heimen aber nur Client oder Mesh netz am LAN auf.

Um das willentlich herbeizuführen müsstest du zwei Router (idealerweise beide mit Uplink, dann macht es mehr Spaß den Loop zu finden :yum:) an den Clientports miteinander per Patchkabel verbinden. Also beispielsweise einen 841er mit einem Patchkabel an einem gelben Port mit einem gelben Port eines anderen 841 verbinden.

Aus Versehen kann es passieren, wenn du versuchst Mesh on LAN zu machen ohne das Client Netz auf dem Switch zu deaktivieren.
Wenn man hierzu die Gluon Doku heranzieht könnte folgender Fehler passieren:
Korrektes Snippet um Mesh on LAN zu aktivieren:

uci set network.mesh_lan.disabled=0
for ifname in $(cat /lib/gluon/core/sysconfig/lan_ifname); do
  uci del_list network.client.ifname=$ifname
done
uci commit network

Führt man hingegen nur uci set network.mesh_lan.disabled=0 aus ohne die for-Schleife baut man einen Loop.
Ein Eintreten dieses Zustands wäre damit auch denkbar wenn bei einem sysupgrade (ob Autoupdater oder manuell) irgendwie die Config auf dem Router zerschossen wird (wild gewordene Upgrade Scripte, umbenannte LAN Interfaces, geänderte MAC Adressen(berechnung) o.Ä.) und das LAN Interface wieder auf die Client Bridge gelegt wird.

4 „Gefällt mir“

Danke für die ausführliche Antwort.
Ein „brclient auf brbat“ hatte mir sich gereicht. Wie das passiert und wie man einen Mapserver dazu bringen könnte solche Router vollautomatisch zu verpetzen:

hatten wir vor 2-3 Jahren schonmal diskutiert, aber hat niemand gebaut. Man müsste die batctl tg gegen den Linkoutput des respondd laufen lassen.

1 „Gefällt mir“

super idee, hab ich hier mal als issue erstellt:

https://github.com/ffrgb/meshviewer/issues/258

1 „Gefällt mir“

Das Problem was gesehen wurde: man braucht sowohl die json-dateien, die vom respondd eingesammelt wurden (die hat man heute schon), man braucht aber auch output von „batctl tg“ & Co. Und dafür braucht es root-rechte. (Dass man den Mapserver unter solchen nicht laufen lassen möchte: Nachvollziehbar)
Man müsste also einen separaten service haben, der die TransGlobal in ein json auf die platte dumpt.
Dazu kommt ja dann, dass das Outputformat von batctl nicht versionsstabil ist (kann man bei screenscraping nicht drauf hoffen… ist hier aber einfach blöd. Ich weiss, dass man an die Infos auch anders kommt, aber dann wird’s mindestens eine python-Nummer, die die Installatin langfristig komplexer werden lässt.)

Ausserdem muss man per batman in den Domains hängen. Was ein Problem ist, für Installationen, die mehrere Domains/Hoods abdecken mit unterschiedlichen batman-versionen, wo der Mapserver dann per client-bridge in der Domain hängt. Dort bräuchte es dann also einen „abgesetzten Probe“

1 „Gefällt mir“

Map ist ja kein server sondern Client und hat kein Daemon. Nach meiner Meinung die falsche Anlaufstelle. Yanic sammelt, entweder gleich da bzw. via Alerts im Grafana hätte schon ein Berg an Schnittstellen für Notificatrions usw.

Ich möchte an dieser Stelle auch noch anmerken, dass man ein ganz anderes Problemfeld hat, wenn ein Knoten den Loop Verursacht, der nur Mesht.
Entweder muss die Mesh-Verbindung dann unterbunden werden oder alle mit diesem Knoten meshenden Knoten müssen ausgesperrt werden.

On a Sidenote: Kann man in Discourse den ersten Beitrag als Wiki einstellen, sodass auch andere Leute bearbeiten können?

Das ist dann die Frage, wie man das mitigiert, wo Batman da zentral wenig Möglichkeiten bietet… und man mit ebtables auch nicht den durchlaufenden Batman-Traffic filtern kann.

Für 802.11s kommt mir spontan Setting plink_action for 802.11s neighbours · Issue #421 · freifunk-gluon/gluon · GitHub in den Sinn.