ひよっこエンジニアの備忘録

日常とかSEとしての備忘を書いていきます。

ZabbixでSNMP Trapを監視する手順

自宅のZabbix6.0にてSNMPトラップを受ける設定を実施しました。
思いのほか苦労したので手順をメモしておきます。

ZabbixサーバはUbuntu22.04を利用中。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.3 LTS
Release:        22.04
Codename:       jammy


こちらの記事でZabbixサーバのインストールした環境に設定追加し、SNMP Trapを受信かつZabbix WEB UIで受信したTrapを確認できるようにします。
nrlay00.hatenablog.jp

Zabbixのドキュメントに、Zabbixでトラップ処理するフローが説明があります。
www.zabbix.com

トラップを受信するワークフロー:

  1. snmptrapdがトラップを受信
  2. snmptrapd はトラップをレシーバー スクリプト (Bash,Perl) または SNMPTT に渡します。
  3. 受信者はトラップを解析、フォーマットし、ファイルに書き込みます
  4. Zabbix SNMP トラッパーは、トラップ ファイルを読み取り、解析します。
  5. トラップごとに、Zabbix は、受信したトラップ アドレスと一致するホスト インターフェイスを持つすべての"SNMP トラッパー"アイテムを検索します。 マッチングでは、ホスト インターフェイスで選択した"IP"または"DNS"のみが使用されることに注意してください。
  6. 見つかった項目ごとに、トラップは snmptrap[regexp] の正規表現と比較されます。 トラップは、一致した すべて のアイテムの値として設定されます。 一致するアイテムが見つからず、snmptrap.fallback アイテムが存在する場合、トラップはその値として設定されます。
  7. トラップがアイテムの値として設定されていない場合、Zabbix はデフォルトで、一致しないトラップをログに記録します。 (これは"管理" → "一般設定" → "その他" の "マッチしないSNMPトラップをログに記録" で設定されます。)

とりあえず以下の設定が必要そうです。
SNMPトラップを受信するための準備:
・Zabbixサーバを稼働させているサーバにてSNMPトラップリスナーをインストール。
 今回はsnmptrapdをインストールし設定します。
SNMPトラップリスナーをZabbixサーバー連携させるためのスクリプトを用意。
 ざっと調べた感じ、Zabbixが提供するperlスクリプトで処理するか、snmpttを利用するのが一般的のよう。
 今回はZabbixが提供するperlスクリプトを使います。

Zabbixサーバの設定:
・ZabbixサーバのWEB画面にて、監視対象のデバイスをホストとして追加、かつSNMPトラップを処理するためのアイテムとトリガーを設定。
 (Templateを使えばホスト追加時にTemplateを利用するとアイテムは勝手に作成されるだが、トリガーは自分で設定する必要があった。。)

上記に加え、NW機器のトラップ送信設定も未設定だったためNW機器の設定変更もあわせて実施します。
本記事ではトラップの送信元機器としては既に監視対象機器として登録済みのJuniper SRX300を使用します。




[snmptrapdの設定]

まず必要となるパッケージをインストール。

$ sudo apt update
$ sudo apt install snmp snmp-mibs-downloader snmptrapd snmptt libconfig-inifiles-perl libsnmp-perl libnet-ip-perl

その後Zabbixのソースをダウンロードし、zabbix_trap_receiver.plを/usr/local/bin/へコピーする。

$ wget https://cdn.zabbix.com/zabbix/sources/stable/6.0/zabbix-6.0.10.tar.gz
$ tar zxvf zabbix-6.0.10.tar.gz
$ sudo cp -p ./zabbix-6.0.10/misc/snmptrap/zabbix_trap_receiver.pl /usr/local/bin/


zabbix_trap_receiver.plを編集してログの保存先を変更する。
デフォルトだと/tmp/zabbix_traps.tmpに保存されるようになっているので、/var/log 配下へ変更。

sudo vi /usr/local/bin/zabbix_trap_receiver.pl
```
 ### Option: SNMPTrapperFile
 #       Temporary file used for passing data to the server (or proxy). Must be the same
 #       as in the server (or proxy) configuration file.
 #
 # Mandatory: yes
 # Default:
 #$SNMPTrapperFile = '/tmp/zabbix_traps.tmp'; ←コメントアウト
 $SNMPTrapperFile = '/var/log/snmptrapd/snmptrap.log'; ←追加
```

ログ保存場所変更後、実行権限と保存先のディレクトリを作成する。
snmptrapdから書き込めるようにユーザ/グループを変更する。

$ sudo chmod +x /usr/local/bin/zabbix_trap_receiver.pl
$ sudo mkdir /var/log/snmptrapd
$ sudo chown Debian-snmp:Debian-snmp /var/log/snmptrapd


SNMPTrapd から Zabbix Trap Receiver を呼び出せるようsnmptrapd.conf の末尾に以下を追加。

$ vi /etc/snmp/snmptrapd.conf 
```
perl do "/usr/local/bin/zabbix_trap_receiver.pl";
```


/etc/systemd/system/snmptrapd.serviceの起動オプション変更。

$ sudo vi /etc/systemd/system/snmptrapd.service
```
[Service]
Type=notify
User=Debian-snmp
# ExecStart=/usr/sbin/snmptrapd -LOw -f udp:162 udp6:162 ←コメントアウト
ExecStart=/usr/sbin/snmptrapd -Lsd -f udp:162 udp6:162 ←追加
```

snmptrapd.serviceの再読み込みとサービス再起動

sudo systemctl daemon-reload
sudo systemctl restart snmptrapd
sudo systemctl status snmptrapd
[zabbix_server.conf 設定変更]

zabbix_server.conf も設定変更。

sudo vi /etc/zabbix/zabbix_server.conf
```
### Option: SNMPTrapperFile
#       Temporary file used for passing data from SNMP trap daemon to the server.
#       Must be the same as in zabbix_trap_receiver.pl or SNMPTT configuration file.
#
# Mandatory: no
# Default:
# SNMPTrapperFile=/tmp/zabbix_traps.tmp 
SNMPTrapperFile=/var/log/snmptrapd/snmptrap.log ←追加

```
### Option: StartSNMPTrapper
#       If 1, SNMP trapper process is started.
#
# Mandatory: no
# Range: 0-1
# Default:
# StartSNMPTrapper=0
StartSNMPTrapper=1  ←追加
```

zabbix-serverサービスを再起動する。

sudo systemctl restart zabbix-server
sudo systemctl status zabbix-server
[snmp.confの設定]

OIDからどのようなSNMPトラップを受け取ったか判断するのは困難なので、トラップ名で確認できるようmibの設定をしておきます。
mibを読み込むため、mibs:をコメントアウトし、mibs allを追記するよう/etc/snmp/snmp.confを編集します。

$ sudo vi /etc/snmp/snmp.conf
```
# As the snmp packages come without MIB files due to license reasons, loading
# of MIBs is disabled by default. If you added the MIBs you can reenable
# loading them by commenting out the following line.
#mibs : ←コメントアウト
mibs all  ←追加
```

aptでsnmp-mibs-downloaderをインストールする場合、一部のmibが壊れている?ようなので正しいmibに置き換えておきます。

$ sudo  wget http://www.iana.org/assignments/ianaippmmetricsregistry-mib/ianaippmmetricsregistry-mib -O /usr/share/snmp/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB
$ sudo  wget http://pastebin.com/raw.php?i=p3QyuXzZ -O /usr/share/snmp/mibs/ietf/SNMPv2-PDU
$ sudo  wget http://pastebin.com/raw.php?i=gG7j8nyk -O /usr/share/snmp/mibs/ietf/IPATM-IPMC-MIB

一応サービス再起動。

sudo systemctl restart snmptrapd
sudo systemctl restart snmpd
sudo systemctl restart zabbix-server

ここまででサーバ(CLI)側での設定は完了です。
snmptrapを受け取った際に、/var/log/snmptrapd/snmptrap.logにログが記録されることが想定動作なので自身からテスト用のsnmptrapを出してログに記録されるか確認しておきます。
※-vがバージョン、-cがコミュニティ文字列を指定する引数です。
 今回はバージョン2c、コミュニティ文字列はZABBIXを想定して、以下のコマンドを指定します。

$ sudo snmptrap -v 2c -c ZABBIX localhost '' .1.3.6.1.4.1.8072.100 .1.3.6.1.4.1.8072.100.1 s "TEST"


こんな感じのlocalhostからlocalhostへのトラップログが記録されていればOK。

$ less /var/log/snmptrapd/snmptrap.log
```
PDU INFO:
  community                      ZABBIX
  receivedfrom                   UDP: [127.0.0.1]:32791->[127.0.0.1]:162
  errorstatus                    0
  messageid                      0
  requestid                      1621789364
  errorindex                     0
  version                        1
  notificationtype               TRAP
  transactionid                  293
VARBINDS:
  iso.3.6.1.2.1.1.3.0            type=67 value=Timeticks: (2230938) 6:11:49.38
  iso.3.6.1.6.3.1.1.4.1.0        type=6  value=OID: iso.3.6.1.4.1.8072.100
  iso.3.6.1.4.1.8072.100.1       type=4  value=STRING: "TEST"
```




[Trap送信元機器の設定]

ここからTrap送信元機器である、SRX300のTrap設定を実施します。

どうでもいい話ですが、私はCisco機器を触って育ってきたのでJunosのコマンドにはなかなか馴染めません・・
オペレーションもCiscoとは異なりますが、Junosはcommitするまで設定が反映されないので誤ってターミナルを右クリックして設定流しこみ→意図しない設定変更発生!!のような事故が起こりずらい点は非常にいいなーと感じています。
一方でCiscoは設定投入時にエラーがあれば即はじかれますが、Junosはcommitまたはcommit checkするまでエラーとならずcommitではじかれてしまうとどこに問題があるのか分かりづらいなーと感じてます。私はJunos素人ですが、もう少し慣れればcommitではじかれてもエラー箇所を察せられるようになるのだろうか。。


話を戻して以下Juniperのサイトよりコンフィグを確認!
www.juniper.net

SNMPv1およびSNMPv2トラップの設定
[edit snmp]
trap-group jnpr {
targets {
192.168.69.179;
}
}


以下がSNMPトラップを送信するための設定のようです。

set snmp trap-group <トラップグループ名> targets <Trap送信先>

トラップグループ名:ZABBIX、Trap送信先:192.168.101.11として設定します。

% cli 
root@****> show version
Hostname: ****
Model: srx300
Junos: 15.1X49-D75.5
JUNOS Software Release [15.1X49-D75.5]

root@****# configure
Entering configuration mode

[edit]
root@****# set snmp trap-group ZABBIX targets 192.168.101.11

[edit]
root@****# show | compare
[edit snmp trap-group ZABBIX]
+   targets 192.168.101.11

[edit]
root@****# commit check
configuration check succeeds

[edit]
root@****# commit

設定が完了したらSRXからトラップを飛ばし、snmptrapdのログに記録されるか確認します。
SRXの場合、実際にリンクダウン等のイベントを発生させずとも、request snmp spoof-trapコマンドにて任意のSNMPトラップを飛ばすことができます。
今回はcoldStartのトラップを発生させてテストします。

root@****> request snmp spoof-trap coldStart
Spoof-trap request result: trap sent successfully

root@****> 

Zabbixサーバにてログ確認。
SRX(192.168.10.254)からトラップを受信できているため次へ進みます。

$ less /var/log/snmptrapd/snmptrap.log
```
PDU INFO:
  version                        1
  transactionid                  295
  notificationtype               TRAP
  receivedfrom                   UDP: [192.168.10.254]:58687->[192.168.101.11]:162
  community                      ZABBIX
  errorstatus                    0
  messageid                      0
  errorindex                     0
  requestid                      1427883058
VARBINDS:
  iso.3.6.1.2.1.1.3.0            type=67 value=Timeticks: (51466127) 5 days, 22:57:41.27
  iso.3.6.1.6.3.1.1.4.1.0        type=6  value=OID: iso.3.6.1.6.3.1.1.5.1

※ちなみに本筋とはずれますが、この<トラップグループ名>という部分にかなりハマったのでメモ。。
 任意の名前でよいのかなと適用にグループ名を付けたのですが、どうやらグループ名がコミュニティ文字列にあたるようです。

 実はなかなかsnmptrap.logにログが記録されず、、snmptrapサーバにてtcpdumpを確認するとトラップ自体は受信できていました。
 で、その受信済みのSNMPトラップパケットをよく見ると、、

$ sudo tcpdump -n -vvv port 162
```
XXXXXX IP (tos 0x0, ttl 61, id 2195, offset 0, flags [none], proto UDP (17), length 100)
    192.168.10.254.58687 > 192.168.101.11.162: [udp sum ok]  { SNMPv2c C="trap-group1" { V2Trap(57) R=1427883105  .1.3.6.1.2.1.1.3.0=51509783 .1.3.6.1.6.3.1.1.4.1.0=.1.3.6.1.6.3.1.1.5.1 } }
```

 C=の後にトラップグループ名入ってるけど、これってコミュニティのCでは・・?ということに気づき、トラップグループ名=コミュニティ文字列になるよう設定しなおしたことでnmptrap.logにログが記録されるようになりました。
 publicのままで利用する場合は特に問題ありませんが、publicではなくコミュニティ文字列を指定する場合はトラップグループ名=コミュニティ文字列となるよう設定する必要があります。




[ZabbixサーバWEB画面での設定]

ここまででTrap送信元NW機器の設定とTrapを受けるsnmptrapdの設定が完了していますので、ZabbixのWEB画面でトラップを処理するためのアイテムとトリガーを設定します。
アイテムとトリガーを設定前にトラップ送信元機器のホスト登録が必要となりますが、本記事ではホスト登録部分は割愛します。

今回のトラップ送信元機器であるSRXはこんな感じで登録しており、SNMPでインターフェース設定、TemplateはJuniper by SNMPを利用しています。

まずはアイテムを作成します。
Zabbix WEB UI>Configuration>Hostにてホストの一覧へ遷移し、トラップ送信元機器のItemsをクリックします。
遷移先のページの右上>Create Itemより新規でアイテムを作成します。

  • Name:任意の名前を入力
  • Type:SNMP trap
  • Key:snmptrap fallback
  • Type of information:Log
  • Host interface:トラップ送信元機器のインターフェースを選択
  • History storage period:任意の保存方式を選択
  • Log time format:任意のタイムスタンプフォーマット

※実はTemplateにJuniper by SNMPを利用していると、対象のアイテムは自動的に作成されます。
 Juniper by SNMP以外でもTemplateによっては自動的にアイテムが作成されている可能性があるのでItemsのページで既存のSNMPトラップ用のアイテムがないか確認しましょう。

続いてトリガーを作成します。
Zabbix WEB UI>Configuration>Hostにてホストの一覧へ遷移し、トラップ送信元機器のTriggersをクリックします。
遷移先のページの右上>Create triggerより新規でトリガーを作成します。

  • Name:任意のトリガー名
  • Severity:任意のアラート重大度
  • Expression:アラート条件

  →今回は全てのトラップでアラートを発生させるため、「length(last(/[ホスト名]/snmptrap.fallback))>=1」設定します。
  ※「snmptrap.fallback」は「snmptrap[regexp]」で取得したデータ以外を全て取得しますので、アラート発生させないSNMP trapがある場合は新規に「snmptrap[regexp]」でSNMP trapを取得するアイテムを作成します。

  • PROBLEM event generation mode:「Multiple」を選択
  • Enabled:チェックをつける

以上で設定は完了。
再度SRXからcoldStartのトラップを発生させて、Zabbix WEB UIからトラップ情報を確認できるかテストします。

root@****> request snmp spoof-trap coldStart
Spoof-trap request result: trap sent successfully

root@****> 

Monitoring > Problemに作成したトリガー名で障害通知が来ています。

意図通り、SRXからcoldStartのトラップが送信されていることがわかります。