SNMPトラップをZabbixで捕捉する in Dockerネットワーク

## はじめに

[前回の記事](https://qiita.com/t13801206/items/c37cb17fba709bc90764)では、Dockerネットワーク上にZabbixサーバをたてた。
そのDockerネットワーク内にZabbixエージェントをインストールしたUbuntuも同居させ、Zabbixサーバから監視もさせた。

🗨️今回は、同じくUbuntuの２号機を構築するのだが、Zabbixエージェントは入れない。
Zabbixエージェントの代わりにSNMPデーモンを起動させておく。

同じUbuntuホストでも、ZabbixエージェントとSNMPデーモンの２通りで監視を行うことを試す。

### 注意❗

この記事を書いている人間はSNMPについてほぼ**無知**であり
試行錯誤の脳内会話を書き連ねているので、誤ったことを書いている可能性があります
諸先輩方におかれましては、見過ごせない誤情報を見かけた際にはコメントで教えていただきたくお願い申し上げます🙇‍♂️

### この記事のゴール

先にゴールのキャプチャを示す。
ZabbixサーバからUbuntuホストが２つ見えており、それぞれZabbixエージェント・SNMPの２通りで監視されていることがわかる。
※バッジが緑色になっているのが正常の証。うまく監視できていないときはバッジが赤色になる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/48521e41-4c0b-7691-b153-4cb9107ca7a9.png)

次から実際の手順を示す。

## SNMPトラップを発報するクライアントをたてる

Ubuntuサーバをたてる。
Zabbix-netに所属させる。このときIPは末尾`.6`であった。
（IPアドレスは`docker network inspect`コマンドで調べた）

```bash
# コンテナをたてる
docker run --name ubuntu-2 --hostname snmp-cl --privileged -it --network=zabbix-net -d ubuntu
```

### UbuntuでSNMPの設定をする

コンテナの中に入って、SNMPのサービスをインストールする

```bash
docker container exec -it ubuntu-2 bash
apt update
apt install -y snmp
apt install -y snmpd
apt install -y snmp-mibs-downloader
download-mibs
```

#### コンフィグを編集する

SNMPコンフィグファイルを編集する。
[こちら](https://qiita.com/tomoyk/items/7a2d48df583e2b1b9bc6)の記事を参考に、`# mibs :`←このように１行だけコメントアウトした。
コンフィグを変更したらサービスを再起動する（コンテナを再起動するでもよい）

つづいてデーモンのコンフィグファイルを編集する。
`/etc/snmp/snmpd.conf`の以下の箇所が`127.0.0.1`だとZabbixサーバから見えなかったので
自身のIPアドレス（=Zabbixサーバから疎通のとれるIPアドレス）に変更した。

変更後の`snmpd.conf`の１行は`agentaddress 172.20.240.6:161`

#### snmpdサービスを起動する

前回Zabbixエージェントを入れた時も、Zabbixエージェントサービスは自動起動していなかった。
今回のSNMPデーモンも同様に自動起動していなかったので、手動で起動した。

```bash
root@snmp-cl:/# service --status-all
 [ - ]  procps
 [ - ]  snmpd
root@snmp-cl:/# service snmpd start
 * Starting SNMP Services snmpd                                                                                  [ OK ]
root@snmp-cl:/# service --status-all
 [ - ]  procps
 [ + ]  snmpd
```

Zabbixサーバからみて下記の様子であればOK（冒頭のゴールイメージで示した通り）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/57ee3b04-c2de-83d9-564a-6893f4dcfdb7.png)

## SNMPトラップを発報する

ChatGPTさんと会話しながら、なんとかSNMPトラップコマンドにたどり着いたが、これが正攻法かは分からない。

宛先は`zabbix-snmptraps`コンテナのIPアドレスとした。
コンテナを建てたときに`1162`ポートを開けていたので、ポートは1162を指定

~~`snmptrap -v 2c -c public 172.20.240.3:1162 '' SNMPv2-MIB::sysLocation.0 s 'america'`~~

`snmptrap -v 2c -c public 172.20.240.3:1162 '' coldstart SNMPv2-MIB::sysLocation.0 s 'america'`
（2024/9/23 修正 --- コメントいただきました @twsnmp 様ありがとうございます！！）


余談）`nc`コマンドで、たしかに1162ポートが開いていることも確認した

```bash
root@7830d9ef2faa:/# nc -uvz 172.20.240.3 1162
zabbix-snmptraps.zabbix-net [172.20.240.3] 1162 (?) open
```

### NG！Dockerでエラーログが吐かれていた！

SNMPトラップを送った先のサーバで、エラーらしきログが出ていた。

```bash:zabbix-snmptrapsコンテナのログ
2024-09-18 00:46:45 iso.3.6.1.2.1.1.3.0 = 2020686       iso.3.6.1.6.3.1.1.4.1.0 = OID: iso.3.6.1.2.1.1.6.0      iso.3.6.1.2.1.31.2.1.8 = STRING: "america"
2024-09-18 00:46:45 /usr/sbin/zabbix_trap_handler.sh: line 47: /var/lib/zabbix/snmptraps/snmptraps.log: Permission denied
```

どうやら`snmptraps.log`ファイルの権限が怪しいようなので、コンテナに入ってパーミッションを変更する。
変更前のパーミッションは下記のとおりで、zabbixユーザでは読み取りしかできないようで、それがエラーログの原因だったよう。
`drwxr-xr-x    2 root     root            40 Sep 16 13:24 snmptraps`

**rootユーザで作業するために`-u 0`を付記**してコンテナに入る。
ログインしたディレクトリに`snmptraps`フォルダがすでに存在しているので、とりあえずフルアクセスを可能とした。

```
docker container exec -u 0 -it zabbix-snmptraps bash
chmod 777 ./snmptraps/
```
公式が出しているコンテナの作成方法に則ってつくったのに、こんな権限変更を強いられるのはおかしい。
どこかで道を誤ったのかもしれない。

何はともあれ、正常化したあとのログは下記のとおり。

```bash:snmptraps.log
fb0ba0fbdd59:/var/lib/zabbix/snmptraps$ tail snmptraps.log
20240917.155909 ZBXTRAP 172.20.240.6
UDP: [172.20.240.6]:53326->[172.20.240.3]:1162
iso.3.6.1.2.1.1.3.0 = 2095066
iso.3.6.1.6.3.1.1.4.1.0 = iso.3.6.1.2.1.1.6.0
iso.3.6.1.2.1.31.2.1.8 = "america"
20240917.160248 ZBXTRAP 172.20.240.6
UDP: [172.20.240.6]:40876->[172.20.240.3]:1162
iso.3.6.1.2.1.1.3.0 = 2116971
iso.3.6.1.6.3.1.1.4.1.0 = iso.3.6.1.2.1.1.6.0
iso.3.6.1.2.1.31.2.1.8 = "Japan"
```

Ubuntuホストから投げたsnmpトラップがちゃんとログに載っている
snmpトラップのコマンドではisoなんて文字列を書いていないが、そうやって変換されるものなのだろうか。
このあたりはもっとsnmpについて詳しくならないとわからない。

## Zabbix画面にアクセスしてSNMPトラップをみてみる

今回は`sysLocation.0`を指定して値`Japan`を送ったのだが、Zabbixサーバ側でみるとその箇所はデフォルトのままだった。Japanに書き変わらなかった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/bc00d49f-84b9-2e8d-af4d-a3e22a60fb7d.png)

### SNMPトラップのログはGUIのここに表れる

[トラップ受信の流れ](https://www.zabbix.com/documentation/2.2/jp/manual/config/items/itemtypes/snmptrap)によると、トラップログの値を格納する先がが見つかれなかったら「snmptrap.fallback」アイテムに保存されるらしい。

たしかに、監視対象ホストの`Linux: SNMP traps (fallback)`の最新50の値を見てみると、americaやらJapanやらのログが見える

最新の値を表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/d5bcba41-643f-e2ac-1456-274d5673ef1b.png)

SNMPトラップログが見える
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/cc7d2ed7-5fb9-7bb1-5f81-313a40e50268.png)

## おわりに

今回はZabbixサーバとUbuntuのSNMPクライアントを使って
SNMPトラップのログがどのようにサーバに表れるのかを実験した

SNMPのポーリング／トラップの双方向でサーバと通信ができていることは確認できたが
トラップのデータでサーバの値が更新されることは確認できなかった

ホスト登録時のテンプレート、アイテムあたりが足りていない・間違っているのかもしれない。

ひとまずこの記事ではここまで。

## おまけ～snmpwalkの結果

```bash
root@snmp-cl:/var/log# snmpwalk -v 2c -c public 172.20.240.6
SNMPv2-MIB::sysDescr.0 = STRING: Linux snmp-cl 5.15.153.1-microsoft-standard-WSL2 #1 SMP Fri Mar 29 23:14:13 UTC 2024 x86_64
SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (851577) 2:21:55.77
SNMPv2-MIB::sysContact.0 = STRING: Me <me@example.org>
SNMPv2-MIB::sysName.0 = STRING: snmp-cl
SNMPv2-MIB::sysLocation.0 = STRING: Sitting on the Dock of the Bay
SNMPv2-MIB::sysServices.0 = INTEGER: 72
SNMPv2-MIB::sysORLastChange.0 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORID.1 = OID: SNMP-FRAMEWORK-MIB::snmpFrameworkMIBCompliance
SNMPv2-MIB::sysORID.2 = OID: SNMP-MPD-MIB::snmpMPDCompliance
SNMPv2-MIB::sysORID.3 = OID: SNMP-USER-BASED-SM-MIB::usmMIBCompliance
SNMPv2-MIB::sysORID.4 = OID: SNMPv2-MIB::snmpMIB
SNMPv2-MIB::sysORID.5 = OID: SNMP-VIEW-BASED-ACM-MIB::vacmBasicGroup
SNMPv2-MIB::sysORID.6 = OID: TCP-MIB::tcpMIB
SNMPv2-MIB::sysORID.7 = OID: UDP-MIB::udpMIB
SNMPv2-MIB::sysORID.8 = OID: IP-MIB::ip
SNMPv2-MIB::sysORID.9 = OID: SNMP-NOTIFICATION-MIB::snmpNotifyFullCompliance
SNMPv2-MIB::sysORID.10 = OID: NOTIFICATION-LOG-MIB::notificationLogMIB
SNMPv2-MIB::sysORDescr.1 = STRING: The SNMP Management Architecture MIB.
SNMPv2-MIB::sysORDescr.2 = STRING: The MIB for Message Processing and Dispatching.
SNMPv2-MIB::sysORDescr.3 = STRING: The management information definitions for the SNMP User-based Security Model.
SNMPv2-MIB::sysORDescr.4 = STRING: The MIB module for SNMPv2 entities
SNMPv2-MIB::sysORDescr.5 = STRING: View-based Access Control Model for SNMP.
SNMPv2-MIB::sysORDescr.6 = STRING: The MIB module for managing TCP implementations
SNMPv2-MIB::sysORDescr.7 = STRING: The MIB module for managing UDP implementations
SNMPv2-MIB::sysORDescr.8 = STRING: The MIB module for managing IP and ICMP implementations
SNMPv2-MIB::sysORDescr.9 = STRING: The MIB modules for managing SNMP Notification, plus filtering.
SNMPv2-MIB::sysORDescr.10 = STRING: The MIB module for logging SNMP Notifications.
SNMPv2-MIB::sysORUpTime.1 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORUpTime.2 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORUpTime.3 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORUpTime.4 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORUpTime.5 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORUpTime.6 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORUpTime.7 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORUpTime.8 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORUpTime.9 = Timeticks: (1) 0:00:00.01
SNMPv2-MIB::sysORUpTime.10 = Timeticks: (1) 0:00:00.01
HOST-RESOURCES-MIB::hrSystemUptime.0 = Timeticks: (2701468) 7:30:14.68
HOST-RESOURCES-MIB::hrSystemDate.0 = STRING: 2024-9-18,16:13:24.0,+0:0
HOST-RESOURCES-MIB::hrSystemInitialLoadDevice.0 = INTEGER: 393216
HOST-RESOURCES-MIB::hrSystemInitialLoadParameters.0 = STRING: "initrd=\\initrd.img WSL_ROOT_INIT=1 panic=-1 nr_cpus=8 hv_utils.timesync_implicit=1 console=hvc0 debug pty.legacy_count=0
"
HOST-RESOURCES-MIB::hrSystemNumUsers.0 = Gauge32: 0
HOST-RESOURCES-MIB::hrSystemProcesses.0 = Gauge32: 4
HOST-RESOURCES-MIB::hrSystemMaxProcesses.0 = INTEGER: 0
HOST-RESOURCES-MIB::hrSystemMaxProcesses.0 = No more variables left in this MIB View (It is past the end of the MIB tree)
```

## SNMPトラップの項目が👆みたいに少ないときはこれ！

こちらの記事がとても参考になりました

https://qiita.com/itohdaigo/items/5567fa1566c287b05e87#etcsnmpsnmpdconf%E3%81%AE%E7%A2%BA%E8%AA%8D

`recommunity`：読み取り専用コミュニティのところを、16bitのセグメントであけてあげる

```bash
# rocommunity: a SNMPv1/SNMPv2c read-only access community name
#   arguments:  community [default|hostname|network/bits] [oid | -V view]

# Read-only access to everyone to the systemonly view
#rocommunity  public default -V systemonly
#rocommunity6 public default -V systemonly
rocommunity  public 172.20.0.0/16
rocommunity6 public 172.20.0.0/16
```

snmpwalkの結果はとても増えた
安易に`snmpwalk -v 2c -c public 172.20.240.6 .`を打つと、しばらく画面に文字が流れ続ける。

ZabbixでSNMP監視対象のLinuxがいたとして
項目がすべてちゃんと取得できていないなー、というときは、これが原因かもしれないと覚えておく。

## 参考

https://qiita.com/Shakapon/items/aab44eaceb75dc8c312e

https://qiita.com/nanbuwks/items/3632b3180e587152bfc7

https://qiita.com/ktaka1104/items/bd178a4eebfa7b07e40a

https://www.zabbix.com/documentation/2.0/jp/manual/config/items/itemtypes/snmptrap