高機能なルータには、LANケーブルが挿されたり抜かれたりすると、Link Up/Downイベントが通知されるSNMPの機能がついているものがあります。
これがあれば、誰かが勝手にLANにつなごうとしているのを検出できたり、何かのはずみでLANケーブルが抜けてしまったことを検知できることになります。
さらに、この検知をCloudWatchに通知すれば、集中管理できそうです。
とは言いながら、そもそもCloudWatchに通知するためのLANケーブルが抜けてしまっては、CloudWatchに通知できないので、参考情報の一つととらえてください。
一方、このSNMPと同様の機能が、Windowsにもありますので、今回はWindowsをルータとみなして、SNMPのLink Up/Down検知およびCloudWatchへの通知をしてみたいとおもいます。
ネットワーク環境
こんな感じのネットワークを想定しています。
別のネットワーク
|
Windows10(監視対象のルータ想定)
|
ルータ - SNMP監視サーバ
|
CloudWatch
Windows10を監視対象のルータとして見立てています。Windows10には2つのネットワークインタフェースがあり、片方のネットワークケーブルが断線した場合を考えます。
SNMPエージェントをWindows10で動作させ、常時監視をします。
SNMPエージェントがネットワークインタフェースのダウンを検知すると、SNMP監視サーバに通知します。
SNMP監視サーバは、通知を検知すると、通知内容を判別し、CloudWatchに通知します。
SNMPエージェントが「snmpd」、SNMP監視サーバが「snmptrapd」です。また、「snmp」の各種コマンドを使えば、ローカルまたはリモートマシンのSNMPの情報を取得することができます。
SNMPエージェントのインストール
Windows10とUbuntuそれぞれでのインストール方法を示しておきます。
Windows10の場合
OS標準の機能ですが、手動で有効化する必要があります。
設定から「アプリと機能」を開きます。
「オプション機能の管理」を選択します。
「機能の追加」を押下し、リストの中から「簡易ネットワーク管理プロトコル(SNMP)」を選択します。
そうすると、コンピュータの管理の「サービス」に「SNMPサービス」が現れます。おそらく、状態は実行中になっているかと思います。
次に、SNMPサービスをダブルクリックしてプロパティを表示します。
「セキュリティ」タブを選択します。
受け付けるコミュニティ名として、コミュニティ「public」、権利「読み取りのみ」を追加します。
また、SNMPパケットを受け付けるホスト名またはIPアドレスを指定します。ここでは単純に、「すべてのホストからSNMPパケットを受け付ける」を選択しています。
これで、SNMP監視サーバから、SNMPの各種情報を取得できるようになりました。
Ubuntuの場合
Ubuntuの場合のインストールは、以下を実行します。
# apt-get install snmpd
以下のファイルを修正する必要があります。
/etc/snmp/snmpd.conf
・・・
# Listen for connections from the local system only
# agentAddress udp:127.0.0.1:161
# Listen for connections on all interfaces (both IPv4 *and* IPv6)
agentAddress udp:161,udp6:[::1]:161
・・・
# rocommunity public default -V systemonly
rocommunity public default
・・・
これで再起動すれば、他のPCからSNMP情報を取得できるようになります。
# /etc/init.d/snmpd restart
SNMPの情報の取得
Ubuntuで、以下を実行します。
# apt-get install snmp snmp-mibs-downloader
これで、SNMPの情報取得のための各種コマンドを実行できるようになりました。
その前に、以下のファイルで、修正が必要です。
/etc/snmp/snmp.conf
mibs:をコメントアウトし、mibs allを追記します。
# 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
これで準備ができたはずなのですが、環境によって以下のようなエラーが出る場合があります。
Bad operator (INTEGER): At line 73 in /usr/share/mibs/ietf/SNMPv2-PDU
その場合は、以下を実行します。
# wget http://www.iana.org/assignments/ianaippmmetricsregistry-mib/ianaippmmetricsregistry-mib -O /usr/share/snmp/mibs/iana/IANA-IPPM-METRICS-REGISTRY-MIB
# wget http://pastebin.com/raw.php?i=p3QyuXzZ -O /usr/share/snmp/mibs/ietf/SNMPv2-PDU
# wget http://pastebin.com/raw.php?i=gG7j8nyk -O /usr/share/snmp/mibs/ietf/IPATM-IPMC-MIB
(参考)
https://docs.linuxconsulting.mn.it/notes/net-snmp-errors
それでは、取得してみましょう。
ローカルホストの場合
$ snmpwalk -v1 localhost -c public
リモートホストの場合
$ snmpwalk -v1 【SNMPエージェントのホスト名】 -c public
すごくたくさんの情報が取得されたかと思います。以下のように指定すると、特定の情報のみ取得します。
$ snmpwalk -v1 localhost -c public .1.3.6.1.2.1.2.2.1.2
$ snmpwalk -v1 localhost -c public RFC1213-MIB:ifDescr
実は、上の2つは同じ情報を指しています。
.1.3.6.1.2.1.2.2.1.2
と
RFC1213-MIB:ifDescr
は同じです。そのOIDと名前のマッピング情報が「snmp-mibs-downloader」にあったわけです。
マッピング情報は、以下の方法で、相互に調べることができます。
$ snmptranslate .1.3.6.1.2.1.2.2.1.10
RFC1213-MIB::ifInOctets
$ snmptranslate -On RFC1213-MIB::ifInOctets
.1.3.6.1.2.1.2.2.1.10
ちなみに、SNMPの項目は、以下を実行することで一覧取得できます。多すぎて面喰いますが。
$ snmptranslate -Tp
どのようなOIDがあるかどうかは、以下の方の記事が参考になります。
ネットワーク機器のSNMP MIB/OIDまとめ
SNMPトラップの設定
LANのLink Up/Down を通知するには、トラップ機能を使います。
通常、監視しているサーバから、snmpwalkやsnmpgetコマンドを使って、SNMPエージェントに対して情報取得を要求するのですが、トラップは、SNMPエージェント側から通知をするための機能です。
Windowsでは、SNMPサービスのプロパティから設定します。
通知する際のコミュニティ名を指定し、トラップ通知先をIPアドレスまたはホスト名を指定しておきます。
SNMPトラップの受信設定
SNMPトラップの受信側では、以下をインストールし、デーモンとして起動しておく必要があります。
# apt-get install snmptrapd
次に、以下のファイルを修正します。
/etc/snmp/snmptrapd.conf
以下の部分のpublicの行のコメントを外します。Windows側から通知する際のコミュニティ名と合わせてください。
# authCommunity log,execute,net private
authCommunity log,execute,net public
変更が完了したら、snmptrapd を再起動します。
# /etc/init.d/snmptrapd restart
準備ができました。
WindowsのLANケーブルを抜いてみてください。
ちょっとすると、/var/log/syslog に以下のようなログが記録されているかと思います。
Oct 6 01:47:34 【SNMP監視サーバのホスト名】 snmptrapd[1072]: 2019-10-06 01:47:34 【SNMPエージェントのホスト名】 [【SNMPエージェントのIPアドレス】] (via UDP: [【SNMPエージェントのIPアドレス】]:59663->[【SNMP監視サーバのIPアドレス】]:162) TRAP, SNMP v1, community public#012#011RFC1155-SMI::enterprises.311.1.1.3.1.1 Link Down Trap (0) Uptime: 23:18:52.53#012#011RFC1213-MIB::ifIndex.32 = INTEGER: 32
SNMPトラップをCloudWatchにアップする
snmptrapdには、SNMPトラップを受信したとき、指定されたプログラムを起動して、受信したSNMPトラップ情報を渡してくれる機能があります。
下記のような感じにしています。(traphandleのところ)
/etc/snmp/snmptrapd.conf
## send mail when get any events
# traphandle default /usr/bin/traptoemail -s smtp.example.org foobar@example.org
traphandle .1.3.6.1.6.3.1.1.5.* /home/XXXXXXXXXX/link_trap.sh
「.1.3.6.1.6.3.1.1.5.*」 の部分で、SNMPトラップで転送したいOIDを指定しています。
あとは、指定したプログラム(今回はシェルスクリプト)を実装し、その中でCloudWatchに上げればよいわけです。
実は、指定したプログラム(シェルスクリプト)には、以下のような情報が標準入力として渡されます。
【SNMPエージェントのホスト名】
UDP: [【SNMPエージェントのIPアドレス】]:59663->[【SNMP監視サーバのIPアドレス】]:162
DISMAN-EXPRESSION-MIB::sysUpTimeInstance 0:17:30:04.71
SNMPv2-MIB::snmpTrapOID.0 IF-MIB::linkDown
RFC1213-MIB::ifIndex.35 35
SNMP-COMMUNITY-MIB::snmpTrapAddress.0 【SNMPエージェントのIPアドレス】
SNMP-COMMUNITY-MIB::snmpTrapCommunity.0 "public"
SNMPv2-MIB::snmpTrapEnterprise.0 RFC1155-SMI::enterprises.311.1.1.3.1.1
これがlinkDownのときの通知内容です。
このうち欲しかったのは以下の情報です。
【SNMPエージェントのホスト名】
SNMPv2-MIB::snmpTrapOID.0 IF-MIB::linkDown
RFC1213-MIB::ifIndex.35 35
先頭行には、送信元ホスト名があります。
linkDown通知であることがわかります。
35とは、linkDownの事象となったLANポートの番号です。Windowsでは、vEthernetやらBluetoothネットワークなど、たくさんの仮想的なネットワークインタフェースが動いており、それぞれに重ならないように番号がついています。
ルータの場合は、純粋にLAN端子の番号になると思います。
snmptrapd.confで指定したスクリプトは以下となります。
標準入力された情報から必要な情報を抽出し、CloudWatchに通知しています。(bashシェルスクリプトは初心者なのでもっと効率的に書けるのでは。。。)
# !/bin/bash
export AWS_CREDENTIAL_FILE=/home/XXXXXXXX/awscreds
while read line
do
if [ -z "$host" ]; then
host=${line}
else
set ${line}
if [[ ${1} =~ "RFC1213-MIB::ifIndex." ]]; then
ifIndex=${2}
fi
if [ ${1} = "SNMPv2-MIB::snmpTrapOID.0" ]; then
if [ ${2} = 'IF-MIB::linkUp' ]; then
link=1
elif [ ${2} = 'IF-MIB::linkDown' ]; then
link=0
fi
fi
fi
done
if [ "$link" -a "$ifIndex" ]; then
echo aws cloudwatch put-metric-data --namespace SNMP_IFLink --metric-name IFLink --dimensions "host=$host,ifNumber=$ifIndex" --value $link
aws cloudwatch put-metric-data --namespace SNMP_IFLink --metric-name IFLink --dimensions "host=$host,ifNumber=$ifIndex" --value $link
fi
AWS_CREDENTIAL_FILEに指定するファイルには以下の形式で記載しておきます。当然ながら、そのIAMユーザにはCloudWatchへput-metric-dataする権利がある必要があります。
AWSAccessKeyId=YYYYYYYYYYYYYYYYYYYY
AWSSecretKey=zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
aws cloudwatch *** の部分が、CloudWatchに通知している個所になります。
コマンドラインからAWSを操作するためのaws-cliを使っています。
(参考)
https://docs.aws.amazon.com/cli/latest/reference/cloudwatch/put-metric-data.html
SNMPトラップ機能をリスタートし、LANケーブルを抜いてみましょう。
# /etc/init.d/snmptrapd restart
ちょっとわかりにくいかもしれませんが、CloudWatchに情報がアップされているのがわかります。
メトリクスネームスペースはSNMP_IFLinkとしています。
メトリクスの値は、Link Up/Down の情報です。Upの場合は1、Downの場合は0としています。また、どのルータのどのLAN端子番号で発生したのかがわかるように、ディメンジョンとしてhostとifNumberが渡っているのがわかります。
以上