スクリプトのお勉強

SNMPTrap を Kafka に転送するツール:snmptrap-kafka-forwarder の紹介

投稿日:

はじめに

こんにちは!今回は、ネットワーク監視の世界で古くから使われている SNMPTrap を、モダンなデータ基盤である Apache Kafka に連携するための便利なツール「snmptrap-kafka-forwarder」を紹介します。このプロジェクトは、Python で実装されており、ネットワーク機器から送られてくる大量のトラップ情報をリアルタイムで処理・分析したい場合に非常に役立ちます。

このツールが解決する課題

ネットワーク機器やサーバーは、異常事態や重要なイベントが発生した際に SNMPTrap を送信します。しかし、従来の Trap 受信サーバーは、受信したデータを単純にログファイルに書き出すだけのものが多く、その後のデータ活用が難しいという課題がありました。

snmptrap-kafka-forwarderは、この課題を解決します。受信した SNMPTrap を構造化されたデータ(JSON 形式)に変換し、指定された Kafka のトピックに転送します。これにより、以下のようなメリットが生まれます。

  • スケーラビリティ: Kafka を介すことで、大量のトラップメッセージを安定して処理できます。
  • リアルタイム性: Stream 処理エンジン(Flink, Spark Streaming など)と連携し、リアルタイムでの異常検知や分析が可能になります。
  • データ活用: Kafka に集約されたデータは、データレイクや DWH に保存し、長期的な傾向分析や可視化に活用できます。

主な機能

このツールの主な機能は以下の通りです。

  • SNMPTrap 受信: 指定した IP アドレスとポートで SNMP v1/v2c のトラップを待ち受けます。
  • MIB による OID の名前解決: 事前にコンパイルした MIB(管理情報ベース)ファイルを使って、数値だけの OID(例: 1.3.6.1.2.1.1.3.0)を、人間が読める形式(例: SNMPv2-MIB::sysUpTime.0)に変換します。
  • JSON 形式への変換: 受信したトラップの情報を、送信元 IP、コミュニティ名、タイムスタンプ、OID と値のペアなどを含む JSON オブジェクトに整形します。
  • Kafka への転送: 整形した JSON データを指定した Kafka トピックにプロデュースします。
  • 柔軟な設定: config.jsonファイルで、SNMP の待受ポートやコミュニティ名、Kafka の接続先などを簡単に変更できます。
  • デーモン化対応: systemdのサービスファイルが同梱されており、Linux サーバー上で安定したバックグラウンド実行が可能です。
  • コンテナ対応: Dockerfileが用意されており、Docker コンテナとして手軽にデプロイできます。

プロジェクトの構造と技術スタック

このツールは以下の主要なファイルとライブラリで構成されています。

  • snmptrap_kafka_forwarder.py: メインの処理を記述した Python スクリプトです。
  • config.json.sample: 設定ファイルのサンプルです。これをコピーしてconfig.jsonを作成します。
  • pyproject.toml: プロジェクトの依存関係を定義しています。
    • pysnmp: SNMP プロトコルのためのコアライブラリ。
    • kafka-python: Kafka と連携するためのライブラリ。
    • pysmi: MIB をコンパイルするために使用します。
  • tools/compile_mib.py: MIB ファイルをpysnmpが読み込める Python 形式にコンパイルするためのスクリプトです。
  • tools/mibs/: コンパイル対象の MIB ファイルを配置するディレクトリです。
  • docker/Dockerfile: Redpanda(Kafka 互換のブローカー)を起動するためのDockerfileです。
  • docker-compose.yml: Redpandaをconsole付きで起動する際に使用します。console-config.ymlも同様です。
  • etc/snmptrap-kafka-forwarder.service: systemd でサービスとして実行するための設定ファイルです。

作成環境

  • WSL2
    • Ubuntu 24.04 LTS
  • python 3.12
  • podman-compose
    • podman-compose version: 1.0.6
    • podman version: 4.9.3

セットアップと実行方法

1. 設定ファイルの準備

まず、config.json.sampleをコピーしてconfig.jsonを作成します。

{
  "snmp": {
    "host": "0.0.0.0",
    "port": 16200,
    "communities": ["public", "private", "internal"]
  },
  "kafka": {
    "bootstrap_servers": "localhost:9092",
    "topic": "snmp-traps",
    "security_protocol": "PLAINTEXT"
  }
}

環境に合わせて、Kafka の接続先(bootstrap_servers)や待受ポートなどを変更してください。

2. MIB のコンパイル

このツールが OID を名前に解決するためには、監視対象の機器が使用する MIB ファイルをコンパイルしておく必要があります。

  1. tools/mibs/ディレクトリに、ベンダーから提供された MIB ファイル(.mib.txtファイル)を置きます。
  2. tools/compile_mib.pyスクリプト(またはそれに類するスクリプト)を実行して、tools/compiled_mibs/ディレクトリに.py形式のコンパイル済み MIB を生成します。

3. 依存関係のインストールと実行

README.mdに記載の通り、uvなどのパッケージ管理ツールを使って依存関係をインストールします。

# 仮想環境の作成と有効化
uv venv
source .venv/bin/activate
uv sync
# アプリケーションの実行
python snmptrap_kafka_forwarder.py

4. サービスとしての実行 (systemd)

Linux サーバーで永続的に実行する場合は、etc/snmptrap-kafka-forwarder.serviceファイルを/etc/systemd/system/にコピーし、パスなどを環境に合わせて修正した上で、以下のコマンドでサービスを有効化・起動します。

sudo systemctl enable snmptrap-kafka-forwarder.service
sudo systemctl start snmptrap-kafka-forwarder.service

5. Redpanda(kafka互換) の起動

kafka が起動していないと、このサービスを起動しても処理を開始しません。

kafkaの実装は複数ありますが、ここではRedpandaを使用します。
起動の仕方は以下の通りです。

$ podman-compose up -d --build

config.jsonで設定した接続先にkafkaが設定されていれば、基本的には何でも構いません。

実際例

手元で実際に起動し、テストする一連の手順を行ってみます。

kafka 起動

コマンドラインでkafkaを起動します。

### 先にredpandaを起動する。同時にconsoleを起動
$ podman-compose up -d --build
### podman上のkafraに設定するための設定
$ echo '127.0.0.1 redpanda-0' | sudo tee -a /etc/hosts

http://localhost:8080にアクセスして、topicとして snmp-trapsを作成します。

本体起動

以下の手順でsnmpkafkaforwarder.pyを起動します。

$ uv venv
Using CPython 3.12.3 interpreter at: /usr/bin/python3.12
Creating virtual environment at: .venv
Activate with: source .venv/bin/activate
$ source .venv/bin/activate
$ uv sync
$ python snmptrap_kafka_forwarder.py
...
2025-09-15 14:55:23,797 - INFO - SNMPトラップの待受を開始します: 0.0.0.0:16200, Communities: ['public', 'private', 'internal']

テスト用にSNMPtrapを送信する。

以下の手順でSNMPtrapを送信できます。

### 別コンソールで以下を行う
$ source .venv/bin/activate
$ python tests/bin/send_snmp_trap.py
Trap sent successfully!
Trap Host: 127.0.0.1:16200
Community: public
Variables: []

送信に成功すると、以下のようにtopicに出てきます。

テスト結果

メッセージ内容は以下の通りです。

{
    "source_ip": "127.0.0.1",
    "source_port": 44466,
    "community": "",
    "protocol_version": "v1/v2c",
    "timestamp": "2025-09-15T15:11:56.521506Z",
    "variables": [
        {
            "oid": "SNMPv2-MIB::sysUpTime.0",
            "oid_full": "1.3.6.1.2.1.1.3.0",
            "value": "0",
            "value_type": "TimeTicks"
        },
        {
            "oid": "SNMPv2-MIB::snmpTrapOID.0",
            "oid_full": "1.3.6.1.6.3.1.1.4.1.0",
            "value": "1.3.6.1.4.1.9694.1.4.3.0.1",
            "value_type": "ObjectIdentifier"
        },
        {
            "oid": "SNMP-COMMUNITY-MIB::snmpTrapAddress.0",
            "oid_full": "1.3.6.1.6.3.18.1.3.0",
            "value": "0.0.0.0",
            "value_type": "IpAddress"
        },
        {
            "oid": "SNMP-COMMUNITY-MIB::snmpTrapCommunity.0",
            "oid_full": "1.3.6.1.6.3.18.1.4.0",
            "value": "public",
            "value_type": "OctetString"
        },
        {
            "oid": "SNMPv2-MIB::snmpTrapEnterprise.0",
            "oid_full": "1.3.6.1.6.3.1.1.4.3.0",
            "value": "1.3.6.1.4.1.9694.1.4.3",
            "value_type": "ObjectIdentifier"
        },
        {
            "oid": "PEAKFLOW-SP-MIB::spAlertID",
            "oid_full": "1.3.6.1.4.1.9694.1.4.1.18",
            "value": "12345",
            "value_type": "Integer32"
        },
        {
            "oid": "PEAKFLOW-SP-MIB::spRouter",
            "oid_full": "1.3.6.1.4.1.9694.1.4.1.2",
            "value": "MyTestRouter",
            "value_type": "OctetString"
        }
    ]
}

まとめ

snmptrap-kafka-forwarderは、伝統的な SNMP 監視と最新のデータ分析基盤を繋ぐ、強力な架け橋となるツールです。セットアップも簡単で、柔軟な設定が可能なため、多くの環境で活用できるでしょう。ネットワーク監視のデータをさらに活用したいと考えている方は、ぜひ試してみてはいかがでしょうか。

-スクリプトのお勉強
-

執筆者:

関連記事

SPAMチェック for OCN の アップデート(v0.7.0)

以前、ここで書いたように、SPAMチェックのThunderbirdプラグインを作りました。 そして、Thunderbirdがアップデートしたので、Pluginもアップデートする必要があります。 正直放 …

CentOS7をRocky Linux 9に移行する

このVMのOSをCentOS7にした関係上、そろそろupdateする必要があります。そもそもCentOS7を選択した理由は、仕事で使用するからでした。 で、仕事ではRocky Linux 9なので、こ …

Pythonのmock.patchを使ってみる

単体テストによく使われるMockライブラリ Pythonで単体テストを行う際、実際のライブラリを使用してしまうと、実際の環境を用意しなければいけません。 例えば、データベースのテストをする際に、データ …

Python Falconによる REST APIの作成

1.はじめに 最近、仕事では、あまり技術的なことをしてませんで。。今回は、pythonのFalconというWebアプリケーションフレームワークを使用し、REST APIを作成します。 前回は、Djan …

PyWebIOでform 入力+ REST API呼び出しを作ってみる

仕事柄、簡単なWebアプリを作りたいと思うことはよくあり、その場合はその場で直せるスクリプトで書きたいとよく思うものです。 すごーく簡単なフォームを非常に簡単に使いたいので、まずは簡単に作れるフレーム …

    google オプトアウト Click here to opt-out.