Dans le réseau local, vous devez souvent savoir sur quel port du commutateur se trouve l'adresse MAC spécifique de l'appareil. Le problème est facilement résolu s'il y a plusieurs commutateurs dans le réseau, mais quand il y en a plus de 30, tout devient beaucoup plus compliqué. Je souhaite partager un petit script Python qui recherche l'adresse MAC souhaitée sur le réseau et renvoie le nom et le port du commutateur sur lequel ce MAC est enregistré.

La critique constructive est la bienvenue. Détails sous la coupe.
Si la conception du réseau est effectuée correctement, c'est-à-dire le commutateur racine
CORE , auquel les commutateurs de distribution
DS (Distribution Switch) sont connectés, et à eux, à leur tour, les commutateurs de niveau d'accès
AS (Access Switch). Cette règle n'est pas toujours vraie; les commutateurs d'accès peuvent être connectés en série. Dans tous les cas, le port du commutateur en amont contient toutes les adresses MAC des périphériques connectés au commutateur en aval.
Par exemple, si le périphérique qui nous intéresse est connecté au commutateur
AS3 , puis, en commençant la recherche avec
CORE , nous trouverons cette adresse sur le port menant à
DS1 . En passant à
DS1 , nous trouverons ce MAC sur le port menant à
AS2 , en passant à
AS2 , nous verrons qu'il nous mène à
AS3 , et seulement sur
AS3, nous trouverons le port spécifique auquel le périphérique d'intérêt est connecté.
Je ne voulais pas tout faire à la main, trier tous les commutateurs en boucle et déterminer où se trouve la liaison montante et où pas trop, donc la solution suivante est née, que je veux partager.
Un peu de théorie.
Pour trouver le MAC
08: 62: 66: c7: b3: 45 sur le commutateur Juniper, exécutez la commande suivante:
show ethernet-switching table | match 08:62:66:c7:b3:45
S'il existe un tel MAC, la réponse sera la suivante:
vlan151 08:62:66:c7:b3:45 D - xe-0/0/23.0
La dernière colonne sera le nom de l'interface du commutateur sur lequel le MAC est enregistré. Mais comment comprendre où mène cette interface? Et voici les
descriptions d'interface à la rescousse. Ce sont des lignes du fichier de configuration du commutateur qui vous permettent d'attribuer des étiquettes de texte aux interfaces.
L'équipe
show interfaces xe-0/0/23 descriptions
montrera ce qui suit:
Interface Admin Link Description xe-0/0/23 up up SW>DS1
Dans la configuration, nous indiquons que cette interface conduit au commutateur aval:
set interfaces xe-0/0/23 description SW>DS1
Implémentation
Le script proposé fera ce qui suit:
- Connectez-vous via SSH au commutateur racine
- vérifier sur quelle interface se trouve l'adresse MAC transmise dans les paramètres;
- Vérifiez la description de cette interface;
- si l'interface mène au commutateur, accédez au commutateur suivant de la chaîne de manière récursive.
Ainsi, le script passera par tous les commutateurs réseau, à partir du noyau, et essaiera de trouver le MAC souhaité. Pour un fonctionnement réussi, il suffit de maintenir à jour les descriptions des interfaces et la topologie peut être de presque n'importe quelle complexité.
Un exemple de script:
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"}
S'il n'y a pas de MAC, nous obtenons
{"host": "CORE", "iface": "none"}
La dernière ligne est le commutateur et le port qui nous intéressent, mais en même temps, nous pouvons suivre l'intégralité du chemin de recherche.
Le code complet est sous le spoiler, merci de votre attention.
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: