Pencarian Alamat MAC pada Switch Juniper

Di jaringan lokal, Anda sering perlu mencari tahu di port mana switch alamat MAC spesifik perangkat berada. Masalahnya mudah diselesaikan jika ada beberapa switch di jaringan, tetapi ketika ada lebih dari 30 dari mereka, semuanya menjadi jauh lebih rumit. Saya ingin berbagi skrip Python kecil yang mencari alamat MAC yang diinginkan di jaringan dan mengembalikan nama dan port switch di mana MAC ini terdaftar.



Kritik konstruktif dipersilahkan. Detail di bawah potongan.

Jika desain jaringan dilakukan dengan benar, yaitu, sakelar CORE root, ke mana sakelar distribusi DS (Distribution Switch) terhubung, dan pada gilirannya, level akses AS (Access Switch) beralih. Aturan ini tidak selalu benar, sakelar akses dapat dihubungkan secara seri. Dalam kasus apa pun, port sakelar hulu berisi semua alamat MAC perangkat yang terhubung ke sakelar hilir.

Misalnya, jika perangkat yang menarik bagi kami terhubung ke switch AS3 , maka, memulai pencarian dengan CORE , kami akan menemukan alamat ini pada port yang mengarah ke DS1 . Pergi ke DS1 , kita akan menemukan MAC ini di port yang mengarah ke AS2 , pergi ke AS2 , kita akan melihat bahwa itu membawa kita ke AS3 , dan hanya pada AS3 kita akan menemukan port spesifik di mana perangkat yang terkait terhubung.

Saya tidak ingin melakukan semuanya dengan tangan, memilah-milah semua sakelar dalam satu lingkaran dan menentukan di mana uplink berada dan di mana tidak terlalu, sehingga solusi berikutnya lahir, yang ingin saya bagikan.

Sedikit teori.


Untuk menemukan MAC 08: 62: 66: c7: b3: 45 pada sakelar Juniper, jalankan perintah berikut:

show ethernet-switching table | match 08:62:66:c7:b3:45 

Jika ada MAC seperti itu, jawabannya adalah sebagai berikut:

 vlan151 08:62:66:c7:b3:45 D - xe-0/0/23.0 

Kolom terakhir adalah nama antarmuka sakelar tempat MAC terdaftar. Tetapi bagaimana memahami di mana antarmuka ini mengarah? Dan di sini Deskripsi Antarmuka datang untuk menyelamatkan. Ini adalah baris dalam file konfigurasi sakelar yang memungkinkan Anda menetapkan label teks untuk antarmuka.

Tim

 show interfaces xe-0/0/23 descriptions 

akan menunjukkan yang berikut:

 Interface Admin Link Description xe-0/0/23 up up SW>DS1 

Dalam konfigurasi, kami menunjukkan bahwa antarmuka ini mengarah ke sakelar hilir:

 set interfaces xe-0/0/23 description SW>DS1 

Implementasi


Skrip yang diusulkan akan melakukan hal berikut:

  1. Terhubung melalui SSH ke sakelar root
  2. periksa antarmuka yang alamat MAC yang dilewati dalam parameter berada;
  3. Periksa Deskripsi antarmuka ini;
  4. jika antarmuka mengarah ke sakelar, akses sakelar berikutnya dalam rantai secara rekursif.

 #       searchpass = [] #main      MAC-    checkswitch,           MAC-.       searchpass   json. def main(argv): mac_addr = argv[0] checkswitch('CORE',mac_addr) for switch in searchpass: print (json.dumps(switch, ensure_ascii=False)) if __name__ == "__main__": main(sys.argv[1:]) #   MAC- def checkswitch(hostname,mac_addr): try: #    ,  host    returnvalue = {} returnvalue['host']=hostname #sendCommand      SSH     MAC-    answer = sendCommand(hostname,'show ethernet-switching table | match '+mac_addr) #   ,      #vlan151 08:62:66:c7:b3:45 D - xe-0/0/23.0 if(answer!=0): iface = answer.split()[4] returnvalue['iface']=iface # description ,    2  .0       #xe-0/0/23 up up SW>DS01 answer = sendCommand(hostname,'show interfaces '+iface[:-2]+' descriptions | last 1 | no-more') iface = answer.split() # description   ,      ,     SW>.  ,   3 ,         . if(len(iface)>2): iface=iface[3] returnvalue['description']=iface else: returnvalue['description']='none' searchpass.append(returnvalue) if (iface[:3]=='SW>'): checkswitch(iface[3:],mac_addr) else: returnvalue['iface']='none' searchpass.append(returnvalue) except Exception as e: print(e) 

Dengan demikian, skrip akan melalui semua switch jaringan, mulai dari kernel, dan mencoba untuk menemukan MAC yang diinginkan. Untuk operasi yang sukses, itu cukup untuk menjaga deskripsi pada antarmuka tetap up to date, dan topologi dapat dari hampir semua kompleksitas.

Contoh skrip:

 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"} 

Jika tidak ada MAC, kita dapatkan

 {"host": "CORE", "iface": "none"} 

Baris terakhir adalah saklar dan port yang menarik minat kami, tetapi pada saat yang sama kami dapat melacak seluruh jalur pencarian.

Kode lengkapnya ada di bawah spoiler, terima kasih atas perhatian Anda.

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: # Create the SSH client. ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # Connect to the host. ssh.connect(host, port, username, password, look_for_keys=False) # Send the command (non-blocking) stdin, stdout, stderr = ssh.exec_command(command) # Wait for the command to terminate while not stdout.channel.exit_status_ready() and not stdout.channel.recv_ready(): time.sleep(1) stdoutstring = stdout.readlines() stderrstring = stderr.readlines() return stdoutstring, stderrstring finally: if ssh is not None: # Close client connection. ssh.close() def sendCommand (hostname,command): returnvalue = 0 logging.info('Host '+hostname+', command: '+command) Try: #add .mydomain for FQDN (stdoutstring, stderrstring) = execute_ssh_command(hostname+'.mydomain', port, login, password, command+'\n') if (len(stdoutstring)>0): logging.info(stdoutstring[0]) if (len(stderrstring)>0): logging.info(stderrstring[0]) except Exception as e: return returnvalue else: returnvalue = stdoutstring[0] finally: return returnvalue def checkswitch(hostname,mac_addr): try: returnvalue = {} returnvalue['host']=hostname answer = sendCommand(hostname,'show ethernet-switching table | match '+mac_addr) if(answer!=0): iface = answer.split()[4] returnvalue['iface']=iface #cut .0 prefix in the interface name answer = sendCommand(hostname,'show interfaces '+iface[:-2]+' descriptions | last 1 | no-more') iface = answer.split() if(len(iface)>2): iface=iface[3] returnvalue['description']=iface else: returnvalue['description']='none' searchpass.append(returnvalue) if (iface[:3]=='SW>'): checkswitch(iface[3:],mac_addr) else: returnvalue['iface']='none' searchpass.append(returnvalue) except Exception as e: logging.info(e) def main(argv): mac_addr = argv[0] #configure log logging.basicConfig(filename='/var/log/findmac.log', level=logging.INFO, format='%(asctime)s %(message)s') logging.info('Find MAC: '+mac_addr) checkswitch('CORE',mac_addr) for switch in searchpass: print (json.dumps(switch, ensure_ascii=False)) if __name__ == "__main__": main(sys.argv[1:]) 

Source: https://habr.com/ru/post/id420013/


All Articles