SNMPトラップのハンドリング(CentOS 8編)

Zabbix Advent Calendar 2020の24日目です。

先日、コミュニティサイト上で、SNMPトラップを受けるための設定を改めて整理すると書いたので、この場に記述しようと思います。
現時点(2020年12月)での情報ですので、時間の経過によって使用できるリポジトリやソフトウェアが変更される場合がありますのでご注意ください。


# 導入環境の想定

今回、環境を構築するのは、CentOS 8上に構築することとします。
CentOS 8の初期のリリースでは、net-snmp-perlパッケージが存在しないため、net-snmp-perlのパッケージを別途用意するなどの対応が必要でした。
しかし、現時点(2020年12月)では、CentOS 8.3.2011のAppStream内にnet-snmp-perlパッケージが公開されるようになったようです。

http://ftp.riken.go.jp/Linux/centos/8.3.2011/AppStream/x86_64/os/Packages/net-snmp-perl-5.8-17.el8.x86_64.rpm

これを使用すれば、別途用意するということが必要なくなりました。

Zabbixは、現時点の最新のLTSである5.0を使用することとします。

あと、SNMPトラップを受け取って処理する方法として、以下の2つの方法がありました。

* snmpttを使用
* zabbix_trap_receiver.plを使用

前者は、受信したトラップを置換して読みやすいメッセージに変換できるので便利なのですが、このsnmpttのパッケージがCentOS 8用だとEPEL上に存在しないため、別途用意するのが面倒です。
後者であれば、net-snmp-perlのパッケージとそれに依存するperl関連のパッケージがインストールされていれば使用することができます。

今回は、後者のzabbix_trap_receiver.plを使用することとします。
また、SNMPのバージョンはv2で、コミュニティ名は「public」としておきます。


# SNMPトラップを受けるときのデータの流れ

Zabbixでは、SNMPトラップを受けるときには、snmptrapd経由でトラップを受けるようにします。
データの流れとしては、以下のような流れになります。

![dataflow_s.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101989/99133164-7c76-5511-e92e-ee64157c11c7.png)

ネットワークデバイスなどで発生したトラップをZabbixサーバーを稼働しているサーバー上で起動したsnmptrapdで受け取って、受け取ったトラップをスクリプトを介して成型済みログファイルに出力します。
その出力されたファイルを、Zabbixサーバーの「snmp trapper」というプロセスが読み込んで、アイテムの値として処理するわけです。


# 事前に決めておくこと

環境を構築する前に以下の2つを決めておくことが必要です。

* zabbix_trap_receiver.plを配置する場所
* snmptrapdとZabbixサーバーを仲介するトラップのログファイル名

前者は、パッケージに含まれていない独自のスクリプトですので、「/usr/local/bin/zabbix_trap_receiver.pl」に配置することとします。
後者は、「/var/log/snmptrap/snmptrap.log」という名前のログファイルとすることとします。


# 導入手順

## Zabbbixのインストール

CentOS 8上にバックエンドとしてMySQLを使用してZabbix 5.0の環境を構築する手順としては、以下のリンク先を参照してください。

* [Zabbix 5.0をCentOS 8にインストール(MySQL編)](https://qiita.com/atanaka7/items/282a3499e135e00edcdc)

## SNMPトラップを受けるために必要なパッケージのインストール

SNMPトラップを受けて成型ログ出力処理をする「zabbix_trap_receiver.pl」を実行するために必要となる「net-snmp」「net-snmp-utils」「net-snmp-perl」のパッケージをインストールします。

```
# dnf install net-snmp net-snmp-utils net-snmp-perl
```

## SNMPトラップハンドリング用のスクリプトの配置と設定

トラップハンドリング用のスクリプト「zabbix_trap_receiver.pl」は、ソースの中に含まれています。
ソースのターボールを取得して展開し、先に決めておいたディレクトリにファイルを配置します。

```
# wget https://cdn.zabbix.com/zabbix/sources/stable/5.0/zabbix-5.0.7.tar.gz
# tar zxvf zabbix-5.0.7.tar.gz
# cp -p zabbix-5.0.7/misc/snmptrap/zabbix_trap_receiver.pl /usr/local/bin/
```

そしてスクリプトファイル内にあるログファイルのパスを設定します。

```
# vi /usr/local/bin/zabbix_trap_receiver.pl
```

設定する内容は以下の通りです。

```
#$SNMPTrapperFile = '/tmp/zabbix_traps.tmp';
$SNMPTrapperFile = '/var/log/snmptrap/snmptrap.log';
```

既存の設定をコメントアウトして、先に決めたログファイル名の設定とするわけです。
ついでに実行権限も付けておき、ログ出力先のディレクトリの作成もしておきましょう。

```
# chmod +x /usr/local/bin/zabbix_trap_receiver.pl
# mkdir /var/log/snmptrap
```

## snmptrapdの設定

続いてsnmptrapdの設定です。
設定ファイルである/etc/snmp/snmptrapd.confを編集します。

```
# vi /etc/snmp/snmptrapd.conf
```

SNMPv2で、コミュニティ名が「public」である場合は、/etc/snmp/snmptrapd.conf内に以下の設定を行います。

```
authCommunity log,execute,net public
perl do "/usr/local/bin/zabbix_trap_receiver.pl";
```

コミュニティ名が異なる場合や、zabbix_trap_receiver.plを配置したパスが異なる場合は、それぞれの環境に合わせて修正してください。
設定が終わったら、snmptrapdを起動します。

```
# systemctl start snmptrapd
# systemctl enable snmptrapd
```

ここまで設定できたら、スクリプトが実行されるかコマンドでテスト用にSNMPトラップを投げてみましょう。
これは、linkDownのOIDを指定した場合です。

```
# snmptrap -v 2c -c public 127.0.0.1 '' .1.3.6.1.6.3.1.1.5.3
```

/var/log/snmptrap/snmptrap.logに時刻で始まるログが出力されたはずです。


## Zabbixサーバーの設定

次は、Zabbixサーバーでこのログを読み取る設定を行います。

```
# vi /etc/zabbix/zabbix_server.conf
```

設定するのは以下の設定を挿入します。

```
StartSNMPTrapper=1
```

設定を反映するには、Zabbixサーバーの再起動が必要なので、再起動を行います。

```
# systemctl restart zabbix-server
```


## Firewallの設定

デフォルトの設定ではSNMPトラップを受けられないので、受け取れるよう許可設定を行います。

```
# firewall-cmd --add-port=162/udp --zone=public --permanent
# firewall-cmd --reload
```


## ログのローテーション

ログファイルは溜まったままにしておかないようにするために、ローテーションも設定しておきましょう。

```
# vi /etc/logrotate.d/snmptrap
```

例えば、以下のような設定が考えられます。

```
/var/log/snmptrap/snmptrap.log {
	daily
	rotate 7
	compress
	delaycompress
	missingok
	notifempty
}
```

どのくらいの期間保存するのかを考慮してローテーションの設定を行ってください。


# Zabbixでのトラップのテスト

ZabbixサーバーがSNMPトラップを受けられるようになったかを確認しておきましょう。
実際のネットワーク機器から故意にトラップをなげるのは難しいと思うので、Linuxサーバーからコマンドを使用してトラップを投げ、それが受け取れるかを確認してみましょう。

別途、SNMPトラップ送信用のサーバーを用意するのが難しい場合もあるかと思いますので、ローカルからトラップを投げる方法を使用しようと思います。


## ホストとアイテムの作成

今回はテスト用にローカルからのトラップを受け取れるようなホストを作成します。

![hostsetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101989/c7c68814-84a9-4b6b-5fea-fd0ac18aa021.png)


ポイントしては、インターフェースとしてSNMPのインターフェースを用意することです。
実際のネットワーク機器をホストとして登録する際には、IPアドレスやポート番号、SNMPのバージョンやコミュニティを環境に合わせて設定してください。
デフォルトで設定されるSNMPコミュニティに「{$SNMP_COMMUNITY}」とあるのは、グローバルマクロで設定されているマクロです。
デフォルトでは、「public」という値が設定されています。
個別に設定してもよいのですが、複数のホストで同じ設定を使用する場合は、マクロを使用することで一斉に変更する時などの管理が容易になります。

続いて、そのホストにアイテムを作成します。
ここでは、すべてのトラップを受け取れるよう「snmptrap.fallback」というアイテムキーを使用することとします。
![itemsetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101989/8a10e028-3d34-82d8-e187-992686aec06d.png)


実際のホストを設定する場合は、発生したトラップごとに障害かどうか判断分岐が必要になると思いますので、「snmptrap[regexp] 」を使用して引数のregexpの部分に正規表現を使用して、特定のトラップを受け取るアイテムを作成した方が良いと思います。

データ型は、「ログ」でも「テキスト」でも動くと思います。
「ログ」を使用した場合は、トラップ内に含まれるタイムスタンプを読み込むことができるので、今回の例ではデータ型として「ログ」を選択し、ログに出力されている日付のフォーマットに合わせてログの時間の形式を指定してみました。

## テスト用トラップをZabbixサーバーに送る

さて、ここではテスト用にローカルでなげるだけなので、先ほどと同様に以下のコマンドを実行します。

```
# snmptrap -v 2c -c public 127.0.0.1 '' .1.3.6.1.6.3.1.1.5.3
```

別のサーバーから送る場合は、送り先のIPアドレスを引数に指定して実行してください。

```
# snmptrap -v 2c -c public ＜ZabbixサーバーのIPアドレス＞ '' .1.3.6.1.6.3.1.1.5.3
```


## ZabbixのWebインターフェースでの確認

受け取ったトラップは、「監視データ」->「最新データ」の該当するアイテムのヒストリをクリックすると、以下のように表示されるはずです。

![trapdata.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101989/e8546876-dfd3-b8fb-a0bc-a8fff9be09cc.png)


表示されない場合は、以下のようなログがZabbixサーバーのログ(/var/log/zabbix/zabbix_server.log)に出力されているはずです。

```
  1809:20201224:184201.901 unmatched trap received from "192.168.1.50": 18:42:00 2020/12/24 PDU INFO:
```

これは、Zabbixサーバーが受け取ったSNMPトラップの中に含まれる情報と、Zabbix上に登録されたホストの情報とが一致しないために発生します。この場合だと、IPアドレスが192.168.1.50のSNMPインターフェースを持つホストが登録されていなかったのです。

このようなログが出力された場合は、ホストやアイテムの設定を見直してみてください。

# 独自MIBを使用したい場合

CentOSで最初に登録されているMIB情報は限られているので、ベンダー固有のMIBを追加したい場合があると思います。
その場合は、例えば「/usr/share/snmp/vender_mibs」というディレクトリを作成して、その下にベンダ固有のMIBファイルを置き、/etc/snmp/snmp.confというファイルを作成して、その中にそのディレクトリのMIB情報も読み込むよう設定してみてください。

設定例：

```
mibdirs /usr/share/snmp/mibs:/usr/share/snmp/vender_mibs
mibs all
```


# 最後に

用途によっては、snmpttを使用した方が良い場合もあると思いますが、あまり苦労せずにCentOS 8上でSNMPトラップを受信してZabbixで監視する方法として紹介させていただきました。

時間の経過によって陳腐化してしまうかもしれませんが、現時点(2020年12月)の情報として参考にしてみてください。

ご質問等があれば、[コミュニティのサイト](http://www.zabbix.jp/)のフォーラムをご利用ください。