プログラマ探偵の事件簿:新たなダイイングメッセージの真相!
去年書いた
のような事件にまた遭遇した。今回はTWSNMP FCがSNMPのTRAPを受信により停止した原因を調べた時の話である。助手の猫は大好きな雨水がすぐに無くなるのでちょっと不機嫌である。そして、私の助手よりもかみさんに甘えるほうがよいらしいく、この事件が解決した時に一言「にゃー」と言いにきた以外は、かみさんのそばにべったりしていた。
事件の始まり
TWSNMPのSNMPv3通信に関する問い合わせを調べるためSNMPv3のTRAPをTWSNMP FCに送信してみた。TRAPを確認するためにブラウザーからTRAPの画面を開こうとすると画面が表示されない。TWSNMP FC自体が停止していたのだ。
ダイイングメッセージを探す
ログを出力させてみると、
panic: runtime error: slice bounds out of range [63:61]
goroutine 298 [running]:
github.com/twsnmp/gosnmp.(*UsmSecurityParameters).unmarshal(0xc003a98270, 0xc003a98203, 0xc0005c2000, 0xc1, 0x1000, 0x37, 0x10, 0x507a220, 0x63b8c98)
/Users/ymimacmini/go/pkg/mod/github.com/twsnmp/gosnmp@v1.32.2/v3_usm.go:975 +0x13ce
久しぶりのパニック発生!GO言語のスライスで63から61のデータを指定している。範囲外のデータということだ!ソースコードを確認すると
の場所である。確かにスライスで範囲指定している。もし
len(macVarbinds[sp.AuthenticationProtocol])
が0になれば、この問題が起こる。なぜ0になっているのか?
デフォルトを信じるな
sp.AuthenticationProtocolはSNMPv3の認証プロトコルの方式であるが、
これが初期値0のため未定義の状態になっている。lenが0になる原因である。TWSNMPでは、SNMPv3以外の場合TRAPの受信をデフォルトの設定で受信していた。SNMPv3に関するパラメータは未設定のままであった。
このためsp.AuthenticationProtocolが0になっていた。
gosnmpのパッケージが必要な設定を未設定ならばエラーにするか適切なデフォルト値で処理してくれればパニックは回避できたはずだ!
信じた私が悪かった。
衝撃の事実
修正のために、VSCodeでgosnmpのTRAP受信の関数のヘルプを表示させると
「SNMPv3のTRAP受信は信頼できない」という注意書き!
「そうだったのか!」
パラメータを初期化して解決
SNMPv3以外でもパラメータを初期化して問題は解決した。
// SNMPv2c
tl.Params.Version = gosnmp.Version2c
tl.Params.SecurityModel = gosnmp.UserSecurityModel
tl.Params.MsgFlags = gosnmp.NoAuthNoPriv
tl.Params.SecurityParameters = &gosnmp.UsmSecurityParameters{
UserName: datastore.MapConf.SnmpUser,
AuthenticationProtocol: gosnmp.SHA,
AuthenticationPassphrase: datastore.MapConf.SnmpPassword,
PrivacyProtocol: gosnmp.AES,
PrivacyPassphrase: datastore.MapConf.SnmpPassword,
}
gosnmpのSNMPv3は、これからも何かありそうだ。