Zabbix で YAMAHA ルータを監視する

ふと「そういえばネットワーク機器の監視ってやったことないな」となってちょろっと入門してみたメモ。(SNMP, Zabbix ともに初めてなのでかなり初心者っぽい記事になっている。)

## 0. 用語
### SNMP
**SNMP** (Simple Network Management Protocol) は、ネットワーク機器（ルーター, スイッチ, サーバー など）を監視・管理するための通信プロトコル。デフォルトでは UDP 161 番ポートが使用される。

監視する側を **Manager** / 監視される側を **Agent** と呼び、基本的には Manager から Agent に定期的にリクエストを送信してデータを取得したり設定を管理したりするが、機器側で何かしら障害などのイベントが発生した場合は Agent から Manager に対して通知を送信する仕組みもある。(**Trap** という)

プロトコルのバージョンは主に SNMPv1 / SNMPv2c / SNMPv3 の3種類があり、SNMPv3 では認証と暗号化に対応している。

### MIB
**MIB** (Management Information Base) は SNMP でやりとりされる情報の構造を定義したもの。MIB は木構造だが、各ノードに割り当てられている **OID** (Object Identifier) によってノードが一意に特定される。例えば OID `1.3.6.1.2.1.1.5.0` は「sysName (機器名)」を意味する。

MIB の構造は RFC で定義されており上記の sysName などは **標準 MIB** 領域のノードとして定義されているが、さらに MIB には **拡張 MIB** (プライベート MIB) 領域が定められていて各ベンダが独自に構造を定義することができるようになっている。例えば YAMAHA ルータは標準 MIB に含まれない種類のデータを返すことができて、その構造については公式リファレンスと MIB ファイルが公開されている。[^yamaha-mib]

[^yamaha-mib]: [SNMP MIBリファレンス | RTpro - ヤマハ](https://www.rtpro.yamaha.co.jp/RT/docs/snmp/snmp_mibref_list.html)

## 1. YAMAHA ルータの情報を取得できるようにする
自宅にあるルータが YAMAHA NVR700W なので今回はこのデータを取得できるようにしていく。

※ この記事中では、ルータの IP アドレスは `192.168.100.1` で、作業している端末 (MacBook) の IP アドレスは `192.168.100.10` ということにしておく。

### YAMAHA ルータの設定
作業端末の IP を指定して SNMPv2c を許可する。[^yamaha-snmpv2c]

※ 本当は SNMPv3 でやるのがセキュアで良いのかもしれないが、今回はちょっと触ってみたかっただけなので設定が簡単そうな SNMPv2c にした。

[^yamaha-snmpv2c]: [21.6 SNMPv2c によるアクセスを許可するホストの設定](https://www.rtpro.yamaha.co.jp/RT/manual/rt-common/snmp/snmpv2c_host.html)

```:NVR700W のコマンド
snmpv2c host 192.168.100.10 public
```

### snmpwalk してみる
試しに、標準 MIB の受信トラフィック量を表すノード ifInOctets (OID: `1.3.6.1.2.1.2.2.1.10`) を `snmpwalk` コマンドで取得してみる。

※ macOS では `snmpwalk` コマンドがデフォルトで入っているので何もしなくても使えた。

``` console
$ snmpwalk -v 2c -c public 192.168.100.1 1.3.6.1.2.1.2.2.1.10
IF-MIB::ifInOctets.1 = Counter32: 2467833741
IF-MIB::ifInOctets.2 = Counter32: 0
IF-MIB::ifInOctets.3 = Counter32: 4074117545
IF-MIB::ifInOctets.4 = Counter32: 0
IF-MIB::ifInOctets.5 = Counter32: 0
IF-MIB::ifInOctets.6 = Counter32: 0
IF-MIB::ifInOctets.7 = Counter32: 0
IF-MIB::ifInOctets.8 = Counter32: 4264280814
IF-MIB::ifInOctets.9 = Counter32: 0
IF-MIB::ifInOctets.10 = Counter32: 0
(以下略)
```

`.1` `.3` `.8` が受信トラフィックがあるインタフェースっぽいが、それぞれが何を表しているのか謎...。

## 2. Zabbix でダッシュボードを作る
SNMP データの収集と可視化は、調べると Prometheus SNMP Exporter で収集して Grafana で可視化する方法がイマドキっぽいようだが、Zabbix を使う方法のほうが手軽そうだったので今回は Zabbix でやってみることにした。今回は試しに触ってみたかっただけなので、各選択肢のメリデメなどはちゃんと比較していない。

### Zabbix を立てる
Zabbix は公式で Docker イメージが提供されている[^zabbix-docker]ので、ローカルで試しに動かすだけなら Docker Compose の設定ファイルを書くだけで簡単にできた。

[^zabbix-docker]: [Zabbix SIA | Docker Hub](https://hub.docker.com/u/zabbix)

```yaml:compose.yml
services:

  web:
    image: zabbix/zabbix-web-nginx-pgsql:7.2-alpine-latest
    ports:
      - 8080:8080
    environment:
      DB_SERVER_HOST: postgres
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: deadbeef
      ZBX_SERVER_HOST: server
      PHP_TZ: Asia/Tokyo

  server:
    image: zabbix/zabbix-server-pgsql:7.2-alpine-latest
    volumes:
      - zabbix:/var/lib/zabbix
    environment:
      DB_SERVER_HOST: postgres
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: deadbeef
      ZBX_ENABLE_SNMP_TRAPS: true

  snmptraps:
    image: zabbix/zabbix-snmptraps:7.2-alpine-latest
    volumes:
      - zabbix:/var/lib/zabbix
    ports:
      - 162:162/tcp
      - 162:162/udp

  postgres:
    image: postgres:17
    volumes:
      - postgres:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: deadbeef

volumes:
  zabbix:
  postgres:
```

※ SNMP Trap を受信するための zabbix-snmptraps の設定も記述しているが、今回の記事中では Trap を送信する設定までは扱っていない。

`docker compose up` で起動させたら http://localhost:8080/ にアクセスして、ユーザ名 `Admin` パスワード `zabbix` でログインすることができた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/e92dad4e-7025-4615-8af8-0898054aab75.png)

### データを収集する設定
host を追加する。(※ `Host name` `Host groups` は適当)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/1c624ef9-014b-479d-91cd-228cd270a747.png)

item として前項でも使用した ifInOctets のうちひとつを取得する設定を追加してみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/6f02cf97-b26f-4f04-bb7a-338dc91c460e.png)

すこし時間をおいてから Graph をみてみると、無事に取れているっぽい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/45b3ec34-a37b-441b-97e0-cb65e827df0f.png)

### YAMAHA ルータ用の MIB を追加
YAMAHA ルータが提供する拡張 MIB 領域の構造 (MIB ファイル) は公式サイトで公開されている[^yamaha-mib]ので、これを Zabbix に登録してみる。

```console:server コンテナ内で実行するコマンド
$ cd /var/lib/zabbix/mibs/
$ wget http://www.rtpro.yamaha.co.jp/RT/docs/mib/yamaha-private-mib.tar.gz
$ tar xzf yamaha-private-mib.tar.gz
$ rm -f yamaha-private-mib.tar.gz
```

登録はできたものの、これをやっておくと何が嬉しいのかはまだよくわかっていない。(拡張 MIB データを取得するだけなら OID がわかればできるし)

## TODO: 次にやること
今回は時間がなかったので「とりあえず何らかのデータを取得してグラフを出す」だけで終わってしまった。

まだ「監視ダッシュボードを作った」感はないので、やりたいことはまだ色々ある。

- Zabbix テンプレートを作る
    - 取得するデータ項目の定義
    - グラフの定義
- Trap を受け取れるようにする
- ダッシュボードを作る
- 通知できるようにする