Home Python & SNMP
Post
Cancel

Python & SNMP

Tänkte fortsätta på samma tema med SNMP och kombinera detta med lite enklare script i Python. Är långt ifrån någon programmerare så detta är nog inte direkt någon vacker lösning, men det fungerar åtminstone. :) För att göra SNMP-querys kan vi använda exempelvis biblioteken subprocess eller netsnmp enligt följande: Subprocess

1
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
import subprocess
checkarg = sys.argv[1:]
#Checks arguments and saves to variables
if len(checkarg) == 2:
    cCommunity = checkarg[0]
    cIP = checkarg[1]
#Modelname
#Gets the Model-ID, returns numeric
cModelInt = subprocess.Popen([r"snmpwalk","-v2c","-Oqv","-c",cCommunity,cIP,"sysObjectID"],stdout=subprocess.PIPE).communicate()[0]

Alternativt netsnmp:

1
2
3
4
5
6
7
8
9
#!/usr/bin/env python
import subprocess
checkarg = sys.argv[1:]
#Checks arguments and saves to variables
if len(checkarg) == 2:
    cCommunity = checkarg[0]
    cIP = checkarg[1]
oid = netsnmp.Varbind('sysName.0')
cName = netsnmp.snmpget(oid, Version = 2, DestHost = cIP, Community = cCommunity)

Vi testar sedan scriptet med “./script.py community ip-adress”. Här ett exempel där jag hämtar hem lite grundläggande information från en cisco router/switch:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python
import netsnmp
import subprocess
import ipaddr
import sys
import prettytable
from prettytable import PrettyTable

checkarg = sys.argv[1:]
#Checks arguments and saves to variables
if len(checkarg) == 2:
    cCommunity = checkarg[0]
    cIP = checkarg[1]
if isinstance(cCommunity, str):
    try:
        #Checks for valid IPv4-address
        ccIP = ipaddr.IPv4Address(cIP)

        try:
            #Modelname
            #Gets the Model-ID, returns numeric
            cModelInt = subprocess.Popen([r"snmpwalk","-v2c","-Oqv","-c",cCommunity,cIP,"sysObjectID"],stdout=subprocess.PIPE).communicate()[0]
            cModelSplit = cModelInt.split("::")
            cModelSplit = cModelSplit[1].rstrip()
            #Translate numeric Model-ID to string
            cModel = subprocess.Popen([r"snmptranslate","-m","CISCO-PRODUCTS-MIB","-IR",cModelSplit],stdout=subprocess.PIPE).communicate()[0]
            cModel = cModel.split("::") 

            #Name
            oid = netsnmp.Varbind('sysName.0')
            cName = netsnmp.snmpget(oid, Version = 2, DestHost = cIP, Community = cCommunity)

            #Description
            oid = netsnmp.Varbind('sysDescr.0')
            cDesc = netsnmp.snmpget(oid, Version = 2, DestHost = cIP, Community = cCommunity)
            #Output
            print ""
            print "Device info:"
            print "" 
            print "Host:", ccIP
            print "Model:", cModel[1].rstrip()
            print "Name:", cName[0]
            print cDesc[0]
	    x = PrettyTable(["Interface", "IP", "Subnet", "MAC"])
            x.align["Interface"] = "l"

	    #Index of all the interfaces
	    oid = netsnmp.Varbind("ifIndex")
	    cIndex = netsnmp.snmpwalk(oid, Version = 2, DestHost = cIP, Community = cCommunity)

	    #Index of all the interfaces with IP
	    oid = netsnmp.Varbind("ipAdEntIfIndex")
	    cIndexIP = netsnmp.snmpwalk(oid, Version = 2, DestHost = cIP, Community = cCommunity)

	    #IP-Adress list
	    oid = netsnmp.Varbind("ipAdEntAddr")    
	    ipAdd = netsnmp.snmpwalk(oid, Version = 2, DestHost = cIP, Community = cCommunity)

	    #MAC for all interfaces
	    oid = netsnmp.Varbind("ifPhysAddress")
	    cMAC = netsnmp.snmpwalk(oid, Version = 2, DestHost = sys.argv[2], Community = sys.argv[1])

	    #Subnetmask for all IP interfaces
	    oid = netsnmp.Varbind("ipAdEntNetMask")
	    cNetmask = netsnmp.snmpwalk(oid, Version = 2, DestHost = cIP, Community = cCommunity)

	    looped = 0

	    #Prints out interface-details
	    for i in cIndex:

	        #Name of every interface
	        oid = netsnmp.Varbind("ifDescr."+i)
	        cInterfacename = netsnmp.snmpget(oid, Version = 2, DestHost = cIP, Community = cCommunity)

	        try:
	            #Matches interface-list with interface+IP-list       
	            IPindex = cIndexIP.index(i)

	            try:
	                #Hex to readable
	                mac = cMAC[looped]
	                mac = ":".join( [ '%x'%(ord(c)) for c in mac ] )

	                #Prints row
	                x.addrow(cInterfacename[0],ipAdd[IPindex],cNetmask[IPindex],mac)

	            except:
		        pass
		    looped += 1

	        except:
	            try:
	                #Hex to readable
	                mac = cMAC[looped]
	                mac = ":".join( [ '%x'%(ord(c)) for c in mac ] )
	                #Prints row w/o IP
	                x.addrow(cInterfacename[0],mac)

	            except:

	                #Prints row w/o MAC & IP
	                x.addrow(cInterfacename[0])

	            looped += 1

		 except:
		     print "SNMP-polling failed"

	     except: 
                 print "Invalid IP given:", cIP
     else:
         print "Invalid Community given (must be string)"
else:
    print "Error - you must set both Community and IP (ex ./3a.py public localhost):"

Programmering/scripting kan vara väldigt skoj har jag märkt! Kan verkligen rekommendera exempelvis https://www.khanacademy.org/science/computer-science-subject/computer-science för att få en liten introduktion till programmering i just python. Till nästa inlägg tänkte jag komplettera scriptet med att spara ner informationen i en MySQL-databas eller fil istället för att endast skriva ut på skärmen.

This post is licensed under CC BY 4.0 by the author.

SNMPv3

Python & MySQL