带有自定义 MIB 的 Python SNMP 代理

问题描述 投票:0回答:2

我使用 pysnmp 库在 Python 中实现了 SNMP 代理。这是我用来响应自定义 OID 的代码。


from datetime import datetime
from pysnmp import debug
from pysnmp.carrier.asyncore.dgram import udp
from pysnmp.entity import engine, config
from pysnmp.entity.rfc3413 import cmdrsp, context
from pysnmp.proto.api import v2c
from pysnmp.smi import builder, instrum, exval

# Uncomment this to turn pysnmp debugging on
#debug.setLogger(debug.Debug('all'))

formatting = '[%(asctime)s-%(levelname)s]-(%(module)s) %(message)s'
logging.basicConfig(level=logging.DEBUG, format=formatting, )

logging.info("Starting....")

# Create SNMP engine
snmpEngine = engine.SnmpEngine()

# Transport setup

# UDP over IPv4
config.addTransport(
    snmpEngine,
    udp.domainName,
    udp.UdpTransport().openServerMode(('0.0.0.0', 12345))
)

# SNMPv2c setup

# SecurityName <-> CommunityName mapping.
config.addV1System(snmpEngine, 'my-area', 'public')

# Allow read MIB access for this user / securityModels at VACM
# Limit access to just the custom MIB. Widen if need be
config.addVacmUser(snmpEngine,
                   2,
                   'my-area',
                   'noAuthNoPriv',
                   (1, 3, 6, 4),
                   (1, 3, 6, 4))


# Create an SNMP context and ensure the custom MIB is loaded
# Your system must have this MIB installed otherwise pysnmp
# can't load it!
snmpContext = context.SnmpContext(snmpEngine)
logging.debug('Loading __EXAMPLE-MIB module...'),
mibBuilder = snmpContext.getMibInstrum().getMibBuilder()
(MibTable,
 MibTableRow,
 MibTableColumn,
 MibScalarInstance) = mibBuilder.importSymbols(
    'SNMPv2-SMI',
    'MibTable',
    'MibTableRow',
    'MibTableColumn',
    'MibScalarInstance'
)
logging.debug('done')


RowStatus, = mibBuilder.importSymbols('SNMPv2-TC', 'RowStatus')

mibBuilder.exportSymbols(
    '__EXAMPLE-MIB',
    # table object
    exampleTable=MibTable((1, 3, 6, 4, 1)).setMaxAccess('readcreate'),
    # table row object, also carries references to table indices
    exampleTableEntry=MibTableRow((1, 3, 6, 4, 1, 5)).setMaxAccess('readcreate').setIndexNames((0, '__EXAMPLE-MIB', 'exampleTableColumn1')),
    # table column: string index
    exampleTableColumn1=MibTableColumn((1, 3, 6, 4, 1, 5, 1), v2c.OctetString()).setMaxAccess('readcreate'),
    # table column: string value
    exampleTableColumn2=MibTableColumn((1, 3, 6, 4, 1, 5, 2), v2c.OctetString()).setMaxAccess('readcreate'),
    # table column: integer value with default
    exampleTableColumn3=MibTableColumn((1, 3, 6, 4, 1, 5, 3), v2c.Integer32(123)).setMaxAccess('readcreate'),
    # table column: row status
    exampleTableStatus=MibTableColumn((1, 3, 6, 4, 1, 5, 4), RowStatus('notExists')).setMaxAccess('readcreate')
)
logging.debug('done')

(exampleTableEntry,
 exampleTableColumn2,
 exampleTableColumn3,
 exampleTableStatus) = mibBuilder.importSymbols(
    '__EXAMPLE-MIB',
    'exampleTableEntry',
    'exampleTableColumn2',
    'exampleTableColumn3',
    'exampleTableStatus'
)

rowInstanceId = exampleTableEntry.getInstIdFromIndices('example record one')
mibInstrumentation = snmpContext.getMibInstrum()
mibInstrumentation.writeVars(
    ((exampleTableColumn2.name + rowInstanceId, 'hello'),
     (exampleTableColumn3.name + rowInstanceId, 123456),
     (exampleTableStatus.name + rowInstanceId, 'createAndGo'))
)

logging.debug('done')
logging.debug('Snmp Agent Start')

# Register SNMP Applications at the SNMP engine for particular SNMP context
cmdrsp.GetCommandResponder(snmpEngine, snmpContext)
cmdrsp.SetCommandResponder(snmpEngine, snmpContext)
cmdrsp.NextCommandResponder(snmpEngine, snmpContext)
cmdrsp.BulkCommandResponder(snmpEngine, snmpContext)

# Register an imaginary never-ending job to keep I/O dispatcher running forever
snmpEngine.transportDispatcher.jobStarted(1)

# Run I/O dispatcher which would receive queries and send responses
try:
    snmpEngine.transportDispatcher.runDispatcher()
except:
    snmpEngine.transportDispatcher.closeDispatcher()
    raise

我使用 iReasoning MIB 浏览器发送 SNMP 请求。 当我发送 .1.3.6.4.1.5.1 oid 的 Get 请求时,出现以下解释的错误:“无访问错误。

最后,我发送 .1.3.6.4.1.5 oid 的 Get Subtree 请求,MIB 浏览器显示以下结果:

如您所见,OID结果是: .1.3.6.4.1.5.1.18.101.120.97.109.112.108.101.32.114.101.99.111.114.100.32.111.110.101

这并不短,而且有一些附加价值。

怎么了?

python pysnmp mib
2个回答
2
投票

您观察到的似乎是正确的。

您无法对

1.3.6.4.1.5.1
托管对象进行操作,因为它不是值对象,而是定义可以从中派生的“变量”属性的“类型”。前者称为托管对象,后者在SNMP中称为托管对象实例

要寻址特定的托管对象实例,您需要将一个或多个子 OID 附加到托管对象 OID 上。该尾部部分在 SNMP 中称为“托管对象实例 ID”。 在您的实现中,托管对象实例 ID 源自“示例记录一”字符串。它在 OID 的尾部部分中至少需要与字符串中的字符一样多的元素。这就解释了为什么生成的 OID 这么长。


0
投票

发现这有效:

rowInstanceId = (1,)

下面显示了如下所示脚本的结果:

cd ~ snmpwalk -v 3 -u usr-sha-aes -a SHA -A authkey1 -x aes -X privkey1 -l authPriv -L n -m all localhost 1

输出:

IEEE802dot11-MIB::dot11TransmittedFragmentCount.1 = Counter32: 123 IEEE802dot11-MIB::dot11GroupTransmittedFrameCount.1 = Counter32: 123456 IEEE802dot11-MIB::dot11FailedCount.1 = Counter32: 1350 IEEE802dot11-MIB::dot11RetryCount.1 = Counter32: 1251 IEEE802dot11-MIB::dot11MultipleRetryCount.1 = Counter32: 234 IEEE802dot11-MIB::dot11FrameDuplicateCount.1 = Counter32: 566 IEEE802dot11-MIB::dot11RTSSuccessCount.1 = Counter32: 867 IEEE802dot11-MIB::dot11RTSFailureCount.1 = Counter32: 231 IEEE802dot11-MIB::dot11AckFailureCount.1 = Counter32: 856 IEEE802dot11-MIB::dot11ReceivedFragmentCount.1 = Counter32: 568 IEEE802dot11-MIB::dot11GroupReceivedFrameCount.1 = Counter32: 34568 IEEE802dot11-MIB::dot11FCSErrorCount.1 = Counter32: 345 IEEE802dot11-MIB::dot11TransmittedFrameCount.1 = Counter32: 78567 IEEE802dot11-MIB::dot11WEPUndecryptableCount.1 = Counter32: 4545 RFC1213-MIB::ifDescr.1 = STRING: "wifi0" RFC1213-MIB::ifDescr.1 = No more variables left in this MIB View (It is past the end of the MIB tree)

这是脚本:

from datetime import datetime from pysnmp import debug from pysnmp.carrier.asyncore.dgram import udp from pysnmp.entity import engine, config from pysnmp.entity.rfc3413 import cmdrsp, context from pysnmp.proto.api import v2c from pysnmp.smi import builder, instrum, exval, error from pysnmp.proto import rfc1902 # Create SNMP engine # For the correct SNMP Engine ID format please see https://www.rfc-editor.org/rfc/rfc3411.html#page-41 # snmpEngine = engine.SnmpEngine() snmpEngine = engine.SnmpEngine(rfc1902.OctetString(hexValue='8000000004030201')) # Transport setup # UDP over IPv4 and allow any IP address at port 161 config.addTransport( snmpEngine, udp.domainName, udp.UdpTransport().openServerMode(('0.0.0.0', 161)) ) # SNMPv2c setup # SecurityName <-> CommunityName mapping. my-area username maps to the community name of public. config.addV1System(snmpEngine, 'my-area', 'public') # Allow readonly MIB access for this v2 user / securityModels at VACM # Limit access to just the MIBs used here at VACM. Widen if need be config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1, 2)) config.addVacmUser(snmpEngine, 2, 'my-area', 'noAuthNoPriv', (1, 3, 6, 1, 2, 1, 2, 2)) # SNMPv3/USM setup # user: usr-sha-des, auth: SHA, priv AES128 config.addV3User( snmpEngine, 'usr-sha-aes', config.usmHMACSHAAuthProtocol, 'authkey1', config.usmAesCfb128Protocol, 'privkey1' ) # Limit readonly access to just the MIBs used here at VACM for the v3 user. Widen if need be. config.addVacmUser(snmpEngine, 3, 'usr-sha-aes', 'authPriv', (1, 2)) config.addVacmUser(snmpEngine, 3, 'usr-sha-aes', 'authPriv', (1, 3, 6, 1, 2, 1, 2, 2)) # Create an SNMP context snmpContext = context.SnmpContext(snmpEngine) mibBuilder = snmpContext.getMibInstrum().getMibBuilder() (MibTable, MibTableRow, MibTableColumn, MibScalarInstance) = mibBuilder.importSymbols( 'SNMPv2-SMI', 'MibTable', 'MibTableRow', 'MibTableColumn', 'MibScalarInstance' ) mibBuilder.exportSymbols( 'IF-MIB', ifTable=MibTable((1, 3, 6, 1, 2, 1, 2, 2), ).setMaxAccess('notaccessible'), ifEntry=MibTableRow((1, 3, 6, 1, 2, 1, 2, 2, 1)).setMaxAccess('notaccessible').setIndexNames((0, 'IF-MIB', 'ifIndex')), ifIndex=MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 1), v2c.Integer32()).setMaxAccess('notaccessible'), ifDescr=MibTableColumn((1, 3, 6, 1, 2, 1, 2, 2, 1, 2), v2c.OctetString()).setMaxAccess('readonly') ) # All WiFi products use the ifIndex of 1 for the WLAN interface. mibBuilder.exportSymbols( 'IEEE802dot11-MIB', dot11CountersTable=MibTable((1, 2, 840, 10036, 2, 2), ).setMaxAccess('notaccessible'), dot11CountersEntry=MibTableRow((1, 2, 840, 10036, 2, 2, 1)).setMaxAccess('notaccessible').setIndexNames((0, 'IF-MIB', 'ifIndex')), dot11TransmittedFragmentCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 1), v2c.Counter32()).setMaxAccess('readonly'), dot11GroupTransmittedFrameCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 2), v2c.Counter32()).setMaxAccess('readonly'), dot11FailedCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 3), v2c.Counter32()).setMaxAccess('readonly'), dot11RetryCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 4), v2c.Counter32()).setMaxAccess('readonly'), dot11MultipleRetryCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 5), v2c.Counter32()).setMaxAccess('readonly'), dot11FrameDuplicateCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 6), v2c.Counter32()).setMaxAccess('readonly'), dot11RTSSuccessCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 7), v2c.Counter32()).setMaxAccess('readonly'), dot11RTSFailureCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 8), v2c.Counter32()).setMaxAccess('readonly'), dot11AckFailureCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 9), v2c.Counter32()).setMaxAccess('readonly'), dot11ReceivedFragmentCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 10), v2c.Counter32()).setMaxAccess('readonly'), dot11GroupReceivedFrameCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 11), v2c.Counter32()).setMaxAccess('readonly'), dot11FCSErrorCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 12), v2c.Counter32()).setMaxAccess('readonly'), dot11TransmittedFrameCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 13), v2c.Counter32()).setMaxAccess('readonly'), dot11WEPUndecryptableCount=MibTableColumn((1, 2, 840, 10036, 2, 2, 1, 14), v2c.Counter32()).setMaxAccess('readonly') ) (ifEntry, ifIndex, ifDescr ) = mibBuilder.importSymbols( 'IF-MIB', 'ifEntry', 'ifIndex', 'ifDescr' ) (dot11CountersEntry, dot11TransmittedFragmentCount, dot11GroupTransmittedFrameCount, dot11FailedCount, dot11RetryCount, dot11MultipleRetryCount, dot11FrameDuplicateCount, dot11RTSSuccessCount, dot11RTSFailureCount, dot11AckFailureCount, dot11ReceivedFragmentCount, dot11GroupReceivedFrameCount, dot11FCSErrorCount, dot11TransmittedFrameCount, dot11WEPUndecryptableCount ) = mibBuilder.importSymbols( 'IEEE802dot11-MIB', 'dot11CountersEntry', 'dot11TransmittedFragmentCount', 'dot11GroupTransmittedFrameCount', 'dot11FailedCount', 'dot11RetryCount', 'dot11MultipleRetryCount', 'dot11FrameDuplicateCount', 'dot11RTSSuccessCount', 'dot11RTSFailureCount', 'dot11AckFailureCount', 'dot11ReceivedFragmentCount', 'dot11GroupReceivedFrameCount', 'dot11FCSErrorCount', 'dot11TransmittedFrameCount', 'dot11WEPUndecryptableCount' ) rowInstanceId = (1,) mibInstrumentation = snmpContext.getMibInstrum() mibInstrumentation.writeVars( ((ifIndex.name + rowInstanceId, 1), (ifDescr.name + rowInstanceId, 'wifi0')) ) rowInstanceId = (1,) mibInstrumentation = snmpContext.getMibInstrum() mibInstrumentation.writeVars( ((dot11TransmittedFragmentCount.name + rowInstanceId, 123), (dot11GroupTransmittedFrameCount.name + rowInstanceId, 123456), (dot11FailedCount.name + rowInstanceId, 1350), (dot11RetryCount.name + rowInstanceId, 1251), (dot11MultipleRetryCount.name + rowInstanceId, 234), (dot11FrameDuplicateCount.name + rowInstanceId, 566), (dot11RTSSuccessCount.name + rowInstanceId, 867), (dot11RTSFailureCount.name + rowInstanceId, 231), (dot11AckFailureCount.name + rowInstanceId, 856), (dot11ReceivedFragmentCount.name + rowInstanceId, 568), (dot11GroupReceivedFrameCount.name + rowInstanceId, 34568), (dot11FCSErrorCount.name + rowInstanceId, 345), (dot11TransmittedFrameCount.name + rowInstanceId, 78567), (dot11WEPUndecryptableCount.name + rowInstanceId, 4545)) ) # Register SNMP Applications at the SNMP engine for particular SNMP context cmdrsp.GetCommandResponder(snmpEngine, snmpContext) cmdrsp.SetCommandResponder(snmpEngine, snmpContext) cmdrsp.NextCommandResponder(snmpEngine, snmpContext) cmdrsp.BulkCommandResponder(snmpEngine, snmpContext) # Register an imaginary never-ending job to keep I/O dispatcher running forever snmpEngine.transportDispatcher.jobStarted(1) # Run I/O dispatcher which would receive queries and send responses try: snmpEngine.transportDispatcher.runDispatcher() except: snmpEngine.transportDispatcher.closeDispatcher() raise

© www.soinside.com 2019 - 2024. All rights reserved.