SNMP - Simple Network Management Protocol

Version:1.0 of 2011/04/06
Author:SUZUKI Masashi / masasuzu
Mail:m15.suzuki.masashi@gmail.com

Agenda

  1. 監視について
  2. SNMPの概要
  3. Net-SNMP
  4. プログラムからSNMPにアクセスする

監視について

監視には主に死活監視、障碍監視、性能監視、セキュリティ監視があります。

死活監視は、一定間隔でシステムに対してpingやTCPコネクションを張りTimeoutが無いことでサービスが死んでいないかを確認します。 障碍監視は、ログなどを確認しハードウェアエラーソフトウェアエラーがないかを監視します。 性能監視は、システムの性能(リソース)を継続的に監視し、グラフなどで傾向を可視化し、閾値を越えていないことを監視します。

  • 死活監視
    • ping
    • traceroute
    • ssh
    • ポート監視
    • wget
    • Nagios
    • monit
  • 障碍監視
    • snmp trap
    • syslog
    • ログ監視
  • 性能監視
    • MRTG
    • Cacti
    • munin
    • CloudForcast
  • セキュリティ監視
    • IDS
    • Firewallログ監視

SNMPの概要

ネットワーク管理と各種モニタリングのための シンプルな プロトコル。

対象はルータやスイッチに限らず、Unixシステム、Windows、プリンタ、電源、WEBサーバ、DBサーバを監視できます。

SNMPの機能

SNMP主な機能には主に3つの機能があります。ここでは、管理対象機器を監視するノードを 管理機 管理対象機器が持つ情報を 管理情報 とします。

  1. 管理対象機器が管理機に情報の 通知 する
  2. 管理機が管理対象機器に管理情報を 要求 する
  3. 管理機が管理対象機器に 設定 する

っね、シンプルでしょ。

SNMP管理フレームワーク

SNMP管理フレームワークは4つの構成要素と4つの定義されています。

  • 4つの構成要素
    1. 管理対象機器
    2. 管理機
    3. 管理情報
    4. SNMPプロトコル
  • 4つの定義
    1. プロトコル定義
    2. データ定義言語
    3. 管理情報定義
    4. セキュリティと管理の定義
../images/snmp_overview.png

っね、シンプルでしょ。。

SNMP管理フレームワークのバージョン

4つの定義をそれぞれSNMP管理フレームワークのバージョンにマッピングすると以下の通りになります。下記の表は簡略化したものとなります。

  v1 v2 v3
プロトコル SNMPv1 SNMPv2c SNMPv3
データ定義言語 SMIv1 SMIv2 SMIv2
管理情報 MIB-I MIB-II MIB-II
セキュリティと管理の定義 Community Community USM/VACM
SMI
Structre of Management Information
MIB
Mabagement Informationn Base
USM
User-based Security Model
VACM
View-based Access Control Model

SMIとMIB

SMI(Struscture of Manangement Information)

SMIとは、ノードの管理オブジェクト(管理情報)の構造を定義するための定義です。

ANS.1と呼ばれる記述法を用います。

  • 構造: SMI
  • 記述法: ASN.1

SMIの構造は 名前と型管理オブジェクト から構成されます。名前はオブジェクトIDと呼ばれる一意の識別子で表現されます。SMIの型には以下のようなものがあります。

   
プリミティブ型 (単一の値) 整数(INTEGER)
文字列(STRING)
カウンター(Counter)
オブジェクトID(OID)
コンストラクタ型 (複数の値) シーケンス(SEQUENCE)
シーケンスオブ(SEQUENCEOF)
アプリケーションワイド型 (特別な値) 32ビット整数(INTEGER32)
IPアドレス(IPAddress)
時間(TimeTicks)

管理オブジェクトの定義はマクロと呼ばれ、アクセス制限などを定義します。

MIB(Management Informantion Base)

MIBとは、管理オブジェクトをまとめて1つのデータベースとしたものです。MIBはオブジェクトID(OID)を使用した木構造で、管理オブジェクトを管理しています。これをMIBツリーといいます。

SNMPではiso(1).org(3).dod(6).internnet(1)から下のOIDを使用します。これは、OIDが、SNMP以外でも使用されるためです。

SNMPのバージョン

SNMPv1 と v2c

SNMPで管理 する側 のSNMPソフトウェアを マネージャ 、管理 される側 のSNMPソフトウェアを エージェント といいます。

SNMPパケットには UDP を使用します。通知には 162番 、要求と設定には 161番 を使用します。

SNMPでは同じコミュニティが設定してあるエージェントとマネージャ同士のみやりとりができます。また複数の同じノードで複数のコミュニティを設定することもできます。SNMPv1,v2cでは平文でコミュニティ名を送信するため、セキュリティに問題があります。

* 通知
+-----------+------------------------------+--------------+
|           | UDP Header                   |              |
| IP Header +-------------+----------------+ SNMP Message |
|           | Source-port | Dest-port(162) |              |
+-----------+------------------------------+--------------+

* 要求、設定
+-----------+------------------------------+--------------+
|           | UDP Header                   |              |
| IP Header +-------------+----------------+ SNMP Message |
|           | Source-port | Dest-port(161) |              |
+-----------+------------------------------+--------------+

SNMPメッセージ

SNMPメッセージの構造は、SNMPバージョン、コミュニティ名、PDU(後述)から構成されます。

SNMPメッセージの構造
+---------------+-----------+-------+
| SNMP Version  | Community | PDU   |
+---------------+-----------+-------+
Version:SNMPのバージョン。v1(0)、v2c(1)。
Community:コミュニティ名
PDU:SNMPデータ

SNMPv1,v2cでのPDUの種類は以下の通りです。

PDU-type PDU名 Version 概要
0 GetRequest v1,v2c マネージャからの情報取得要求 指定したインスタンスを取得
1 GetNextRequest v1,v2c マネージャからの情報取得要求 指定した次のインスタンスを取得
2 GetResponse v1 マネージャからの要求に対する応答
3 SetRequiest v1,v2c マネージャからの設定要求
4(v1), 7(v2) Trap v1,v2c エージェントからの通知
2 Response v2c マネージャからの要求に対する応答 GetResponseの置き換え
5 GetBulkRequest v2c マネージャからの情報取得要求 指定した範囲のインスタンスを取得
6 InformRequest v2c エージェントからの通知 マネージャが応答対応を返す

インスタンスと表記しているのは、NICのように同じオブジェクトIDで複数のインスタンスを持ち得るからです。

要求、設定

GetRequest, GetNextRequest, GetResponse, SetRequestには下記のPDUを使用します。

+------+----------+--------+--------+---------------------------------+
|      |          |        |        | variable-bindings               |
|      |          |        |        +-------------+-------------+-----+
| PDU- | request- | error- | error- | variable-   | variable-   | ... |
| type | id       | status | index  | bindings1   | bindings2   |     |
|      |          |        |        +-----+-------+-----+-------+-----+
|      |          |        |        | oid | value | oid | value | ... |
+------+----------+--------+--------+-----+-------+-----+-------+-----+
PDU-type:PDUタイプ
request-id:マネージャからの要求を区別するための番号。応答の場合、同じIDが入る
error-status:エラー識別子。応答以外の場合0が入る
error-index:エラーが発生したvariable-bindingsの番号
variable-bindings1-n:
 要求、設定する管理オブジェクトのインスタンス。複数格納可能。要求の場合値にnullを入れる

error-statusの値は以下の通りです。

noError(0):エラー無し
tooBig(1):応答メッセージのサイズが大きすぎる
noSuchName(2):指定したOIDが存在しない
badValue(3):異常な管理オブジェクトの値を指定した
readOnly(4):通常は未使用
genErr(5):上記以外のエラー

GetRequest, GetNextRequest

GetRequestは複数の値を取得することができます。GetNextRequestは指定した次のインスタンスを取得します。OIDは抜けなく並んでいるわけではないので、次の値を取得する場合に通常GetNextRequestを使用します。

SNMPv1, v2cのエラー処理の違い

v1ではGetRequest, GetNextRequest, SetRequestに複数のインスタンスを指定したいた場合、そのうち一つでもエラーが発生するとすべてエラーとして応答されます。そのため、大量の情報のやりとりがしずらい使用となっています。

v2cではその点が改善され、インスタンスごとにエラーを通知できるようになっています。また、GetBulkRequest使用することにより範囲指定でインスタンスが取得できるようになり、大量の情報をやりとりしやすくなっています。

Trap

Trap-PDUの内容以下の通りです。

+------+------------+--------+----------+-----------+-----------+---------------------------------+
|      |            |        |          |           |           | variable-bindings               |
|      |            |        |          |           |           +-------------+-------------+-----+
| PDU- | enterprise | agent- | generic- | specific- | timestamp | variable-   | variable-   | ... |
| type |            | addr   | trap     | trap      |           | bindings1   | bindings2   |     |
|      |            |        |          |           |           +-----+-------+-----+-------+-----+
|      |            |        |          |           |           | oid | value | oid | value | ... |
+------+------------+--------+----------+-----------+-----------+-----+-------+-----+-------+-----+
PDU-type:PDUタイプ。(4)
enterprise:エージェントの識別子
agent-addr:エージェントのIPアドレス
generic-trap:トラップの種別
specific-trap:企業トラップの場合使用する。標準のトラップの場合0。
timestamp:エージェントが初期化されてからの時間
variable-bindings1-n:
 通知する管理オブジェクトのインスタンス。複数格納可能

トラップの種類は以下の通りです。

  generic-trapの値 種別
標準トラップ 0 coldStart
1 warmStart
2 linkdown
3 linkup
4 authenticationFailure
5 egpNeighborLoss
企業固有トラップ 6 enterpriseSpecific

っね、シンプルでしょ。。。

SNMPv3

  • 割愛

Net-SNMP

Debianの標準のsnmpクライアント/サーバはnet-snmpです。古くはucd-snmpと呼ばれていました。

インストール

sudo aptitude insntall snmpd # サーバ
sudo aptitude insntall snmp  # クライアント

snmpdの設定

/etc/snmp/snmpd.confの設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#       sec.name  source          community
com2sec local     localhost       private
com2sec mynetwork 192.168.1.0/24  public

#             >-sec.model  sec.name
group MyGroup v1         local
group MyGroup v2c        local
group MyGroup usm        local
group MyGroup v1         mynetwork
group MyGroup v2c        mynetwork
group MyGroup usm        mynetwork

#           incl/excl subtree                          mask
view all    included  .1                               80

#                context sec.model sec.level match  read   write  notif
access MyGroup   ""      any       noauth    exact  all    all    all

syslocation intra
syscontact Root <root@localhost>

/etc/default/snmpdの設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# This file controls the activity of snmpd and snmptrapd

# MIB directories.  /usr/share/snmp/mibs is the default, but
# including it here avoids some strange problems.
export MIBDIRS=/usr/share/snmp/mibs

# snmpd control (yes means start daemon).
SNMPDRUN=yes

# snmpd options (use syslog, close stdin/out/err).
#SNMPDOPTS='-Lsd -Lf /dev/null -u snmp -I -smux -p /var/run/snmpd.pid 127.0.0.1' 外部からsnmpを受け付ける
SNMPDOPTS='-Lsd -Lf /dev/null -u snmp -I -smux -p /var/run/snmpd.pid'

# snmptrapd control (yes means start daemon).  As of net-snmp version
# 5.0, master agentx support must be enabled in snmpd before snmptrapd
# can be run.  See snmpd.conf(5) for how to do this.
#TRAPDRUN=no
TRAPDRUN=yes

# snmptrapd options (use syslog).
TRAPDOPTS='-Lsd -p /var/run/snmptrapd.pid'

# create symlink on Debian legacy location to official RFC path
SNMPDCOMPAT=yes

snmpコマンドで情報を取得してみる

OID直打ちでも、OIDのエイリアスでもOKです。snmpwalkはget-next-requestとget-bulk-requestを駆使して指定OID以下をごそっと取ってくる便利なコマンドです。

-Oコマンドで出力形式を変更することができます。nで数値形式、fで省略なしのOID名が出力されます。

[ LAB ] masasuzu@masalab01% snmpwalk -v 2c -c private localhost .1.3.6.1.2.1.1.1
SNMPv2-MIB::sysDescr.0 = STRING: Linux masalab01 2.6.30-1-686 #1 SMP Sun Jun 14 16:11:32 UTC 2009 i686

[ LAB ] masasuzu@masalab01% snmpwalk -v 2c -c private -Of localhost system.sysDescr
.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0 = STRING: Linux masalab01 2.6.30-1-686 #1 SMP Sun Jun 14 16:11:32 UTC 2009 i686

[ LAB ] masasuzu@masalab01% snmpwalk -v 2c -c private -On localhost system.sysDescr
.1.3.6.1.2.1.1.1.0 = STRING: Linux masalab01 2.6.30-1-686 #1 SMP Sun Jun 14 16:11:32 UTC 2009 i686

snmptrapdの設定

/etc/snmp/snmptrapd.confの設定

# 受け付けるコミュニティの設定
authCommunity log,execute,net public

/etc/default/snmpdの設定

# snmpd起動時にsnmptrapdを起動する
#TRAPDRUN=no
TRAPDRUN=yes

snmptrapを受信してみる

snmptrapコマンドでtrapを送信することができます。snmptrapdが受信したトラップはsyslogに記録されます。

# トラップ送信
[ LAB ] masasuzu@masalab01% snmptrap -v 2c -c public masalab01.intra '' .1.3.6.1.4.1.311.1.1.3.1.2 .1.3.6.1.4.1.311.1.1.3.1.2 s "Test Trap"

# lv /var/log/syslog
Apr  6 09:52:19 masalab01 snmptrapd[19185]: 2011-04-06 09:52:19 172.16.201.118 [UDP: [172.16.201.118]:32972]:#012DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (768473162) 88 days, 22:38:51.62#011SNMPv2-MIB::snmpTrapOID.0 = OID: SNMPv2-SMI::enterprises.311.1.1.3.1.2#011SNMPv2-SMI::enterprises.311.1.1.3.1.2 = STRING: "Test Trap"

PerlからSNMPをいじってみる

Net::SNMPを使うのが一般的です。

App::MadEye::Util::snmp_session()やApp::MadEye::Plugin::Agent::SNMP::* あたりで使用されてます。

でも、CloudforecastではSNMPを使っています。

サンプルコード

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use strict;
use warnings;

use Net::SNMP;

# ipAdEntAddr => '.1.3.6.1.2.1.4.20.1.1'
my $OID = '.1.3.6.1.2.1.4.20.1.1';

my ($session, $error) = Net::SNMP->session(
    -hostname  => 'localhost',
    -community => 'private',
    -port      => 161,
    -timeout   => 10,
    -retries   => 1,
);

if (not defined($session)) {
    die "ERROR: $error.\n";
} else {
    # SEE http://search.cpan.org/~dtown/Net-SNMP-v6.0.1/lib/Net/SNMP.pm#get_table()_-_retrieve_a_table_from_the_remote_agent
    # get-next-requestとget-bulk-requestを駆使して、baseoid以下のオブジェクトをごっそり持ってくる
    my $response = $session->get_table(-baseoid => $OID)
         or die "cannot get snmp response. " . $session->error;
    $session->close();

    use YAML;
    print YAML::Dump($response);
}
#出力はこんな感じ
#---
#.1.3.6.1.2.1.4.20.1.1.127.0.0.1: 127.0.0.1
#.1.3.6.1.2.1.4.20.1.1.172.16.250.144: 172.16.250.144