1""" 2SNMPv2c-to-SNMPv3 conversion 3++++++++++++++++++++++++++++ 4 5Act as a local SNMPv1/v2c Agent, relay messages to distant SNMPv3 Agent: 6* over IPv4/UDP 7* with local SNMPv2c community 'public' 8* local Agent listening at 127.0.0.1:161 9* remote SNMPv3 user usr-md5-none, MD5 auth and no privacy protocols 10* remote Agent listening at 104.236.166.95:161 11 12This script can be queried with the following Net-SNMP command: 13 14| $ snmpget -v2c -c public 127.0.0.1:161 1.3.6.1.2.1.1.1.0 15 16due to proxy, it is equivalent to 17 18| $ snmpget -v3 -l authNoPriv -u usr-md5-none -A authkey1 -ObentU 104.236.166.95:161 1.3.6.1.2.1.1.1.0 19 20Warning: for production operation you would need to modify this script 21so that it will re-map possible duplicate request-ID values, coming in 22initial request PDUs from different Managers, into unique values to 23avoid sending duplicate request-IDs to Agents. 24 25"""# 26from pysnmp.carrier.asyncore.dgram import udp 27from pysnmp.entity import engine, config 28from pysnmp.entity.rfc3413 import cmdrsp, cmdgen, context 29from pysnmp.proto.api import v2c 30from pysnmp import error 31 32# Create SNMP engine with autogenernated engineID and pre-bound 33# to socket transport dispatcher 34snmpEngine = engine.SnmpEngine() 35 36# 37# Transport setup 38# 39 40# Agent section 41 42# UDP over IPv4 43config.addTransport( 44 snmpEngine, 45 udp.domainName + (1,), 46 udp.UdpTransport().openServerMode(('127.0.0.1', 161)) 47) 48 49# Manager section 50 51# UDP over IPv4 52config.addTransport( 53 snmpEngine, 54 udp.domainName + (2,), 55 udp.UdpTransport().openClientMode() 56) 57 58# 59# SNMPv1/2c setup (Agent role) 60# 61 62# SecurityName <-> CommunityName mapping 63config.addV1System(snmpEngine, 'my-area', 'public') 64 65# 66# SNMPv3/USM setup (Manager role) 67# 68 69# user: usr-md5-none, auth: MD5, priv NONE 70config.addV3User( 71 snmpEngine, 'usr-md5-none', config.usmHMACMD5AuthProtocol, 'authkey1' 72) 73 74# 75# Transport target used by Manager 76# 77 78config.addTargetParams( 79 snmpEngine, 'distant-agent-auth', 'usr-md5-none', 'authNoPriv' 80) 81config.addTargetAddr( 82 snmpEngine, 'distant-agent', 83 udp.domainName + (2,), ('104.236.166.95', 161), 84 'distant-agent-auth', retryCount=0 85) 86 87# Default SNMP context 88config.addContext(snmpEngine, '') 89 90 91class CommandResponder(cmdrsp.CommandResponderBase): 92 cmdGenMap = { 93 v2c.GetRequestPDU.tagSet: cmdgen.GetCommandGenerator(), 94 v2c.SetRequestPDU.tagSet: cmdgen.SetCommandGenerator(), 95 v2c.GetNextRequestPDU.tagSet: cmdgen.NextCommandGeneratorSingleRun(), 96 v2c.GetBulkRequestPDU.tagSet: cmdgen.BulkCommandGeneratorSingleRun() 97 } 98 pduTypes = cmdGenMap.keys() # This app will handle these PDUs 99 100 # SNMP request relay 101 def handleMgmtOperation(self, snmpEngine, stateReference, contextName, 102 PDU, acInfo): 103 cbCtx = stateReference, PDU 104 contextEngineId = None # address authoritative SNMP Engine 105 try: 106 self.cmdGenMap[PDU.tagSet].sendPdu( 107 snmpEngine, 'distant-agent', 108 contextEngineId, contextName, 109 PDU, 110 self.handleResponsePdu, cbCtx 111 ) 112 except error.PySnmpError: 113 self.handleResponsePdu( 114 snmpEngine, stateReference, 'error', None, cbCtx 115 ) 116 117 # SNMP response relay 118 # noinspection PyUnusedLocal 119 def handleResponsePdu(self, snmpEngine, sendRequestHandle, 120 errorIndication, PDU, cbCtx): 121 stateReference, reqPDU = cbCtx 122 123 if errorIndication: 124 PDU = v2c.apiPDU.getResponse(reqPDU) 125 PDU.setErrorStatus(PDU, 5) 126 127 self.sendPdu( 128 snmpEngine, stateReference, PDU 129 ) 130 131 self.releaseStateInformation(stateReference) 132 133 134CommandResponder(snmpEngine, context.SnmpContext(snmpEngine)) 135 136snmpEngine.transportDispatcher.jobStarted(1) # this job would never finish 137 138# Run I/O dispatcher which would receive queries and send responses 139try: 140 snmpEngine.transportDispatcher.runDispatcher() 141except: 142 snmpEngine.transportDispatcher.closeDispatcher() 143 raise 144