暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Python:通过SNMP协议获取H3C、华为交换机的VLAN信息及ARP地址表

捷创源科技 2022-02-16
9214

点击上方蓝字 ● 关注捷创源科技


我测试是H3C S3600交换机和华为S3700交换机

交换机SNMP配置
system-view 进入交换机的配置模式
配置community 只读属性为public,且配置版本为所有

    #
    [switch]snmp-agent
    [switch]snmp-agent local-engineid 80006782000FE2F882956810
    [switch]snmp-agent community read public
    [switch]snmp-agent sys-info version all
    #


    例1:
    这是交换机snmp只读团体字是public

      vlan 100
      #
      interface Vlanif100
      ip address 192.168.100.1 255.255.255.0
      #



      这是V100配置的IP是192.168.100.1,子网掩码255.255.255.0,默认网关:192.168.100.1

      例2:

        vlan 100
        #
        interface Vlanif100
        ip address 192.168.100.2 255.255.255.0
        vrrp vrid 8 virtual-ip 192.168.100.1
        #


        这是V100配置的IP是192.168.100.2,子网掩码255.255.255.0,虚拟IP就是网关:192.168.100.1

        下面代码使用例子1配置

        //----------------------------------------------------------------------------------------------------------

          """
          mySnmpScan类,扫描核心交换机发送oid或MIB值获取对应数据
          """
          # -*- coding: utf-8 -*-
          import sys
          import win32api
          import win32con
          import re


          try:
          from pysnmp.entity.rfc3413.oneliner import cmdgen
          except Exception as e:
          print("You need to download pysnmp and pyasn1", e)
          sys.exit(1)


          # oid或MIB值
          oTable = {
          "sysName": (1, 3, 6, 1, 2, 1, 1, 5), # 系统名称
          "sysDescr": (1, 3, 6, 1, 2, 1, 1, 1), # 系统描述,可以获取系统版本信息


          "dot1qTpFdbPort": (1, 3, 6, 1, 2, 1, 17, 7, 1, 2, 2, 1, 2), # MAC地址对应的端口
          "dot1qTpFdbStatus": (1, 3, 6, 1, 2, 1, 17, 7, 1, 2, 2, 1, 3), # MAC表项的状态


          "dot1dBasePortIfIndex": (1, 3, 6, 1, 2, 1, 17, 1, 4, 1, 2), # dot1d端口索引


          "ifIndex": (1, 3, 6, 1, 2, 1, 2, 2, 1, 1), # 端口索引
          "ifDescr": (1, 3, 6, 1, 2, 1, 2, 2, 1, 2), # 端口信息描述
          "ifType": (1, 3, 6, 1, 2, 1, 2, 2, 1, 3), # 端口类型
          "ifSpeed": (1, 3, 6, 1, 2, 1, 2, 2, 1, 5), # 端口速率(bits,万兆端口会溢出,参考节点ifHighSpeed)
          "ifPhysAddress": (1, 3, 6, 1, 2, 1, 2, 2, 1, 6), # 端口物理地址
          "ifAdminStatus": (1, 3, 6, 1, 2, 1, 2, 2, 1, 7), # 端口的管理状态
          "ifOperStatus": (1, 3, 6, 1, 2, 1, 2, 2, 1, 8), # 端口的工作状态


          "ifName": (1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 1), # 端口名称(节点值同节点ifDescr)
          "ifHighSpeed": (1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 15), # 端口速率(1000000bits)
          "ifAlias": (1, 3, 6, 1, 2, 1, 31, 1, 1, 1, 18), # 网管用的端口描述信息(就是在端口视图下,命令行配置的description)


          "ipAdEntAddr": (1, 3, 6, 1, 2, 1, 4, 20, 1, 1), # 接口IP地址
          "ipAdEntIfIndex": (1, 3, 6, 1, 2, 1, 4, 20, 1, 2), # 接口索引
          "ipAdEntNetMask": (1, 3, 6, 1, 2, 1, 4, 20, 1, 3), # 接口IP掩码
          "ipAdEntBcastAddr": (1, 3, 6, 1, 2, 1, 4, 20, 1, 4), # 广播地址


          # 有两个MIB表用来表示所有ARP表项。
          # 注:静态ARP对应的MIB表索引都是0,动态ARP的索引是vlan虚接口对应的ifIndex。
          # (1) 表atEntry,1.3.6.1.2.1.3.1.1,它没有表项类型的字段,即不知道ARP表项是动态的,还是静态的ARP表项,包含的节点如下。
          "atIfIndex": (1, 3, 6, 1, 2, 1, 3, 1, 1, 1), # 端口索引
          "atPhysAddress": (1, 3, 6, 1, 2, 1, 3, 1, 1, 2), # 物理地址
          "atNetAddress": (1, 3, 6, 1, 2, 1, 3, 1, 1, 3), # IP地址


          # (2) 表ipNetToMediaEntry,1.3.6.1.2.1.4.22.1,它有表项类型的节点ipNetToMediaType,
          # 知道ARP表项是动态表项,还是静态表项,包含的节点如下。
          "ipNetToMediaIfIndex": (1, 3, 6, 1, 2, 1, 4, 22, 1, 1), # 端口索引
          "ipNetToMediaPhysAddress": (1, 3, 6, 1, 2, 1, 4, 22, 1, 2), # 物理地址 (ARP表oid,IP-MAC)
          "ipNetToMediaNetAddress": (1, 3, 6, 1, 2, 1, 4, 22, 1, 3), # IP地址
          "ipNetToMediaType": (1, 3, 6, 1, 2, 1, 4, 22, 1, 4), # 表项类型
          }




          # snmp扫描交换机类
          class mySnmpScan:
          def __init__(self, strSwitchVlanIP: str, strCommunity: str):
          """
          @function: 初始化
          @parameter: strSwitchVlanIP,交换机一个VLAN的配置IP
          @parameter: strCommunity,交换机snmp团体字
          """
          self.strSwitchVlanIP = strSwitchVlanIP # 交换机一个VLAN的网关IP
          self.strCommunity = strCommunity # 交换机snmp团体字


          self.listSystemNameTable = [] # 列表存储系统名称信息
          self.listSystemVersionTable = [] # 列表存储系统版本信息


          self.listPortInterfaceTable = [] # 列表存储Port-Interface对应记录
          self.listIpPortTable = [] # # 列表存储IP-Port对应记录
          self.listIpNetMaskTable = [] # 列表存储IP-NetMask(子网掩码)对应记录


          self.listArpIpMacTable = [] # 列表存储ARP表所有IP-MAC对应记录
          self.listArpIpTypeTable = [] # 列表存储ARP表所有IP-Type对应记录
          self.listArpIpPortTable = [] # 列表存储ARP表所有IP-Port对应记录


          self.listVlanIpNetMaskTable = [] # 列表存储VLAN号、IP、NetMask(子网掩码)对应列表
          self.listIpMacTypeTable = [] # 列表存储IP、MAC、Type对应列表


          def walk(self, tupleOid: tuple):
          """
          @function: This function will return the table of OID's that I am walking
          此函数将返回我正在扫描的 OID 表
          """
          errorIndication, errorStatus, errorIndex, generic = cmdgen.CommandGenerator().nextCmd(
          # 社区信息,my-agent ,self.strCommunity表示社区名团体字,1表示snmp v2c版本,0为v1版本
          cmdgen.CommunityData('my-agent', self.strCommunity, mpModel=1),
          # 这是传输的通道,传输到IP self.strSwitchIP, 端口 161上(snmp标准默认161 UDP端口)
          cmdgen.UdpTransportTarget((self.strSwitchVlanIP, 161)), tupleOid)


          if errorIndication:
          win32api.MessageBox(0, "请求超时!", "温馨提示", win32con.MB_ICONWARNING)
          # return errorIndication
          return '0xAA'


          return generic


          def getSystemName(self, bFlag=True):
          """
          @function: 获取系统名称
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listSystemNameTable.clear() # 清空列表
          entAddress = self.walk(oTable["sysName"]) # 系统名称的oid或MIB值


          if entAddress == '0xAA':
          return False
          else:
          # 请求未超时
          for i in entAddress:
          temp = ''
          for j in i:
          temp += str(j)
          temp = temp[temp.find('=') + 1:]


          self.listSystemNameTable.append(temp)


          if bFlag:
          # 打印列表
          for list_System_Name in self.listSystemNameTable:
          print(list_System_Name)


          return True


          def getSystemVersionInfo(self, bFlag=True):
          """
          @function: 获取系统版本信息
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listSystemVersionTable.clear() # 清空列表
          entAddress = self.walk(oTable["sysDescr"]) # 系统描述的oid或MIB值


          if entAddress == '0xAA':
          return False
          else:
          # 请求未超时
          for i in entAddress:
          temp = ''
          for j in i:
          temp += str(j)
          self.listSystemVersionTable.append(temp)


          if bFlag:
          # 打印列表
          for list_System_Version in self.listSystemVersionTable:
          print(list_System_Version)


          return True


          def getPortInterfaceTable(self, bFlag=True):
          """
          @function: 获取Port-Interface对应列表
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listPortInterfaceTable.clear() # 清空列表
          entAddress = self.walk(oTable["ifDescr"]) # 端口信息描述的oid或MIB值


          if entAddress == '0xAA':
          return False
          else:
          # 请求未超时
          for i in entAddress:
          temp = ''
          for j in i:
          temp += str(j)


          temp = temp.replace("SNMPv2-SMI::mib-2.2.2.1.", "")
          temp = temp[temp.find('.') + 1:]
          temp = temp.split(' = ')
          self.listPortInterfaceTable.append(temp)


          if bFlag:
          # 打印列表
          for list_IP_Interface in self.listPortInterfaceTable:
          print(list_IP_Interface)


          return True


          def getIpPortTable(self, bFlag=True):
          """
          @function: 获取IP-Port对应列表
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listIpPortTable.clear() # 清空列表
          entAddress = self.walk(oTable["ipAdEntIfIndex"]) # 接口索引的oid或MIB值


          if entAddress == '0xAA':
          return False
          else:
          # 请求未超时
          for i in entAddress:
          temp = ''
          for j in i:
          temp += str(j)


          temp = temp.replace("SNMPv2-SMI::mib-2.4.20.1.", "")
          temp = temp[temp.find('.') + 1:]
          temp = temp.split(' = ')
          self.listIpPortTable.append(temp)


          if bFlag:
          # 打印列表
          for list_IP_Port in self.listIpPortTable:
          print(list_IP_Port)


          return True


          def getIpNetMaskTable(self, bFlag=True):
          """
          @function: 获取IP-NetMask(子网掩码)对应列表
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listIpNetMaskTable.clear() # 清空列表
          entAddress = self.walk(oTable["ipAdEntNetMask"]) # 接口IP掩码的oid或MIB值


          if entAddress == '0xAA':
          return False
          else:
          # 请求未超时
          for i in entAddress:
          temp = ''
          for j in i:
          temp += str(j)


          temp = temp.replace("SNMPv2-SMI::mib-2.4.20.1.", "")
          temp = temp[temp.find('.') + 1:]
          temp = temp.split(' = ')
          self.listIpNetMaskTable.append(temp)


          if bFlag:
          # 打印列表
          for list_IP_NetMask in self.listIpNetMaskTable:
          print(list_IP_NetMask)


          return True


          def getArpIpMacTable(self, bFlag=True):
          """
          @function: 获取arp列表的所有IP-MAC对应列表
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listArpIpMacTable.clear() # 清空列表
          entAddress = self.walk(oTable["ipNetToMediaPhysAddress"]) # 物理地址的oid或MIB值


          if entAddress == '0xAA':
          return False
          else:
          # 请求未超时
          for i in entAddress:
          temp = ''
          for j in i:
          temp += str(j)


          temp = temp.replace("SNMPv2-SMI::mib-2.4.22.1.2.", "")
          temp = temp[temp.find('.') + 1:]
          temp = temp.split(' = ')
          temp[1] = temp[1][2:].upper() # MAC'0xb0dfc1ed87e0'去掉0x后转换成大写字母
          self.listArpIpMacTable.append(temp)


          if bFlag:
          # 打印ARP表
          for list_IP_MAC in self.listArpIpMacTable:
          print(list_IP_MAC)


          return True


          def getArpIpTypeTable(self, bFlag=True):
          """
          @function: 获取arp列表的所有IP-TYPE对应列表。Type:动态表项IP-dynamic(3),静态表项IP-static(4)
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listArpIpTypeTable.clear() # 清空列表
          entAddress = self.walk(oTable["ipNetToMediaType"]) # 表项类型的oid或MIB值


          if entAddress == '0xAA':
          return False
          else:
          # 请求未超时
          for i in entAddress:
          temp = ''
          for j in i:
          temp += str(j)


          temp = temp.replace("SNMPv2-SMI::mib-2.4.22.1.4.", "")
          temp = temp[temp.find('.') + 1:]
          temp = temp.split(' = ')
          self.listArpIpTypeTable.append(temp)


          if bFlag:
          # 打印列表
          for list_IP_Type in self.listArpIpTypeTable:
          print(list_IP_Type)


          return True


          def getArpIpPortTable(self, bFlag=True):
          """
          @function: 获取arp列表的所有IP-Port对应列表
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listArpIpPortTable.clear() # 清空列表
          entAddress = self.walk(oTable["ipNetToMediaIfIndex"]) # 端口索引的oid或MIB值


          if entAddress == '0xAA':
          return False
          else:
          # 请求未超时
          for i in entAddress:
          temp = ''
          for j in i:
          temp += str(j)


          temp = temp.replace("SNMPv2-SMI::mib-2.4.22.1.1.", "")
          temp = temp[temp.find('.') + 1:]
          temp = temp.split(' = ')
          self.listArpIpPortTable.append(temp)


          if bFlag:
          # 打印列表
          for list_IP_Port in self.listArpIpPortTable:
          print(list_IP_Port)


          return True


          def getVlanIpNetMaskTable(self, bFlag=True):
          """
          @function: 获取VLAN号、IP、NetMask(子网掩码)对应列表
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listVlanIpNetMaskTable.clear() # 清空
          self.getPortInterfaceTable(False) # 获取Port-Interface对应列表
          self.getIpPortTable(False) # 获取IP-Port对应列表
          self.getIpNetMaskTable(False) # 获取IP-NetMask(子网掩码)对应列表


          # 以IP为基础,创建VLAN号、IP、NetMask(子网掩码)对应列表
          for i in range(len(self.listIpNetMaskTable)):
          netmask = self.listIpNetMaskTable[i][1]
          ip = self.listIpNetMaskTable[i][0]


          if ip != '127.0.0.1':
          for j in range(len(self.listIpPortTable)):
          if ip == self.listIpPortTable[j][0]:
          port = self.listIpPortTable[j][1]
          for k in range(len(self.listPortInterfaceTable)):
          if port == self.listPortInterfaceTable[k][0]:
          temp = self.listPortInterfaceTable[k][1]
          # print(temp)
          temp = re.sub('\D', "", temp) # 从虚接口Vlanif10或VlanInterface10中提取数字
          # print(temp)
          vlan = 'V' + temp
          listTemp = [vlan, ip, netmask]
          self.listVlanIpNetMaskTable.append(listTemp)
          else:
          continue
          else:
          continue
          else:
          continue


          if bFlag:
          # 打印列表
          for list_Vlan_IP_NetMask in self.listVlanIpNetMaskTable:
          print(list_Vlan_IP_NetMask)


          def getIpMacTypeTable(self, bFlag=True):
          """
          @function: 获取IP、MAC、Type对应列表。Type:动态表项IP-dynamic(3),静态表项IP-static(4)
          @parameter: bFlag,True打印列表,False不打印列表
          """
          self.listIpMacTypeTable.clear() # 清空
          self.getArpIpMacTable(False) # 获取arp列表的所有IP-MAC对应列表
          self.getArpIpTypeTable(False) # 获取arp列表的所有IP-TYPE对应列表


          # 以IP为基础,创建IP、MAC、Type对应列表
          for i in range(len(self.listArpIpMacTable)):
          mac = self.listArpIpMacTable[i][1][2:].upper()
          ip = self.listArpIpMacTable[i][0]


          for j in range(len(self.listArpIpTypeTable)):
          if ip == self.listArpIpTypeTable[j][0]:
          typeNum = self.listArpIpTypeTable[j][1]


          """
          if typeNum == '1':
          typeNum = 'interface' # VLAN虚接口IP
          """


          if typeNum == '3':
          typeNum = 'dynamic' # 动态表项IP


          if typeNum == '4':
          typeNum = 'static' # 静态表项IP


          listTemp = [ip, mac, typeNum]
          self.listIpMacTypeTable.append(listTemp)
          else:
          continue


          if bFlag:
          # 打印列表
          for list_IP_MAC_Type in self.listIpMacTypeTable:
          print(list_IP_MAC_Type)




          """--------------------------------------------------------
          主函数
          --------------------------------------------------------"""
          if __name__ == '__main__':
          mySnmp = mySnmpScan("192.168.100.1", "public")


          # mySnmp.getSystemName() # 获取系统名称
          # mySnmp.getSystemVersionInfo() # 获取系统版本信息


          # mySnmp.getPortInterfaceTable() # 获取Port-Interface对应列表
          # mySnmp.getIpPortTable() # 获取IP-Port对应列表
          # mySnmp.getIpNetMaskTable() # 获取IP-NetMask(子网掩码)对应列表


          # mySnmp.getArpIpMacTable() # 获取arp列表的所有IP-MAC对应列表
          # mySnmp.getArpIpTypeTable() # 获取arp列表的所有IP-TYPE对应列表
          # mySnmp.getArpIpPortTable() # 获取arp列表的所有IP-PORT对应列表


          # 获取VLAN号、IP、NetMask(子网掩码)对应列表
          print("VLAN号、IP、NetMask(子网掩码)对应列表:")
          mySnmp.getVlanIpNetMaskTable()


          # 获取IP、MAC、Type对应列表
          print("IP、MAC、Type对应列表:")
          mySnmp.getIpMacTypeTable()







          运行效果:

          关注上面微信公众号“捷创源科技每天获取技术干货让我们一起成长

          文章转载自捷创源科技,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

          评论