Im lokalen Netzwerk müssen Sie häufig herausfinden, an welchem Port des Switches sich die spezifische MAC-Adresse des Geräts befindet. Das Problem ist leicht zu lösen, wenn mehrere Switches im Netzwerk vorhanden sind. Wenn jedoch mehr als 30 Switches vorhanden sind, wird alles viel komplizierter. Ich möchte ein kleines Python-Skript freigeben, das nach der gewünschten MAC-Adresse im Netzwerk sucht und den Namen und den Port des Switches zurückgibt, auf dem dieser MAC registriert ist.

Konstruktive Kritik ist willkommen. Details unter dem Schnitt.
Wenn das Netzwerkdesign korrekt ausgeführt wird,
dh der
CORE- Root-Switch, mit dem die
DS- Verteilungsschalter (Verteilungsschalter) verbunden sind, und mit diesen wiederum die Zugriffsebenenschalter
AS (Zugriffsschalter). Diese Regel gilt nicht immer, Zugriffsschalter können in Reihe geschaltet werden. In jedem Fall enthält der Upstream-Switch-Port alle MAC-Adressen der an den Downstream-Switch angeschlossenen Geräte.
Wenn beispielsweise das für uns interessante Gerät mit dem
AS3- Switch verbunden ist, finden wir diese Adresse beim Starten der Suche mit
CORE an dem Port, der zu
DS1 führt . Wenn wir zu
DS1 gehen , finden wir diesen MAC an dem Port, der zu
AS2 führt , und zu
AS2 . Wir werden sehen, dass er uns zu
AS3 führt , und nur bei
AS3 finden wir den spezifischen Port, an den das interessierende Gerät angeschlossen ist.
Ich wollte nicht alles von Hand machen, alle Schalter in einer Schleife sortieren und feststellen, wo sich der Uplink befindet und wo nicht. Daher wurde die nächste Lösung geboren, die ich teilen möchte.
Ein bisschen Theorie.
Führen Sie den folgenden Befehl aus, um den MAC
08: 62: 66: c7: b3: 45 auf dem Juniper-Switch zu finden:
show ethernet-switching table | match 08:62:66:c7:b3:45
Wenn es einen solchen MAC gibt, lautet die Antwort wie folgt:
vlan151 08:62:66:c7:b3:45 D - xe-0/0/23.0
Die letzte Spalte ist der Name der Schnittstelle des Switches, auf dem der MAC registriert ist. Aber wie kann man verstehen, wohin diese Schnittstelle führt? Und hier kommen
Schnittstellenbeschreibungen zur Rettung. Dies sind Zeilen in der Switch-Konfigurationsdatei, mit denen Sie Schnittstellen Textbeschriftungen zuweisen können.
Das Team
show interfaces xe-0/0/23 descriptions
zeigt Folgendes:
Interface Admin Link Description xe-0/0/23 up up SW>DS1
In der Konfiguration geben wir an, dass diese Schnittstelle zum Downstream-Switch führt:
set interfaces xe-0/0/23 description SW>DS1
Implementierung
Das vorgeschlagene Skript führt Folgendes aus:
- Stellen Sie über SSH eine Verbindung zum Root-Switch her
- Überprüfen Sie, auf welcher Schnittstelle sich die in den Parametern übergebene MAC-Adresse befindet.
- Überprüfen Sie die Beschreibung dieser Schnittstelle.
- Wenn die Schnittstelle zum Switch führt, greifen Sie rekursiv auf den nächsten Switch in der Kette zu.
Daher durchläuft das Skript alle Netzwerk-Switches, beginnend mit dem Kernel, und versucht, den gewünschten MAC zu finden. Für einen erfolgreichen Betrieb reicht es aus, die Beschreibungen der Schnittstellen auf dem neuesten Stand zu halten, und die Topologie kann nahezu beliebig komplex sein.
Ein Beispiel für ein Skript:
python findmac.py 00:17:fc:21:e8:f9 {"host": "CORE", "iface": "xe-0/0/23.0", "description": "SW>DS1"} {"host": "DS1", "iface": "xe-0/0/11.0", "description": "SW>AS2"} {"host": "AS2", "iface": "xe-1/0/1.0", "description": "SW>AS3"} {"host": "AS3", "iface": "ge-0/0/26.0", "description": "none"}
Wenn es keinen MAC gibt, bekommen wir
{"host": "CORE", "iface": "none"}
Die letzte Zeile ist der Switch und Port, der uns interessiert, aber gleichzeitig können wir den gesamten Suchpfad verfolgen.
Der vollständige Code befindet sich unter dem Spoiler. Vielen Dank für Ihre Aufmerksamkeit.
findmac.py import paramiko import time import sys import json import threading import logging login = 'user1' password = 'pass1234' searchpass = [] port = 22 class LogPipe(threading.Thread): def __init__(self, level): threading.Thread.__init__(self) self.daemon = False self.level = level self.fdRead, self.fdWrite = os.pipe() self.pipeReader = os.fdopen(self.fdRead) self.start() def fileno(self): return self.fdWrite def run(self): for line in iter(self.pipeReader.readline, ''): logging.log(self.level, line.strip('\n')) self.pipeReader.close() def close(self): os.close(self.fdWrite) def execute_ssh_command(host, port, username, password, command): try: