البحث عن عنوان MAC على مفاتيح Juniper

في الشبكة المحلية ، غالبًا ما تحتاج إلى معرفة منفذ التبديل الموجود في عنوان MAC المحدد للجهاز. يتم حل المشكلة بسهولة إذا كان هناك العديد من المفاتيح في الشبكة ، ولكن عندما يكون هناك أكثر من 30 مفتاحًا ، يصبح كل شيء أكثر تعقيدًا. أريد مشاركة نص Python صغير يبحث عن عنوان MAC المطلوب على الشبكة ويعيد اسم ومنفذ المحول الذي تم تسجيل MAC عليه.



النقد البناء مرحب به. التفاصيل تحت القطع.

إذا تم تصميم الشبكة بشكل صحيح ، أي مفتاح الجذر CORE ، الذي تتصل به مفاتيح توزيع DS (مفتاح التوزيع) ، وبدوره ، يقوم مستوى الوصول بالتبديل AS (مفتاح الوصول). هذه القاعدة ليست صحيحة دائمًا ؛ يمكن توصيل مفاتيح الوصول في سلسلة. في أي حال ، يحتوي منفذ التبديل الرئيسي على جميع عناوين MAC للأجهزة المتصلة بمفتاح التحويل.

على سبيل المثال ، إذا كان الجهاز الذي يهمنا متصلاً بمفتاح AS3 ، فبدءًا من البحث باستخدام CORE ، سنجد هذا العنوان على المنفذ المؤدي إلى DS1 . بالانتقال إلى DS1 ، سنجد هذا MAC على المنفذ المؤدي إلى AS2 ، والذهاب إلى AS2 ، وسنرى أنه يقودنا إلى AS3 ، وفقط في AS3 سنجد المنفذ المحدد الذي يتصل به الجهاز المعني.

لم أكن أرغب في القيام بذلك يدويًا ، وفرز جميع مفاتيح التبديل في حلقة وتحديد مكان الوصلة الصاعدة وأين لا يكون كذلك ، لذلك ولد الحل التالي ، والذي أريد مشاركته.

القليل من النظرية.


للعثور على MAC 08: 62: 66: c7: b3: 45 على مفتاح Juniper ، قم بتشغيل الأمر التالي:

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

إذا كان هناك مثل MAC ، فسيكون الجواب على النحو التالي:

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

سيكون العمود الأخير هو اسم واجهة المحول الذي تم تسجيل MAC عليه. ولكن كيف نفهم إلى أين تقود هذه الواجهة؟ وهنا يأتي وصف واجهة لإنقاذ. هذه خطوط في ملف تكوين المحول تسمح لك بتعيين تسميات نصية للواجهات.

الفريق

 show interfaces xe-0/0/23 descriptions 

سيظهر ما يلي:

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

في التكوين ، نشير إلى أن هذه الواجهة تؤدي إلى تبديل التيار:

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

التنفيذ


سيقوم البرنامج النصي المقترح بما يلي:

  1. الاتصال عبر SSH إلى مفتاح الجذر
  2. تحقق من الواجهة التي يوجد بها عنوان MAC الذي تم تمريره في المعلمات ؛
  3. تحقق من وصف هذه الواجهة ؛
  4. إذا أدت الواجهة إلى التبديل ، فقم بالوصول إلى المفتاح التالي في السلسلة بشكل متكرر.

 #       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) 

وبالتالي ، سوف يمر البرنامج النصي عبر جميع مفاتيح الشبكة ، بدءًا من النواة ، ويحاول العثور على MAC المطلوب. من أجل التشغيل الناجح ، يكفي إبقاء الأوصاف على الواجهات محدثة ، ويمكن أن تكون الطوبولوجيا بأي تعقيد تقريبًا.

مثال على البرنامج النصي:

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

إذا لم يكن هناك MAC ، نحصل

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

السطر الأخير هو المفتاح والمنفذ الذي يهمنا ، ولكن في نفس الوقت يمكننا تتبع مسار البحث بأكمله.

الرمز الكامل تحت المفسد ، شكرا لكم على اهتمامكم.

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/ar420013/


All Articles