snmp trapをircで見る
何だかよくわからない
スイッチのcpu使用率は急に落ち着いてきました.何もしてないんだけどなぁ.不気味です.だからって監視をやめてしまうと後が怖いので,継続してsyslogを見る事にしました.そんなとき普通は,syslogサーバにスイッチのlogを飛ばして/var/log/syslogを定期的に眺めるもんだと思いましたが,すぐに飽きてしまいそうなので,logをircに飛ばしてみることにしました.
CISCO-SYSLOG-MIB
最初はsyslogファイルをtailして,差分をircに投げようかと思ったのですが,なんかアーキテクチャが気持ち悪い.専用のsyslogdを作ることもちょっと考えたんですが,偶然snmp trapでsyslogメッセージを送れる事に気がつきました.実際に
snmp-server host loghost version 2c communityString syslog
なんて設定をスイッチに入れてケーブルの抜き差しなんてことをやってみると,syslogと同じメッセージが飛んでいます.そこで簡単なtrapdを作る事にしました.Net::SNMPとかCPANにあるSNMP関連のモジュールではtrapdを簡単に作るサンプルがないんですが,mrtgで使われているhttp://www.switch.ch/misc/leinen/snmp/perl/にはtrapdのサンプルが着いています.これを参考にすることにしました.ちなみに,このライブラリはModule::ThirdParty - Provide information for 3rd party modules (outside CPAN) - metacpan.orgでも紹介されている有名どころなので,覚えておいて損はないと思います.
syslog-trap.pl
ってことで作ってみたスクリプトは以下のようになります.
#!/usr/local/bin/perl use strict; use warnings; use lib 'SNMP_Session-1.10/lib'; use SNMP_Session; use BER; use Socket; use POE::Component::IKC::ClientLite; use Term::ANSIColor qw(:constants); sub msg (@) { print GREEN, BOLD, " * ", RESET, "@_\n" } my ( %status, $session, $trap, $sender, $sender_port ); %status = ( 1 => 'EMERGENCY', 2 => 'ALERT', 3 => 'CRITICAL', 4 => 'ERROR', 5 => 'WARNING', 6 => 'NOTICE', 7 => 'INFO', 8 => 'DEBUG', ); $session = SNMPv2c_Session->open_trap_session() or die "cannot open trap session"; msg "trapd start"; while ( ( $trap, $sender, $sender_port ) = $session->receive_trap() ) { print_trap( $sender, $session, $trap ); } sub print_trap { my ( $sender, $session, $trap ) = @_; my ( $binding, $severity, $message ); my ( $community, $ent, $agent, $gen, $spec, $dt, $bindings ) = $session->decode_trap_request($trap); while ($bindings) { my ( $oid, $value ); ( $binding, $bindings ) = decode_sequence($bindings); ( $oid, $value ) = decode_by_template( $binding, "%O%@" ); $severity = pretty_print($value) if ( BER::pretty_oid($oid) =~ /1.3.6.1.4.1.9.9.41.1.2.3.1.3/ ); $message = pretty_print($value) if ( BER::pretty_oid($oid) =~ /1.3.6.1.4.1.9.9.41.1.2.3.1.5/ ); } if ( $severity && $message ) { my $notify = sprintf "%s - %s %s on %s", $status{$severity}, inet_ntoa($sender), $message, scalar localtime(time); msg($notify); if ( $severity < 4 ) { my $r = POE::Component::IKC::ClientLite::create_ikc_client( port => 9999, ip => "localhost", name => "syslogtrap$$", timeout => 5, ) || die "create_ikc\n"; $r->post( 'notify_irc/update', $notify ); } } }
昨日の日記に書いたirclient.plを拡張しています.サーバ側は同じnotify-irc.plスクリプトです.スイッチから何かログがとんで来たらとりあえずコンソールにメッセージを出力し,CRITICAL/ALERT/EMERGENCYレベルのログであればircに飛ばします.SNMPのオブジェクト定義はftp://ftp.cisco.com/pub/mibs/v2/CISCO-SYSLOG-MIB.myにあったものを参考にしました.ログの出力イメージはこんな感じになります.
* ERROR - 10.0.0.1 Interface FastEthernet4/0/15, changed state to up on Wed Oct 10 14:39:09 2007 * ERROR - 10.0.0.1 Interface FastEthernet4/0/15, changed state to down on Wed Oct 10 14:40:25 2007
なぜ,ポートのアップダウンごときがエラーになるのだ?!とかそんな感想はさておきなんとか適当に動いているようです.
さて,
とりあえず,撒き餌はしました.後は魚が網にかかるのを待つだけです.どんな魚がいるのか,そしてそれをめでたく釣り上げることはできるのか.しばらくは様子見です.