You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Net-SNMP SNMPv3 Trap发送及用户管理问题:C++应用发送的SNMPv3 Trap无法被iReasoning MIB Browser接收

Net-SNMP SNMPv3 Trap发送及用户管理问题:C++应用发送的SNMPv3 Trap无法被iReasoning MIB Browser接收

兄弟,看你这情况,SNMPv3陷阱收不到确实闹心——毕竟v3比v1/v2多了认证加密和Engine ID这些弯弯绕,能收v1/v2说明网络通,问题肯定出在v3的参数匹配或者代码初始化上。先帮你捋捋排查步骤,再聊配置文件管理的事儿。

一、先搞定“收不到陷阱”的问题:从参数匹配到代码细节逐一排查

1. 认证/加密参数必须完全对齐

SNMPv3的安全机制是“严丝合缝”的,你代码里定义的认证算法、加密算法、认证密码、加密密码,必须和iReasoning里配置的用户完全一致,连大小写、空格、特殊字符都不能错!
比如你代码里用的是USM_AUTH_HMAC_SHA1(SHA-1认证),但iReasoning里给用户选了SHA-256,那肯定收不到。还有安全级别也要对应:如果代码里设的是SNMP_SEC_LEVEL_AUTHPRIV(认证+加密),iReasoning里也得选相同的安全级别,不能选无认证无加密或者只认证不加密。

2. 别忽略Engine ID这个关键

SNMPv3靠Engine ID来绑定用户,很多人栽在这儿。你得确保C++代码里设置的Engine ID和iReasoning里目标设备的Engine ID完全一样:

  • 要是代码里没指定Engine ID,Net-SNMP会自动生成一个随机的,这时候你可以先在代码里硬编码一个固定值测试,比如:
    u_char engine_id[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
    size_t engine_id_len = sizeof(engine_id);
    snmpusm_set_engineID(sessp, engine_id, engine_id_len);
    
    然后去iReasoning的用户配置里,把Engine ID改成和代码里一模一样的,再发陷阱测试。

3. 确认陷阱的目标地址和端口,排除防火墙干扰

虽然v1/v2能收到,但还是要确认:

  • 代码里的目标IP是不是iReasoning所在机器的正确IP
  • 162端口有没有被防火墙拦截(有些系统默认会阻止入站的162端口,你可以临时关闭防火墙或者加规则放行)
  • 用Wireshark或者tcpdump抓包,看看SNMPv3的包有没有发出去,iReasoning那边有没有收到——如果包都没到,先查网络;如果到了但被丢弃,那就是参数不匹配。

4. 检查代码初始化步骤有没有漏

Net-SNMP发v3陷阱的初始化步骤比v1/v2多,你得确保这些步骤都做了:

// 初始化会话
netsnmp_session sess, *sessp;
snmp_sess_init(&sess);
sess.version = SNMP_VERSION_3;
sess.peername = "192.168.1.100"; // 替换成iReasoning的IP
sess.securityName = "my_snmp_user";
sess.securityNameLen = strlen(sess.securityName);
// 安全级别要和iReasoning一致
sess.securityLevel = SNMP_SEC_LEVEL_AUTHPRIV;
// 认证算法
sess.securityAuthProto = USM_AUTH_HMAC_SHA1;
sess.securityAuthProtoLen = USM_AUTH_HMAC_SHA1_LEN;
// 加密算法
sess.securityPrivProto = USM_PRIV_AES_128;
sess.securityPrivProtoLen = USM_PRIV_AES_128_LEN;

// 创建会话
if (!(sessp = snmp_open(&sess))) {
  snmp_perror("snmp_open");
  exit(1);
}

// 添加USM用户
if (snmpusm_create_user(sessp, sess.securityName) != SNMPERR_SUCCESS) {
  snmp_perror("snmpusm_create_user");
  snmp_close(sessp);
  exit(1);
}

// 设置认证密码
if (snmpusm_set_auth_passphrase(sessp, sess.securityName, "my_auth_pass") != SNMPERR_SUCCESS) {
  snmp_perror("snmpusm_set_auth_passphrase");
  snmp_close(sessp);
  exit(1);
}

// 设置加密密码
if (snmpusm_set_priv_passphrase(sessp, sess.securityName, "my_priv_pass") != SNMPERR_SUCCESS) {
  snmp_perror("snmpusm_set_priv_passphrase");
  snmp_close(sessp);
  exit(1);
}

要是漏了snmpusm_create_user或者密码设置的步骤,陷阱根本发不出去。

二、把用户信息从硬编码改成配置文件管理

你说要让其他人通过配置文件管理用户,有两种简单的方式:

1. 自己实现简单的配置文件解析

比如用INI格式写配置文件snmp_config.ini

[snmpv3]
username = my_snmp_user
auth_proto = SHA1
auth_pass = my_auth_pass
priv_proto = AES128
priv_pass = my_priv_pass
engine_id = 0000000000000001
trap_target = 192.168.1.100

然后在C++代码里用fstream或者轻量的INI解析库读取这些参数,再对应设置到Net-SNMP的会话结构体里。这样管理员只需要改配置文件,不用碰代码。

2. 利用Net-SNMP自带的配置文件

Net-SNMP会自动读取系统配置文件(比如/etc/snmp/snmp.conf)或者用户目录下的.snmp/snmp.conf,你可以在配置文件里直接添加USM用户:

createUser my_snmp_user SHA "my_auth_pass" AES "my_priv_pass"

然后代码里只需要指定用户名和安全级别,Net-SNMP会自动从配置文件加载用户的认证/加密信息。注意要给配置文件设置合适的权限(比如chmod 600 /etc/snmp/snmp.conf),避免密码泄露。

最后给个测试小技巧

先用Net-SNMP自带的snmptrap命令行工具发一个v3陷阱,看iReasoning能不能收到:

snmptrap -v 3 -u my_snmp_user -l authPriv -a SHA -A my_auth_pass -x AES -X my_priv_pass -e 0000000000000001 192.168.1.100 '' 1.3.6.1.4.1.2021.999.1.1.1.0 s "Test SNMPv3 Trap"

如果命令行发的陷阱能收到,说明iReasoning配置没问题,问题出在你的C++代码里;如果命令行也收不到,那就是iReasoning的配置或者网络问题。

备注:内容来源于stack exchange,提问作者Ebak

火山引擎 最新活动