はじめに
私はなんちゃってプログラマですが、なぜかいまどきsnmptrapの受信プログラムを作ることになりました。
なんだかなと思いますが、、まぁブログネタにいいかなと思い、手元でもやってみることにしました。
snmptrapとは
Bingいわく「SNMPトラップとは、ネットワーク上の機器(SNMPエージェント)が異常や
状態変化を検知した際に、管理用コンピュータ(SNMPマネージャ)に向けて自動的に送信する通知のことです」
だそうです。
基本は簡単なデータですが、それが意外に真っ当に動作させるのは面倒でして。。
まずは動作させてみます。
環境
- Windows 10
- WSL2
- pysnmp (4.4.12)
- pyans1 (0.4.8)
注意点
現状、pyasn1のバージョンが0.5.0の場合、0.4.8でないと動作しません。ダウングレードさせたら動作しました。
こういう事があるからOSSは怖い。。
受信側(snmprecv.py)
全体はここに置きました。
起動方法
ポートが162番なので、rootで起動させる必要があります。
$ python3 -m venv ./venv $ source venv/bin/activate $ pip install poetry $ poetry install $ sudo ./exec.sh
プログラム自体は簡単です。以下は中心部分です。
snmpEngine = engine.SnmpEngine()
# for receive logging
snmpEngine.observer.registerObserver(
requestObserver,
'rfc3412.receiveMessage:request',
'rfc3412.returnResponsePdu'
)
# port: 162 receive
config.addTransport(
snmpEngine,
udp.domainName,
udp.UdpTransport().openServerMode((bindIF, 162))
)
# SNMP v1 my-area is security name
config.addV1System(snmpEngine, 'my-area', 'public')
ntfrcv.NotificationReceiver(snmpEngine, cbFun)
# not return
snmpEngine.transportDispatcher.jobStarted(1)
try:
snmpEngine.transportDispatcher.runDispatcher()
except Exception as e:
logger.exception(e)
snmpEngine.observer.unregisterObserver()
snmpEngine.transportDispatcher.closeDispatcher()
見たまんまなのですが、いまいち謎なのが”my-area”です。config.addV1System()は呼び出さないと何も処理しなくなります。
security nameとして”my-area”を指定するようですが、送信側は気にしなくても、この設定で受信するようです。
送信側(snmpsend.py)
起動は以下で行います。
$ python3 ./snmpsend.py
プログラムの説明は割愛します。
受信ログ(app.log)
送信データを受信したときのログは以下になります。
INFO : 2023-10-21T13:01:54.985775+0900 : Execution point: rfc3412.receiveMessage:request* transportDomain: 1.3.6.1.6.1.1* transportAddress: 172.22.123.3@50652* securityModel: 2* securityName: my-area* securityLevel: 1* contextEngineId: 0x80004fb8054445534b544f502d3642515645354422f5ff40* contextName: * PDU: SNMPv2TrapPDU:
request-id=15081672
error-status=noError
error-index=0
variable-bindings=VarBindList:
VarBind:
name=1.3.6.1.2.1.1.3.0
=_BindValue:
value=ObjectSyntax:
application-wide=ApplicationSyntax:
timeticks-value=0
VarBind:
name=1.3.6.1.6.3.1.1.4.1.0
=_BindValue:
value=ObjectSyntax:
simple=SimpleSyntax:
objectID-value=1.3.6.1.6.3.1.1.5.2
VarBind:
name=1.3.6.1.2.1.1.1.0
=_BindValue:
value=ObjectSyntax:
simple=SimpleSyntax:
string-value=my system
: 8949
INFO : 2023-10-21T13:01:54.986406+0900 : Notify from ContextId "0x80004fb8054445534b544f502d3642515645354422f5ff40", ContextName "": 8949
INFO : 2023-10-21T13:01:54.986834+0900 : 1.3.6.1.2.1.1.3.0 = 0: 8949
INFO : 2023-10-21T13:01:54.987125+0900 : 1.3.6.1.6.3.1.1.4.1.0 = 1.3.6.1.6.3.1.1.5.2: 8949
INFO : 2023-10-21T13:01:54.987395+0900 : 1.3.6.1.2.1.1.1.0 = my system: 8949
終わりに
比較的あっさり実装できました。
一応GPT-4にも質問したのですが、結局pySNMPのサンプルそのままになりました。
使えない、、GPT-4。。
参考
https://pysnmp.readthedocs.io/en/latest/examples/v3arch/asyncore/manager/ntfrcv/advanced-topics.html