CentOSコンテナ2台でsnmpgetとsnmptrapの設定メモ

# はじめに
## 検証の目的
Docker で CentOSコンテナ 2台を稼働させて snmpget、snmptrap させてみる。

- SNMP manager側のコンテナ名：snmp-sv
- SNMP agent側のコンテナ名：snmp-cl 
- Docker for MAC： v2.2.0.4(43472)

## dockerのリハビリ
久しぶりに docker 触るので軽くリハビリ。まずは dockerのバージョン確認とか稼働確認。

```console
# バージョン確認
~/work/Docker $ docker --version
Docker version 19.03.8, build afacb8b

# 正常に動くか確認
~/work/Docker $ docker run hello-world
（省略）
Hello from Docker!
This message shows that your installation appears to be working correctly.
(省略)
```
ちなみに hello-world についてはここが非常にためになる。
[Dockerイメージの理解を目指すチュートリアル](https://qiita.com/zembutsu/items/24558f9d0d254e33088f)


# 環境構築
## snmp-svの構築

```
# コンテナ作成
~/work/Docker $ docker run -d --name snmp-sv --hostname snmp-sv --privileged centos:latest /sbin/init
0e6f4a5eee5699b1ebcc4c78d64a8099854a30ac70e3d0bac9ea3b7a09e59e09
~/work/Docker $ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
0e6f4a5eee56        centos:latest       "/sbin/init"        4 seconds ago       Up 2 seconds                            snmp-sv

# コンテナに入る
~/work/Docker $ docker exec -it snmp-sv /bin/bash
```
`--privileged`を付けないと`systemctl`などのコマンドが使えない。以下のようなエラーが出てしまう。
以下を読むと`--cap-add sys_admin`でもいけそう。この辺は今後機会があれば勉強する。
[systemd in docker container without --privileged](https://qiita.com/shusugmt/items/92ece6874ba5aeff2b41)

```
# systemctl が実行できない
[root@centos8 /]# systemctl status
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

# PID=1 が systemd ではなくて /sbin/init になってる
[root@centos8 /]# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.2  93640  5352 pts/0    Ss+  10:25   0:00 /sbin/init
root         7  0.0  0.1  12128  3288 pts/1    Ss   10:25   0:00 /bin/bash
root        24  0.0  0.1  44632  3428 pts/1    R+   10:27   0:00 ps aux
```
続いて、コンテナの中での作業を実施していく。

```
# OS情報
[root@snmp-sv /]# cat /etc/centos-release
CentOS Linux release 8.4.2105
[root@snmp-sv /]# uname -r
4.19.76-linuxkit

# dnf update
[root@snmp-sv /]# dnf update

# モジュールインストール、バージョン確認
[root@snmp-sv /]# dnf -y install net-snmp net-snmp-utils
[root@snmp-sv /]# snmpd -v

NET-SNMP version:  5.8
Web:               http://www.net-snmp.org/
Email:             net-snmp-coders@lists.sourceforge.net

[root@snmp-sv /]# snmpget -V
NET-SNMP version: 5.8

# IP確認
[root@snmp-sv /]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000
    link/tunnel6 :: brd ::
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# snmptrapd を編集
[root@snmp-sv /]# cat >> /etc/sysconfig/snmptrapd << "EOF"
> OPTIONS="-Ls6 -p /var/run/snmptrapd.pid"
> EOF
[root@snmp-sv /]# tail /etc/sysconfig/snmptrapd 
# snmptrapd command line options
# '-f' is implicitly added by snmptrapd systemd unit file
# OPTIONS="-Lsd"
OPTIONS="-Ls6 -p /var/run/snmptrapd.pid"

```
`/etc/sysconfig/snmptrapd` で `OPTIONS="-Ls6 -p /var/run/snmptrapd.pid"` を追記しているのは、snnmptrapd 実行時のオプションを指定するため。`-Ls6`でログ出力先を syslog にしてかつファシリティ local6 を指定。`-p  /var/run/snmptrapd.pid`でPIDファイルを作成（もしかしたらもういらないかも）。
[snmptrapd (8) - Linux Man Pages](https://www.systutorials.com/docs/linux/man/8-snmptrapd/)

```
# snmptrapd.conf を編集
[root@snmp-sv /]# cat >> /etc/snmp/snmptrapd.conf << "EOF"
> authCommunity log,execute,net traptest
> EOF
[root@snmp-sv /]# tail /etc/snmp/snmptrapd.conf 
# Example configuration file for snmptrapd
#
# No traps are handled by default, you must edit this file!
#
# authCommunity   log,execute,net public
# traphandle SNMPv2-MIB::coldStart    /usr/bin/bin/my_great_script cold
authCommunity log,execute,net traptest

# サービス起動
[root@snmp-sv /]# systemctl enable snmptrapd
[root@snmp-sv /]# systemctl start snmptrapd
```

`/etc/snmp/snmptrapd.conf`での設定内容としては、`authCommunity log,execute,net traptest`でアクセス制御を設定している。コミュニティ名が「traptest」のもののみ受け取る。log,execute,net については以下の通り。

- log：ログ出力を許可する。ファイル出力、標準出力、エラー出力、syslogなどが該当。
- execute：プログラムの実行を許可する。例えば、メール転送を行うtraptoemailなどのperlスクリプト等が該当。
- net：他のsnmptrapdサーバへの転送を許可する。

```
# rsyslog インストール
[root@snmp-sv /]# dnf -y install rsyslog

# syslog 設定
[root@snmp-sv /]# cat >> /etc/rsyslog.d/snmptrapd.conf << "EOF"
> local6.*     /var/log/snmptrapd.log
> EOF
[root@snmp-sv /]# tail /etc/rsyslog.d/snmptrapd.conf 
local6.*     /var/log/snmptrapd.log

# サービス起動
[root@snmp-sv /]# systemctl enable rsyslog
[root@snmp-sv /]# systemctl start rsyslog
```
`local6.*     /var/log/snmptrapd.log`で local6 のファシリティのログ出力先を指定。これで受信した trap は /var/log/snmptrapd.log に書かれるようになる。

## snmp-clの構築
続いて snmp agent 側を設定していく。

```
# snmp-cl コンテナ作成
~/work/Docker $ docker run -d --name snmp-cl --hostname snmp-cl --privileged centos:latest /sbin/init
75bf8c2ea1be091bbb452a0025c30a54dd0a0c8f31242b0561df18d3993bf58e
~/work/Docker $ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
75bf8c2ea1be        centos:latest       "/sbin/init"        7 seconds ago       Up 7 seconds                            snmp-cl
0e6f4a5eee56        centos:latest       "/sbin/init"        4 hours ago         Up 4 hours                              snmp-sv
~/work/Docker $ docker exec -it snmp-cl /bin/bash

# dnf update
[root@snmp-sv /]# dnf update

# モジュールインストール
[root@snmp-cl /]# dnf -y install net-snmp net-snmp-utils
[root@snmp-cl /]# snmpd -v

NET-SNMP version:  5.8
Web:               http://www.net-snmp.org/
Email:             net-snmp-coders@lists.sourceforge.net

[root@snmp-cl /]# snmpget -V
NET-SNMP version: 5.8

# IP確認
[root@snmp-cl /]# ip addr 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
    link/ipip 0.0.0.0 brd 0.0.0.0
3: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN group default qlen 1000
    link/tunnel6 :: brd ::
18: eth0@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever

# snmpd.conf に以下を追記
[root@snmp-cl /]# cat >> /etc/snmp/snmpd.conf << "EOF"
> com2sec LocalNetwork      default         test
> group   LocalGroup        v1              LocalNetwork
> group   LocalGroup        v2c             LocalNetwork
> view    AllView           included        .1
> access  LocalGroup        ""      any     noauth  exact   AllView         none    none
> EOF

# サービス起動
[root@snmp-cl /]# systemctl enable snmpd.service
[root@snmp-sv /]# systemctl start snmpd.service
```

snmpd.conf での設定内容は以下の通り。

- `com2sec LocalNetwork      default  test`：セキュリティの定義を行う。default(これは 0.0.0.0 なので全てのネットワーク)からの接続を受け付け、コミュニティ名（認証パスワードのようなもの）を test とする LocalNetwork というセキュリティを定義している。
- `group   LocalGroup        v2c             LocalNetwork`：セキュリティ LocalNetwork は SNMPv2c を使うことをグループ名 LocalGroup として定義している。
- `view    AllView        included        .1`： MIBツリーの参照を許可する範囲を定義。ここでは全ての参照を可能とする AllView というビュー定義となっている。`.1`で全てのMIBを対象としてる。
- `access  LocalGroup        ""      any     noauth  exact   AllView         none    none`：アクセス許可の定義。LocalGroup に対して、AllView を紐付ける。


#テスト
## 環境確認

```
# lsof入ってなかったのでインストール
[root@snmp-sv /]# dnf -y install lsof

# lsof。ポートは UDP/161 を使ってることがわかる。
[root@snmp-sv /]# lsof -c snmpd -a -i -P
COMMAND PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
snmpd    62 root    6u  IPv4 329881      0t0  UDP *:161 
snmpd    62 root    7u  IPv4 329882      0t0  TCP localhost:199 (LISTEN)

```

## snmpwalk

```
[root@snmp-sv /]# snmpwalk -On -v 2c -c test 172.17.0.3 ip
.1.3.6.1.2.1.4.1.0 = INTEGER: forwarding(1)
.1.3.6.1.2.1.4.2.0 = INTEGER: 64
.1.3.6.1.2.1.4.3.0 = Counter32: 382
.1.3.6.1.2.1.4.4.0 = Counter32: 0
（省略）
```

## snmpget

```
[root@snmp-sv /]# snmpget -v 2c 172.17.0.3 -c test .1.3.6.1.2.1.4.1.0
IP-MIB::ipForwarding.0 = INTEGER: forwarding(1)
```

## snmp trap

```
[root@snmp-cl /]# snmptrap -v 2c -c traptest 172.17.0.2 '' 1.1.1.1.1.1 1.1.1.1.1.1.1.1 s "hogehoge"
```

snmp-sv 側で以下の通り受信できた。

```
[root@snmp-sv /]# tail -f /var/log/snmptrapd.log 
[172.17.0.2]:162]:#012DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (9071038) 1 day, 1:11:50.38#011SNMPv2-MIB::snmpTrapOID.0 = OID: iso.1.1.1.1.1#011iso.1.1.1.1.1.1.1 = STRING: "hogehoge"
```

# 参考
[SNMPTrapを試す](https://kstoneriver.com/tech/2020/01/01/snmptrap%E3%82%92%E8%A9%A6%E3%81%99/)
[snmptrapd 設定方法](https://changineer.info/server/monitoring/monitoring_snmptrapd.html#toc4)
[net-snmpの設定](https://qiita.com/toshiro3/items/e8f87da88cd383a6421d)
[snmpd 設定方法 (CentOS8.2とWindows Server 2019の場合)](https://changineer.info/server/monitoring/monitoring_snmpd.html#toc10)
[snmpget/snmpwalkコマンドの使い方](https://qiita.com/hana_shin/items/856529cdab1b46668fc2#2-%E7%92%B0%E5%A2%83)