TWSNMPをSNMPv3に対応する
TWSNMPをSNMPv3に対応した時の話を書いておきます。梅雨入りして外は雨が激しく降っています。猫はソファーに吐いてしまったのでキーボードから離れて寝ています。あと、久しぶりに浦和レッズの練習試合をライブ中継で観ることができました。
SNMPパッケージのおさらい
TWSNMPではSNMP対応のためGO言語の
というパッケージを使用しています。exampleのフォルダにSNMPv3対応のサンプルプログラムが公開されています。これを参考にすれば比較的簡単にSNMPv3に対応できました。
SNMPv3対応のための設定項目
まず、ドキュメント
とサンプルコードでSNMPv3でアクセスするための設定を眺めてみます。
Version: g.Version3,
SecurityModel: g.UserSecurityModel,
MsgFlags: g.AuthPriv,
SecurityParameters: &g.UsmSecurityParameters{UserName: "user",
AuthenticationProtocol: g.SHA,
AuthenticationPassphrase: "password",
PrivacyProtocol: g.AES,
PrivacyPassphrase: "password",
},
設定するパラメータは、
Version
SNMPのバージョンです。当然V3に設定します。
SecurityModel
セキュリティーモデルです。これはユーザーベースセキュリティーモデルしか使われていないのでこの設定でよいです。
MsgFlags
この設定は、認証と暗号化に関する設定です。
*認証のみ
*認証と暗号化
が選択できます。(暗号化だけは意味がないのでありません。)
UserName
SNMPv3でアクセスする時にユーザー名です。
AuthenticationProtocol
認証のための設定です。MD5とSHA1が選択できます。
AuthenticationPassphrase
認証のためのパスワードです。
PrivacyProtocol
暗号化のための設定です。DESとAESが選択できます。
PrivacyPassphrase
暗号化のためのパスワードです。
です。この内容をよく考えて実際に設定できる項目は、
SNMPモードは、
のような選択項目にしました。作る側の論理だと考えられるすべての組み合わせを設定できるようにしたほうがよいと思うかもしれませんが、使う側で考えると「じゃどれがお勧め」という感じだと思ったのでお勧めの選択だけにしました。
SNMPv3でMIB取得する
ポーリング、自動発見、MIBブラウザーのMIBアクセスをSNMPv3に対応することを考えます。もともとのソースコードは
agent := &gosnmp.GoSNMP{
Target: n.IP,
Port: 161,
Transport: "udp",
Community: n.Community,
Version: gosnmp.Version2c,
Timeout: time.Duration(p.Timeout) * time.Second,
Retries: p.Retry,
ExponentialTimeout: true,
MaxOids: gosnmp.MaxOids,
}
err := agent.Connect()
のようになっていました。 agent.Connect()の前に
if n.SnmpMode != "" {
agent.Version = gosnmp.Version3
agent.SecurityModel = gosnmp.UserSecurityModel
if n.SnmpMode == "v3auth" {
agent.MsgFlags = gosnmp.AuthNoPriv
agent.SecurityParameters = &gosnmp.UsmSecurityParameters{
UserName: n.User,
AuthenticationProtocol: gosnmp.SHA,
AuthenticationPassphrase: n.Password,
}
} else {
agent.MsgFlags = gosnmp.AuthPriv
agent.SecurityParameters = &gosnmp.UsmSecurityParameters{
UserName: n.User,
AuthenticationProtocol: gosnmp.SHA,
AuthenticationPassphrase: n.Password,
PrivacyProtocol: gosnmp.AES,
PrivacyPassphrase: n.Password,
}
}
}
を挿入すればSNMPv3に対応できました。n.Userとかが設定した値です。
SNMPv3のTRAPを受信する
TRAPの受信も修正しないとSNMPv3のTRAPは受信できません。これも比較的簡単に修正できました。
tl := gosnmp.NewTrapListener()
tl.OnNewTrap = func(s *gosnmp.SnmpPacket, u *net.UDPAddr) {
|
}
だったものを
tl := gosnmp.NewTrapListener()
if mapConf.SnmpMode != "" {
tl.Params = &gosnmp.GoSNMP{}
tl.Params.Version = gosnmp.Version3
tl.Params.SecurityModel = gosnmp.UserSecurityModel
if mapConf.SnmpMode == "v3auth" {
tl.Params.MsgFlags = gosnmp.AuthNoPriv
tl.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{
UserName: mapConf.User,
AuthenticationProtocol: gosnmp.SHA,
AuthenticationPassphrase: mapConf.Password,
}
} else {
tl.Params.MsgFlags = gosnmp.AuthPriv
tl.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{
UserName: mapConf.User,
AuthenticationProtocol: gosnmp.SHA,
AuthenticationPassphrase: mapConf.Password,
PrivacyProtocol: gosnmp.AES,
PrivacyPassphrase: mapConf.Password,
}
}
}
tl.OnNewTrap = func(s *gosnmp.SnmpPacket, u *net.UDPAddr) {
|
}
のようにSNMPv3のための設定する部分を挿入しました。思っていたより簡単に修正できました。
SNMPv3のセキュリティーについて思うこと
SNMPのセキュリティーには面白歴史があります。最初のSNMPv1はCommunityという文字列を合言葉としてマネージャとエージェントで共有するという簡単セキュリティーしかありませんでした。今、思うとかなり怖いことです。それではいけないとSNMPv2でセキュリティーを強化した仕様の検討が始まりました。これはSNMPのメーリングリスト上で大喧嘩が行われる。プロトコル戦争に発展しました。結局、セキュリティーに関する仕様はまとまらずにSNMPv1と同じCommunityを使うSNMPv2cだけ残りました。戦争の原因は実際に使う時に難しすぎて使えないということだったと思います。この戦争は、25年以上前でした。私もちょっとだけ巻き込まれました。
その後、仕切り直しでSNMPv3の仕様が決められました。セキュリティー機能も搭載されました。使っている暗号技術は当時としては良かったのですが今となっては、ちょっと心配なものです。認証に使うMD5やSHA1などのハッシュ関数や暗号に使うDESやAES128は今では推奨されていません。Ciscoなどは独自の仕様で暗号方式を拡張していたりします。
でも、今はSNMP自体のセキュリティー機能よりも別の通信技術(VPN、FWなど)でセキュリティーを確保できるので、SNMPの仕様を拡張する必要はないと私は思っています。
開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。