SNMPv2cからSNMPv3へ|USM・VACMの仕組みとCisco設定、移行と切り分け

ルータやスイッチの監視で長く使われてきた SNMPv2c は、コミュニティ名を平文のまま送るため、盗聴や送信元の偽装に弱いという問題を抱えています。SNMPv3 はこの弱点を、ユーザー単位の認証・暗号化(USM)と、MIB 単位のアクセス制御(VACM)で解消した規格です。

この記事では、SNMPv2c の仕組みと限界を確認したうえで、SNMPv3 の USM が Engine ID と機器の時刻を使って、盗み見・なりすまし・使い回しをどう防ぐのかを、図で順に整理します。後半では Cisco IOS/IOS-XE の設定例と、つながらないときの切り分け方、v2c からの移行手順をまとめます。

この記事でわかること
  1. SNMPv2c のコミュニティ名の役割と、セキュリティ上の限界
  2. SNMPv3 の USM(認証・暗号化)と VACM(アクセス制御)の仕組み
  3. Cisco IOS/IOS-XE での SNMPv3 の設定と確認の手順
  4. usmStats カウンタを使った切り分けと、v2c からの段階的な移行

SNMPの基本動作

SNMP は、監視サーバ側の SNMP マネージャー(NMS)と、監視される機器側の SNMP エージェントの間でメッセージをやり取りするプロトコルです。マネージャーから機器に問い合わせる「ポーリング」と、機器からマネージャーへ知らせる「通知」の2つの流れがあります。

GET / GETNEXT / GETBULK / SET(UDP 161) Response TRAP / INFORM(UDP 162) Response(INFORM のときだけ返す) SNMPマネージャー (NMS) SNMPエージェント (ルータ・スイッチ等)
図1 SNMP のポーリングと通知
操作内容
GET / GETNEXT指定した OID の値(CPU 使用率、インターフェースの状態など)を取得します。GETNEXT は次の OID を順にたどるときに使います。
GETBULK複数の値をまとめて取得します。SNMPv2c で追加され、テーブルを読むときの往復回数を減らせます。
SET機器の設定値や状態を書き換えます。
TRAP障害や状態変化を機器からマネージャーへ通知します。受け取ったかどうかの応答はありません。
INFORM応答(Response)付きの通知です。SNMPv2c で追加され、応答がなければ機器が再送します。

SNMPv2cのコミュニティ名と限界

SNMPv1 と SNMPv2c では、「コミュニティ名」という文字列を共通のパスワードとして使います。読み取り専用の RO コミュニティと、SET も許可する RW コミュニティを使い分けるのが一般的です。機器と監視サーバに同じ文字列を登録するだけで監視を始められる手軽さが、長く使われてきた理由です。

SNMPv2c は、64 ビットカウンタ(Counter64)、GETBULK、INFORM を追加したバージョンです。高速なインターフェースでは 32 ビットのカウンタがすぐに一周してしまうため、トラフィックを正しく数えるには 64 ビットカウンタが欠かせません(RFC 2863 では、650Mbps を超えるインターフェースに 64 ビットカウンタを求めています)。一方で、認証の仕組みは SNMPv1 と同じコミュニティ名のままです。

限界内容
コミュニティ名が平文コミュニティ名はパケットにそのまま入って流れます。経路上でキャプチャされると、そのまま読み取られます。
通信の暗号化がない取得した値(構成情報、インターフェース名、ルーティング情報など)も平文で流れます。
送信元を確かめられないSNMP は UDP で動くため、送信元 IP アドレスの偽装が容易です。RW コミュニティが漏れると、なりすました SET で設定を書き換えられるおそれがあります。

SNMPv3で何が変わったのか

SNMPv3 は RFC 3411〜3418 で定められた規格です。SNMPv2c の PDU(GET や GETBULK などの操作)はそのまま引き継ぎ、メッセージの包み方とセキュリティの仕組みを作り直しています。中心になるのは次の2つの仕組みです。

仕組み役割
USM(User-based Security Model)
RFC 3414
ユーザー名を単位に、メッセージの認証(改ざん検知・送信元の確認)、暗号化、再送攻撃の防止を行います。
VACM(View-based Access Control Model)
RFC 3415
どのユーザー(グループ)に、どの MIB の範囲を、読み取り・書き込み・通知のどれで使わせるかを決めます。

3つのセキュリティレベル

SNMPv3 では、ユーザーごとに要求するセキュリティの強さを3段階から選びます。暗号化だけを使うことはできず、暗号化するときは必ず認証も行います。

レベル認証暗号化内容
noAuthNoPrivなしなしユーザー名を照合するだけです。強度は実質的に SNMPv2c と変わりません。
authNoPrivありなしメッセージに認証コードを付けて、改ざんとなりすましを防ぎます。中身は平文のままです。
authPrivありあり認証に加えて、メッセージの中身(PDU)を暗号化します。盗聴も防げるため、通常はこのレベルを使います。

認証と暗号化に使えるアルゴリズムは、標準とベンダー実装で次のように分かれます。

種類アルゴリズム定義
認証HMAC-MD5-96、HMAC-SHA-96RFC 3414(USM の基本仕様)
認証HMAC-SHA-2(SHA-224/256/384/512)RFC 7860。機器と NMS の両方が対応している場合に使えます。
暗号化CBC-DESRFC 3414
暗号化AES-128(CFB)RFC 3826
暗号化AES-192、AES-256RFC にはないベンダー拡張です。Cisco などが対応していますが、NMS 側の対応を確認してから使います。
選び方

MD5 と DES はいまでは安全性が低いため、新しく設定するときは選びません。相互接続性を重視するなら認証に SHA、暗号化に AES-128 を使い、機器と NMS の両方が対応していれば SHA-2 を検討します。

USMの仕組み:盗み見・なりすまし・使い回しを防ぐ

SNMPv2c ではコミュニティ名という「合言葉」をそのままネットワークに流していました。SNMPv3 の USM は、パスワードそのものは送りません。パスワードから作った鍵を使って、メッセージに鍵をかけたり、本物である証明を付けたりします。USM がしていることは、次の3つに分けられます。

防ぎたいことSNMPv2cSNMPv3(USM)の対策
盗み見(中身を見られる)平文なので防げないpriv 鍵で PDU を暗号化する
なりすまし・書き換えコミュニティ名を知っていれば誰でも送れるauth 鍵で認証コード(HMAC)を付け、受信側で照合する
使い回し(古いパケットの再送)防げないメッセージの時刻を機器の時刻と比べ、古いものを捨てる

この章では、まず暗号化と認証コードの流れを見て、そのあと両者が土台にしている「Engine ID」と「機器の時刻」を説明します。続いて、その2つを使って鍵を作るしくみと、古いメッセージを見分けるしくみを説明し、最後に通知の場合の違いと、これらの情報がメッセージのどこに入るのかを確認します。

パスワードは送らず、暗号化と認証コードを使う

SNMPv3 のユーザーには、認証用(auth)と暗号化用(priv)の2つのパスワードを設定します。NMS と機器の両方に同じパスワードを設定しておくので、双方が同じ鍵を作れます。鍵そのものはネットワークに流れません。

送信側(NMS) 受信側(エージェント) 平文の PDU 例:GET ifHCInOctets 暗号化した PDU 第三者には読めない 暗号化 PDU HMAC 暗号化 PDU HMAC HMAC が一致 本物・改ざんなしと確認 平文の PDU 中身を処理して応答 ① 暗号化 priv 鍵 ② HMAC auth 鍵 ③ 照合 auth 鍵 ④ 復号 priv 鍵 途中で盗み見・書き換えをされても 中身は読めず、書き換えると HMAC が合わない
図2 暗号化(priv)と認証コード(auth)の流れ

送信側は、まず priv 鍵で PDU を暗号化し(①)、次に auth 鍵を使ってメッセージ全体から認証コード(HMAC)を計算し、メッセージに付けます(②)。HMAC は、メッセージの中身と鍵の両方から決まる短い値で、中身が少しでも変わるとまったく違う値になります。

受信側は、届いたメッセージから自分の auth 鍵で HMAC を計算し直し、付いてきた HMAC と比べます(③)。一致すれば「同じ鍵を持つ相手から、書き換えられずに届いた」とわかるので、priv 鍵で復号して中身を処理します(④)。途中でパケットを見られても中身は読めません。書き換えられた場合は HMAC が合わないので、受信側が捨てます。

最初に、相手の Engine ID と時刻を教えてもらう

この暗号化と認証コードのしくみは、通信相手の2つの情報を土台にしています。1つは相手の識別番号である Engine ID、もう1つは相手の時刻です。

情報中身使い道
Engine IDSNMP の機能を持つ機器や NMS に1つずつ付いている識別番号(snmpEngineID)機器ごとの鍵を作る
機器の時刻年月日の時計ではなく、起動回数(snmpEngineBoots)と起動してからの秒数(snmpEngineTime)の組。機器の中にあるストップウォッチのようなもの古いメッセージを見分ける

GET などのポーリングでは、NMS は初めて機器と通信するときに、この2つを機器に問い合わせ、教えてもらった値を覚えてから本番の要求を送ります。この手順をディスカバリと呼び、NMS が自動で行います。

NMS エージェント ① 「Engine ID を教えて」(Engine ID・ユーザー名は空) ② 「Engine ID はこれです」(Report) ③ 「今の時刻を教えて」(認証付き・時刻は 0) ④ 「起動 5 回目・1000 秒です」(Report) ⑤ GET(authPriv) ⑥ Response(値を返す) Engine ID を聞く 時刻を 聞く 本番の 通信
図3 ディスカバリ:Engine ID と時刻を聞いてから本番の要求を送る

②と④の Report は、機器が要求に対して状況を知らせる応答で、この中に Engine ID や時刻が入っています。NMS は、ここで教えてもらった Engine ID と時刻(図3の例では 5 回目・1000 秒)を、機器ごとに覚えておきます。このあと説明する「機器ごとの鍵」と「時刻の窓」は、どちらもこの2つの値を使います。

ここではポーリングの場合で説明しています。トラップのように機器から一方的に送る通知では、ディスカバリは行いません。通知の場合の扱いは、この章の最後でまとめます。

同じパスワードでも、機器ごとに鍵が変わる

ディスカバリで教えてもらった Engine ID は、まず鍵を作るのに使います。図2では「同じパスワードから同じ鍵を作る」と説明しましたが、正確には、USM はパスワードと相手機器の Engine ID を混ぜてハッシュ関数にかけ、その機器専用の鍵を作ります。これを「鍵の局所化」と呼びます。

パスワード どの機器にも同じもの パスワード + Engine ID A ハッシュ関数で混ぜる パスワード + Engine ID B ハッシュ関数で混ぜる 鍵 A 機器A 専用 鍵 B 機器B 専用 機器A 機器B 鍵 A と鍵 B は まったく別の値
図4 鍵の局所化:パスワードと Engine ID から機器ごとの鍵を作る

そのため、全部の機器に同じパスワードを設定していても、実際に使われる鍵は機器ごとに違います。仮に機器 A の鍵が漏れても、その鍵で機器 B の通信を読んだり、機器 B になりすましたりはできません。

注意

鍵は Engine ID から作られるので、機器の交換や設定変更で Engine ID が変わると、それまでの鍵は使えなくなります。NMS 側に古い Engine ID が残っていると認証に失敗するため、機器を交換したときは NMS の登録も見直します。

古いパケットの使い回しを防ぐ(時刻の窓)

ディスカバリで教えてもらったもう1つの値、機器の時刻は、古いパケットの使い回しを防ぐのに使います。

暗号化と HMAC があっても、攻撃者が正しいパケットをキャプチャしておき、あとでそのまま送り直す「再送(リプレイ)攻撃」は防げません。中身に手を加えていないので、HMAC は一致してしまうからです。そこで SNMPv3 のメッセージには時刻(起動回数と秒数)を入れておき、受信側は古いメッセージを捨てます。

勘違いしやすいポイント

メッセージに入る時刻は「送った側の時刻」ではありません。GET や SET のポーリングでは、NMS が送るメッセージにも機器(エージェント)の時刻が入ります。NMS の起動時間はどこにも使われず、照合は機器の時計を基準に行います。

NMS は機器の時刻をどうやって予想するのか

NMS は機器の時計を直接見られないので、ディスカバリで教えてもらった値(5 回目・1000 秒)を出発点にします。そのあとは、覚えた値に自分の手元で経過した秒数を足して、「機器の時計は今この値のはず」と予想します。1 秒の長さはどの機器でも同じなので、年月日を知らなくても、経過時間を足すだけで機器の時計を追いかけられます。

① ディスカバリ ② 60 秒後に GET ③ 応答で補正 NMS 機器 Report 5 回目・1000 秒 GET に書く値 5 回目・1060 秒 Response 5 回目・1060 秒 機器の時刻を覚える 5 回目・1000 秒 (受け取った時点の値) 手元で 60 秒たった 1000+60=1060 と予想して書く 覚えた値を更新 5 回目・1060 秒 自分の時計 5 回目・1000 秒 自分の時計は 5 回目・1060 秒 差 0 秒 → 受理 (照合するのはここ) 今の時刻を入れて返す 5 回目・1060 秒
図5 メッセージに入るのは機器の時刻(NMS は覚えた値に経過秒数を足して予想する)
タイミング何が起きるか
① ディスカバリ機器が自分の時刻(5 回目・1000 秒)を NMS に知らせます(図3の④)。NMS はその値を、受け取った時点のものとして覚えます。
② 60 秒後に GETNMS は「1000+60=1060 秒のはず」と予想し、Boots=5・Time=1060 をメッセージに書いて送ります。機器はその値を自分の時計(5 回目・1060 秒)と比べ、差が 0 秒なので受け付けます。
③ 応答で補正機器は Response に今の時刻を入れて返します。NMS は覚えた値をこの値で更新するので、予想が少しずつずれていっても、通信のたびに元に戻ります。

機器は何と何を比べて、通すか捨てるかを決めるのか

機器はメッセージを受け取ると、HMAC で本物かどうかを確かめたあと、メッセージに書かれた Boots・Time と、自分の今の Boots・Time を比べます。判定のルールは次のとおりです。

比べた結果判定
Boots(起動回数)が自分と違う破棄します。再起動前に作られたメッセージだからです。
Boots は同じで、Time の差が 150 秒を超える破棄します。古いメッセージ(または予想が大きく外れたメッセージ)だからです。
Boots が同じで、Time の差が 150 秒以内受け付けます。

攻撃者がキャプチャしたパケットを 5 分後に送り直した場合を、図6で見てみます。

NMS の正しい要求(すぐ届く) Time=1060 攻撃者が 5 分後に同じパケットを再送 Time=1060 1060 秒 1360 秒(今) 1360 秒の時点で受け付ける範囲(1210〜1510 秒) 機器の時刻 差 0 秒 → 受理 差 300 秒 → 破棄
図6 再送されたメッセージは、機器の時計との差で見分ける

攻撃者のパケットの中身は「Time=1060」のままですが、機器の時計はもう 1360 秒まで進んでいます。差が 300 秒あるので、機器はこのメッセージを捨てます。攻撃者が Time を 1360 に書き換えようとしても、書き換えた時点で HMAC が合わなくなるため、やはり捨てられます。

よくあるケースを並べると、次のようになります(値は「起動回数・秒数」で表記)。

ケース送られた値機器の値判定
正しい要求5・10605・1060差 0 秒なので受理
NMS の予想が少しずれた5・11005・1060差 40 秒(150 秒以内)なので受理
攻撃者が 5 分後に再送5・10605・1360差 300 秒なので破棄
機器の再起動後に再送5・10606・30起動回数が違うので破棄
機器の再起動を NMS がまだ知らない5・14006・30起動回数が違うので破棄。Report で新しい値(6・30)が返るので、NMS は覚え直して次から受理される
NTP との関係

この時刻は起動してからの秒数なので、機器の時計(NTP で合わせる時刻)がずれていても、それだけで SNMPv3 が失敗することはありません。ただし、ログやトラップの時刻を突き合わせるために、NTP での時刻合わせはしておきます。

通知(TRAP・INFORM)では基準になる側が変わる

ここまでは、NMS が機器に問い合わせるポーリングの場合で説明しました。通知の場合は、どちらの Engine ID と時計を基準にするかが変わります。決まりは「応答を返す側が基準になる。TRAP のように応答がないものは、送る側が基準になる」というものです。

やり取り基準鍵に使う Engine IDメッセージに入る時刻と照合のしかた
GET・SET機器機器の Engine IDNMS が予想した機器の時刻を、機器が自分の時計と比べます(±150 秒を超えたら破棄)。
TRAP機器機器の Engine ID機器が今の時刻を入れて送り、NMS が覚えている機器の時刻と比べます(150 秒を超えて古ければ破棄、新しければ覚えた値を更新)。
INFORMNMSNMS の Engine ID機器が予想した NMS の時刻を、NMS が自分の時計と比べます(±150 秒を超えたら破棄)。

TRAP は機器から一方的に送るため、ディスカバリは行いません。NMS 側には、あらかじめ機器の Engine ID とユーザーを登録しておきます。INFORM では逆に、機器が NMS の Engine ID を知っている必要があります。どちらも、あとの Cisco の設定で出てきます。

ここまでの情報は、メッセージのどこに入るのか

最後に、ここまで出てきた Engine ID、時刻、ユーザー名、HMAC、暗号化が、SNMPv3 のメッセージのどこに入っているかを確認します。

認証(HMAC)の対象:メッセージ全体 msgVersion 値は 3 msgGlobalData 共通ヘッダ msgSecurityParameters USM のパラメータ scopedPDU authPriv では暗号化 msgID msgMaxSize msgFlags msgSecurityModel msgAuthoritativeEngineID msgAuthoritativeEngineBoots msgAuthoritativeEngineTime msgUserName msgAuthenticationParameters msgPrivacyParameters contextEngineID contextName PDU(GET、Response など)
図7 SNMPv3 メッセージの構造と、USM の情報が入る場所

USM が使う情報は、すべて msgSecurityParameters の欄に入ります。msgAuthoritativeEngineID、msgAuthoritativeEngineBoots、msgAuthoritativeEngineTime は、基準になる側の Engine ID と時刻です。名前に付いている Authoritative は、前の項で説明した「基準になる側」という意味です。msgAuthenticationParameters には HMAC の値が、msgPrivacyParameters には暗号化に使うパラメータが入ります。

共通ヘッダの msgFlags には、そのメッセージが認証付きか、暗号化付きかを示すビットが入ります。msgSecurityModel は USM を使っていることを示し、受信側はこの値を見てセキュリティパラメータの読み方を決めます。

VACMの仕組み:見せる範囲を決める

USM で「正しい相手からの、書き換えられていないメッセージか」を確かめたあと、VACM で「その相手にどこまで見せるか」を決めます。会社にたとえると、社員(ユーザー)を部署(グループ)に入れ、部署ごとに入れる部屋(ビュー)を決めるイメージです。

誰が(ユーザー) secuser1 どのレベルで(グループ) ADMIN-GROUP authPriv を必須にする どこまで見せるか(ビュー) MONITOR-VIEW mib-2 1.3.6.1.2.1 SNMP で読める情報 (MIB)の木 system interfaces ifMIB ip tcp .1 .2 .4 .6 .31 MONITOR-VIEW では 見える 見える 見えない 見えない 見える
図8 ユーザー・グループ・ビューの関係と、ビューで見せる MIB の枝(一部の枝のみ表示)

SNMP で読める情報(MIB)は、図8の下のような木の形で整理されていて、枝ごとに番号(OID)が付いています。ビューでは、この木のどの枝を見せるかを指定します。図の例では、system(機器名や稼働時間など)、interfaces(インターフェースの状態など)、ifMIB だけを見せ、ip や tcp などのほかの枝は見せません。

トラフィック量のグラフに使う 64 ビットカウンタ(ifHCInOctets など)は、interfaces ではなく ifMIB の枝にあります。トラフィックを監視する場合は、ifMIB もビューに入れておきます。

グループには、読み取り用(read)、書き込み用(write)、通知用(notify)のビューを割り当てられます。監視だけが目的なら read ビューだけを割り当て、write ビューは付けません。こうすると、そのユーザーでは設定を書き換える SET ができなくなります。

Cisco IOS/IOS-XEでの設定

Cisco では、ここまでの仕組みを4つのコマンドで設定します。どのコマンドも、前のコマンドで付けた名前を指定するので、ビュー → グループ → ユーザー → 通知先の順に作ります。

STEP 1 ビュー STEP 2 グループ STEP 3 ユーザー STEP 4 通知先 snmp-server view MONITOR-VIEW system included snmp-server group ADMIN-GROUP v3 priv read MONITOR-VIEW snmp-server user secuser1 ADMIN-GROUP v3 auth sha … priv aes 128 … snmp-server host 192.168.1.100 version 3 priv secuser1 ▼ ビュー名 MONITOR-VIEW を、次のグループで指定 ▼ グループ名 ADMIN-GROUP を、次のユーザーで指定 ▼ ユーザー名 secuser1 を、次の通知先で指定
図9 4つのコマンドのつながり(太字が名前の受け渡し)

ここでは、NMS(192.168.1.100)から authPriv でポーリングし、トラップも SNMPv3 で送る例で設定します。ユーザー名やパスワードは例なので、実際は推測されにくい値に置き換えてください。

ビューを作る(見せる範囲)

見せる枝を included で1行ずつ追加します。同じビュー名で何行も書くと、そのビューに枝が追加されていきます。ifMIB は OID で指定しています。

設定例

Device(config)# snmp-server view MONITOR-VIEW system included
Device(config)# snmp-server view MONITOR-VIEW interfaces included
! 1.3.6.1.2.1.31 は ifMIB(64ビットカウンタの ifXTable を含む)
Device(config)# snmp-server view MONITOR-VIEW 1.3.6.1.2.1.31 included

グループを作る(レベルとビュー)

v3 priv で、このグループのユーザーには認証と暗号化の両方(authPriv)を求めます。read MONITOR-VIEW で、STEP 1 のビューを読み取り用に割り当てます。write ビューは指定しないので、SET はできません。

Device(config)# snmp-server group ADMIN-GROUP v3 priv read MONITOR-VIEW

ユーザーを作る(パスワード)

ユーザー secuser1 をグループ ADMIN-GROUP に入れ、認証に SHA、暗号化に AES-128 を指定します。auth sha の後ろが認証用、priv aes 128 の後ろが暗号化用のパスワードです。

Device(config)# snmp-server user secuser1 ADMIN-GROUP v3 auth sha AuthPass123! priv aes 128 PrivPass456!
補足
  • Cisco IOS では、パスワードは Engine ID で局所化した鍵の形で保持され、snmp-server user の行は show running-config に表示されません。登録内容は show snmp user で確認します。
  • 機器の Engine ID は、既定では MAC アドレスをもとに作られます。snmp-server engineID local で Engine ID を変えると鍵が合わなくなるため、ユーザーを登録し直します。

トラップの送信先を設定する

送るトラップの種類を snmp-server enable traps で選び、送信先を snmp-server host で指定します。version 3 priv secuser1 は、「secuser1 の鍵で authPriv にして送る」という意味です。TRAP ではディスカバリを行わないので、NMS 側にも同じユーザーとパスワードを、機器の Engine ID とあわせて登録しておきます。

Device(config)# snmp-server enable traps snmp linkdown linkup coldstart warmstart
Device(config)# snmp-server host 192.168.1.100 version 3 priv secuser1
INFORM を使う場合

INFORM では NMS が基準になるので、鍵には NMS 側の Engine ID が使われます。Cisco では、先に NMS の Engine ID を snmp-server engineID remote で登録し、そのあとで remote を付けてユーザーを作ります。順番を逆にすると、ユーザー作成のコマンドが失敗します。

! 800000090300000102030405 は例。実際は NMS の Engine ID を指定する
Device(config)# snmp-server engineID remote 192.168.1.100 800000090300000102030405
Device(config)# snmp-server user secuser1 ADMIN-GROUP remote 192.168.1.100 v3 auth sha AuthPass123! priv aes 128 PrivPass456!
Device(config)# snmp-server host 192.168.1.100 informs version 3 priv secuser1

設定を確認する

機器側では次のコマンドで設定内容を確認します。パスワードはどのコマンドでも表示されません。

コマンド確認すること
show snmp groupグループ名、セキュリティモデル(v3 priv)、割り当てたビュー
show snmp user secuser1ユーザー名、Engine ID、認証・暗号化の方式、所属グループ
show snmp engineID機器の Engine ID(NMS に登録する値)と、登録したリモートの Engine ID

NMS 側からは、Net-SNMP の snmpwalk で実際に値を読めるかを確かめます。system が読めて、ビューに入れていない枝(たとえば ip)が読めなければ、ビューも期待どおりに効いています。

NMS(Net-SNMP)

$ snmpwalk -v3 -l authPriv -u secuser1 \
    -a SHA -A 'AuthPass123!' -x AES -X 'PrivPass456!' \
    <機器のIPアドレス> system

つながらないときの切り分け

SNMPv3 の設定ミスは、どれも「応答が返ってこない」「認証エラーになる」という似た症状に見えます。原因を絞るには、受信側がメッセージをどの順番でチェックしているかを知っておくと便利です。

① 宛先の Engine ID は合っているか ② そのユーザーは登録されているか ③ ユーザーはそのレベルに対応しているか ④ HMAC(認証コード)は一致するか ⑤ 時刻の窓(±150 秒)に入っているか ⑥ 復号できるか(authPriv のとき) すべて OK → 要求を処理して応答する NGNGNG NGNGNG Engine ID の誤り・未取得 ユーザー名の誤り・未登録 auth/priv の有無の食い違い auth パスワード・方式の誤り 古いメッセージ・時刻情報のずれ priv パスワード・方式の誤り usmStatsUnknownEngineIDs(.4) usmStatsUnknownUserNames(.3) usmStatsUnsupportedSecLevels(.1) usmStatsWrongDigests(.5) usmStatsNotInTimeWindows(.2) usmStatsDecryptionErrors(.6)
図10 受信側のチェック順序と、引っかかったときに増えるカウンタ(RFC 3414 3.2 節)

受信側は①から順にチェックし、引っかかった段階のカウンタを1つ増やして、そのメッセージを捨てます。多くの場合、送信元にはどのカウンタが増えたかを知らせる Report が返ります。NMS 側でパケットをキャプチャし、Report に入っている OID(1.3.6.1.6.3.15.1.1.N)の最後の数字を見ると、図10のどこで止まったかがわかります。

段階よくある原因確認すること
① Engine ID初回のディスカバリでは正常。続く場合は、機器を交換したのに NMS が古い Engine ID を覚えている機器の show snmp engineID と NMS の登録値を比べます。
② ユーザーユーザー名のつづりや大文字・小文字の違いshow snmp user にユーザーがあるかを確認します。
③ レベルNMS は authPriv で送っているのに、ユーザーに暗号化を設定していない(またはその逆)両側のセキュリティレベルを合わせます。
④ HMACauth パスワードの誤り、MD5 と SHA の取り違え両側の auth の設定を入れ直します。
⑤ 時刻の窓初回のディスカバリでは正常。続く場合は、同じ Engine ID を手動設定した機器が複数あるEngine ID が機器ごとに違うかを確認します。
⑥ 復号priv パスワードの誤り、DES と AES、AES の鍵長(128/192/256)の違い両側の priv の設定を入れ直します。
ディスカバリのエラーは正常

図3のディスカバリで②と④の応答が返ってきたのは、NMS がわざと図10の①(Engine ID)と⑤(時刻の窓)に引っかかるメッセージを送り、その Report から Engine ID と時刻を受け取っていたためです。そのため、初回の通信で usmStatsUnknownEngineIDs や usmStatsNotInTimeWindows が増えるのは正常です。

Engine ID の重複に注意

NMS は、相手機器の時刻を Engine ID ごとに覚えています。設定の流用などで同じ Engine ID の機器が2台あると、NMS の中で2台の時刻が混ざり、⑤のエラーが不規則に出るようになります。Engine ID を手動で設定するときは、機器ごとに必ず別の値にします。

SNMPv2cからの移行の進め方

機器には v2c と v3 の設定を同時に入れておけます。そのため、いきなり v2c を止めるのではなく、v3 を追加してから監視、通知の順に切り替え、最後に v2c を消すと、監視を止めずに移行できます(併用の考え方は RFC 3584 で定められています)。

1. v3 を追加 2. 監視を切替 3. 通知を切替 4. v2c を削除 機器の v2c 設定 機器の v3 設定 ポーリング トラップ コミュニティ名を残す(送信元は NMS に限定) 削除 ビュー・グループ・ユーザー v2c v3(authPriv) v2c v3(authPriv)
図11 移行の流れ(グレーが v2c、紺が v3)
フェーズやること確認すること
1. v3 を追加機器にビュー、グループ、ユーザーを追加します。コミュニティ名は残し、この期間はアクセスリストで送信元を NMS に絞ります。show snmp group、show snmp user
2. 監視を切替NMS の監視設定を、機器ごとに SNMPv3(authPriv)へ切り替えます。グラフや監視値が途切れていないか
3. 通知を切替トラップの送信先設定を SNMPv3 に変えます。リンクダウンなどを起こし、NMS で受信できるか
4. v2c を削除snmp-server community と v2c のトラップ設定を削除します。コミュニティ名で問い合わせても応答がないか

まとめ

SNMPv3 では、USM が「暗号化」「認証コード(HMAC)」「時刻の窓」の3つで、盗み見、なりすまし、使い回しを防ぎます。VACM は、ユーザーごとに見せる MIB の範囲を決めます。鍵は Engine ID とパスワードから作られるので、つながらないときは、両側の Engine ID、パスワード、セキュリティレベルを見比べるのが近道です。

項目SNMPv2cSNMPv3
盗み見平文のまま流れるauthPriv で PDU を暗号化(AES など)
なりすまし・改ざんコミュニティ名だけで判断認証コード(HMAC)で本物か確認
使い回し防げない機器の時刻と比べ、±150 秒を超えたら破棄
見せる範囲RO/RW が中心VACM のビューで枝ごとに指定
鍵全機器で同じ文字列Engine ID で機器ごとに異なる鍵
Cisco の設定snmp-server communitysnmp-server view/group/user/host

コメント