SNMP 实战与排错 — snmpwalk 抓包、监控落地与故障定位

SNMP 动手实战:Wireshark 过滤式、net-snmp 命令族、v3 用户配置、超时/OID 不存在/Trap 丢失排错、与 NETCONF 对比 / 应用层 / UDP 161

这篇你能学到

  • 怎么用 Wireshark / tshark 把 SNMP 报文抓出来看清楚,尤其是"明文 community 到底有多裸奔"。
  • net-snmp 全套命令怎么用:读单值、遍历表、批量抓、v3 加密查询、写配置、发 Trap,以及 Linux 与思科/华为设备两侧怎么配。
  • 六类高频故障(超时、OID 不存在、写不进去、流量图乱跳、Trap 收不到、被当成 DDoS 放大器)的定位套路,外加选型对比、速查表与面试题。

抓包观察

Wireshark 显示过滤式

下面这些过滤式是排错时的"筛子":你抓到的包往往上千条,先用一条过滤式把无关流量滤掉,再看细节。最值得先记住的是 snmp.error_status != 0(只看出错的)和 snmp.community == "public"(找弱口令)。

过滤式用途
snmp所有 SNMP 报文(Wireshark 自动解 BER)
udp.port == 161只看轮询请求/响应
udp.port == 162只看 Trap / Inform
snmp.version == 0只看 v1(0=v1, 1=v2c, 3=v3)
snmp.version == 3只看 v3
snmp.community == "public"抓默认弱口令,安全审计常用
snmp.data == 4只看 v1 Trap(data 即 PDU 类型:0 get, 1 getnext, 2 response, 3 set, 4 trap, 5 getbulk, 6 inform, 7 snmpV2-trap, 8 report)
snmp.name contains "1.3.6.1.2.1.2.2"只看访问接口表的报文
snmp.error_status != 0只看出错的响应,排错第一过滤式
snmp.msgUserNamev3 用户名(明文可见,即使 authPriv 也不加密)
snmp && ip.addr == 10.0.0.1只看与某台设备的交互

命令行抓包

没有图形界面时(比如在服务器上),用下面三条命令就能完成"抓下来 → 提取关键字段 → 实时盯"三件事。第二条尤其实用:它能把一个 pcap 里所有明文口令一次性列出来,是安全审计的常用手法。

1
2
3
4
5
6
7
8
9
# tcpdump 抓 SNMP 到文件(-s 0 抓全包,UDP 报文可能较大)
sudo tcpdump -i eth0 -s 0 -w snmp.pcap 'udp port 161 or udp port 162'

# tshark 直接打印 community 与 OID(快速审计明文口令)
tshark -r snmp.pcap -Y snmp -T fields \
  -e ip.src -e ip.dst -e snmp.version -e snmp.community -e snmp.name

# 实时监控哪些主机在扫 SNMP
sudo tshark -i eth0 -Y 'snmp.community' -T fields -e ip.src -e snmp.community

典型字段说明(Wireshark 解码视图)

一个 v2c GetRequest 在 Wireshark 中展开长这样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
Simple Network Management Protocol
    version: v2c (1)  注意 v2c 的数值是 1
    community: public  明文!这就是密码
    data: get-request (0)
        get-request
            request-id: 1234567  用它把 Response 配对
            error-status: noError (0)
            error-index: 0
            variable-bindings: 1 item
                1.3.6.1.2.1.1.5.0: ...
                    Object Name: 1.3.6.1.2.1.1.5.0 (iso.3.6.1.2.1.1.5.0)
                    Value (Null)  请求时值为 NULL

对应的 Response 中 Value 会变成 Value (OctetString): core-sw01

排错时重点看三处

  1. 有没有 Response:只见 GetRequest 无 Response → 网络不通 / ACL 拦截 / Agent 未监听 / community 错(多数 Agent 对错误 community 静默丢弃,不回错误)。
  2. error-statusnoSuchName(2) = OID 不存在或无权限;readOnly(4) / notWritable(17) = 用只读 community 做了 SET;authorizationError(16) = v3 权限不足;tooBig(1) = 响应超过 Agent 的 msgMaxSize,减小 getbulk 的 max-repetitions。
  3. v3 的 Report PDU:如果一直收到 Report 而拿不到数据,看它携带的计数器 OID:
    • 1.3.6.1.6.3.15.1.1.5.0 usmStatsWrongDigests → 认证口令错
    • 1.3.6.1.6.3.15.1.1.3.0 usmStatsUnknownUserNames → 用户名不存在
    • 1.3.6.1.6.3.15.1.1.2.0 usmStatsNotInTimeWindows → 时钟不同步(超出 ±150 秒窗口)
    • 1.3.6.1.6.3.15.1.1.6.0 usmStatsDecryptionErrors → 加密口令错

常用命令 / 配置

安装 net-snmp 工具族

这一步装的是"客户端工具箱"(snmpget/snmpwalk 等)和"服务端 Agent"(snmpd)。最后两行是 Debian 系特有的坑:默认不加载 MIB 字典,导致输出全是一串数字而不是可读名字。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Debian / Ubuntu
sudo apt install snmp snmpd snmp-mibs-downloader

# RHEL / CentOS / Rocky
sudo yum install net-snmp net-snmp-utils

# macOS
brew install net-snmp

# 默认 Debian 系不加载 MIB 文件,导致只显示数字 OID。启用方法:
sudo sed -i 's/^mibs :/# mibs :/' /etc/snmp/snmp.conf
sudo download-mibs

查询命令(Manager 侧)

这一组是日常用得最多的"读数"命令。简单说:snmpget 读一个值,snmpgetnext 读下一个值,snmpwalk 一路读到底,snmpbulkwalk 是加速版的 walk,snmptable 把表格排整齐给人看,snmptranslate 则纯粹是本地查字典、根本不发包。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 读单个对象:设备名
snmpget -v2c -c public 192.168.1.1 1.3.6.1.2.1.1.5.0
snmpget -v2c -c public 192.168.1.1 SNMPv2-MIB::sysName.0 # 用 MIB 名更易读

# 取"下一个"对象(理解 getnext 语义的最好方式)
snmpgetnext -v2c -c public 192.168.1.1 1.3.6.1.2.1.1

# 遍历整棵子树(最常用!先看系统信息)
snmpwalk -v2c -c public 192.168.1.1 1.3.6.1.2.1.1

# 遍历接口表:看设备有哪些口、什么状态、跑多少流量
snmpwalk -v2c -c public 192.168.1.1 IF-MIB::ifDescr
snmpwalk -v2c -c public 192.168.1.1 IF-MIB::ifOperStatus
snmpwalk -v2c -c public 192.168.1.1 IF-MIB::ifHCInOctets # 64 位计数器

# 批量遍历(GetBulk,比 walk 快得多;-Cr 指定 max-repetitions)
snmpbulkwalk -v2c -c public -Cr50 192.168.1.1 1.3.6.1.2.1.2.2

# 以表格形式输出,可读性最好
snmptable -v2c -c public -Ci 192.168.1.1 IF-MIB::ifTable

# 常用输出选项
snmpwalk -v2c -c public -On 192.168.1.1 sysUpTime # -On 强制显示数字 OID
snmpwalk -v2c -c public -Oqv 192.168.1.1 sysName.0 # -Oqv 只输出值,便于脚本处理
snmpwalk -v2c -c public -t 5 -r 2 192.168.1.1 system # -t 超时秒数 -r 重试次数

# 查 OID 对应的 MIB 定义(不发包,纯本地查字典)
snmptranslate -Td -On IF-MIB::ifOperStatus
snmptranslate -On IF-MIB::ifInOctets # 名字 → 数字
snmptranslate 1.3.6.1.2.1.2.2.1.10 # 数字 → 名字

SNMPv3 查询

v3 不再用一个 community 字符串走天下,而是"用户名 + 认证口令 + 加密口令"三件套。下面两条命令分别演示"既认证又加密"和"只认证不加密"两档安全级别。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# authPriv:SHA 认证 + AES 加密(生产推荐)
snmpwalk -v3 -l authPriv \
  -u monitor -a SHA -A 'AuthPass123!' \
  -x AES -X 'PrivPass456!' \
  192.168.1.1 1.3.6.1.2.1.1

# authNoPriv:只认证不加密
snmpwalk -v3 -l authNoPriv -u monitor -a SHA -A 'AuthPass123!' 192.168.1.1 system

# 参数含义:-l 安全级别 -u 用户名 -a 认证算法(MD5|SHA|SHA-256...)
# -A 认证口令 -x 加密算法(DES|AES) -X 加密口令

写操作(SET)

这组命令是往设备里"写"值,需要读写权限。第二条会直接把交换机的某个物理口关掉——生产环境执行前务必确认 ifIndex 对不对。命令末尾的单个字母是值的类型标识,写错类型会直接报错。

1
2
3
4
5
6
7
8
# 修改设备联系人(需要读写权限)
snmpset -v2c -c private 192.168.1.1 SNMPv2-MIB::sysContact.0 s "netops@example.com"

# 关闭第 3 号接口(ifAdminStatus: 1=up 2=down 3=testing)—— 生产慎用!
snmpset -v2c -c private 192.168.1.1 IF-MIB::ifAdminStatus.3 i 2

# 类型标识:i=INTEGER s=STRING a=IPADDRESS u=UNSIGNED
# t=TIMETICKS o=OBJID x=HEX STRING d=DECIMAL STRING

Agent 侧配置(Linux net-snmp)

这份配置文件决定了"这台 Linux 对外暴露什么、谁能读、往哪发告警"。第一行 agentAddress 最关键——不改它,外部机器永远连不上。

编辑 /etc/snmp/snmpd.conf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# ---------- 监听地址(默认只听 127.0.0.1,这是最常见的"不通"原因)----------
agentAddress udp:161,udp6:[::1]:161

# ---------- v2c:只读 community,限制来源网段 ----------
rocommunity MyS3cretRO 10.0.0.0/8 -V systemonly
rocommunity6 MyS3cretRO ::1

# ---------- 定义视图:只暴露必要子树 ----------
view systemonly included .1.3.6.1.2.1.1 # system 组
view systemonly included .1.3.6.1.2.1.2 # interfaces 组
view systemonly included .1.3.6.1.2.1.25 # host resources
view systemonly excluded .1.3.6.1.2.1.1.5 # 举例:隐藏 sysName

# ---------- v3 用户(推荐)----------
# 创建用户需先停止 snmpd,写入 /var/lib/snmp/snmpd.conf:
# net-snmp-create-v3-user -ro -A 'AuthPass123!' -a SHA -X 'PrivPass456!' -x AES monitor
rouser monitor authPriv -V systemonly

# ---------- Trap 目标 ----------
trap2sink 10.0.0.100:162 MyTrapCommunity # v2c Trap
informsink 10.0.0.100:162 MyTrapCommunity # 带确认的 Inform

# ---------- 系统信息 ----------
sysLocation "Beijing IDC / Rack A12"
sysContact "netops@example.com"

# ---------- 扩展:自定义脚本作为 OID(强大且常用)----------
extend diskcheck /usr/local/bin/check_disk.sh
# 之后可通过 NET-SNMP-EXTEND-MIB::nsExtendOutput1Line."diskcheck" 读取

改完配置必须重启生效,然后按下面三步自检:先看服务活没活,再看监听地址是不是还锁在 127.0.0.1,最后本机自己查一次确认能出数。

1
2
3
4
5
# 重启并验证
sudo systemctl restart snmpd
sudo systemctl status snmpd
sudo ss -ulnp | grep 161 # 确认监听地址不是 127.0.0.1
snmpwalk -v2c -c MyS3cretRO localhost system # 本机自测

网络设备侧配置(参考)

交换机路由器上的配置逻辑和 Linux 一样,只是换了套命令:先定义"能看哪些 OID"(view),再定义"哪个组用什么安全级别"(group),然后建用户、指定告警接收方、最后用 ACL 限制谁能来查。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
# Cisco IOS
snmp-server community MyS3cretRO RO 10 # 10 是 ACL 编号
snmp-server group MONGRP v3 priv read MONVIEW
snmp-server view MONVIEW 1.3.6.1.2.1 included
snmp-server user monitor MONGRP v3 auth sha AuthPass123 priv aes 128 PrivPass456
snmp-server host 10.0.0.100 version 3 priv monitor
snmp-server enable traps snmp linkdown linkup coldstart
access-list 10 permit 10.0.0.100

# Huawei VRP
snmp-agent community read cipher MyS3cretRO acl 2000
snmp-agent sys-info version v3
snmp-agent group v3 mongrp privacy read-view mibview
snmp-agent mib-view included mibview 1.3.6.1.2.1
snmp-agent usm-user v3 monitor group mongrp authentication-mode sha AuthPass123 privacy-mode aes128 PrivPass456
snmp-agent target-host trap address udp-domain 10.0.0.100 params securityname monitor v3 privacy

发送与接收 Trap(测试用)

排查"收不到告警"时,不要干等设备出故障——用下面的命令自己造一个假告警发过去,就能立刻验证接收链路通不通。前半段是启动接收端,后半段是手工构造并发送。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 接收端:前台启动 trap 守护进程,直接打印到屏幕
sudo snmptrapd -f -Lo -c /etc/snmp/snmptrapd.conf
# /etc/snmp/snmptrapd.conf 至少要有:
# authCommunity log,execute,net MyTrapCommunity
# disableAuthorization yes # 仅测试环境用

# 发送端:手工构造一个 linkDown Trap
snmptrap -v2c -c MyTrapCommunity 10.0.0.100:162 '' \
  1.3.6.1.6.3.1.1.5.3 \
  1.3.6.1.2.1.2.2.1.1.3 i 3 \
  1.3.6.1.2.1.2.2.1.8.3 i 2

# 发送 Inform(会等待确认)
snmpinform -v2c -c MyTrapCommunity 10.0.0.100:162 '' 1.3.6.1.6.3.1.1.5.3

常见故障与排错

故障 1:Timeout: No Response from 192.168.1.1

先记住结论:这条报错不代表网络不通。 SNMP 的超时是个"万能报错",网络不可达、防火墙拦截、Agent 只听本地、community 写错、源 IP 不在白名单,这五种完全不同的原因表现出来一模一样。所以只能按下表从下往上逐层排除,不能跳步。

这是 SNMP 最高频的报错,它不区分"网络不通"和"认证失败",需逐层排查:

排查层命令 / 检查点说明
① 三层可达ping 192.168.1.1不通先解决路由/ARP
② UDP 161 可达nmap -sU -p 161 192.168.1.1结果 open|filtered 属正常(UDP 特性);filtered 明确表示被防火墙拦
③ Agent 监听地址设备侧 ss -ulnp | grep 161net-snmp 默认只监听 127.0.0.1,必须改 agentAddress
④ 防火墙iptables -L -n | grep 161、云安全组、设备 ACL双向都要放行(请求去 161,响应从 161 回)
⑤ community 错换个 community 试绝大多数 Agent 对错误 community 静默丢弃,表现与网络不通完全一样
⑥ 源 IP 不在白名单检查 rocommunity ... 10.0.0.0/8 或设备 ACL从别的机器试一下即可区分
⑦ 超时太短snmpwalk -t 10 -r 3 ...老旧设备或大表遍历响应慢

故障 2:No Such Object available on this agent at this OID

先记住结论:这句话的意思是"你要的这个门牌号在这台设备上不存在",而九成情况是你自己写错了地址(漏了 .0)或者对方压根没实现这个 MIB,不是设备坏了。

原因排查
该设备根本不实现这个 MIBsnmpwalk 父节点看有没有东西;查厂商 MIB 支持列表
OID 写错(少了 .0标量对象必须带 .0sysName ✗ → sysName.0
视图(View)把它排除了检查 view ... excluded 或设备 snmp-server view
MIB 文件没装,名字解析失败用纯数字 OID 重试;或 download-mibs 后设 MIBS=ALL

故障 3:Error in packet. Reason: notWritable / noAccess

先记住结论:这是权限问题,不是网络问题——你拿只读的钥匙去开了写的锁。 而且即使换成读写权限也可能照样写不了,因为很多对象在 MIB 定义里本身就是只读的。

用只读 community 或只读用户执行了 SET。改用 RW community(rwcommunity)或把 v3 用户加入带 write-view 的组。注意:即使有 RW 权限,很多对象在 MIB 中本身就定义为 read-only,永远写不了。

故障 4:流量图出现巨大尖峰或负值

先记住结论:图形异常几乎都不是设备真的跑出了那么大流量,而是"计数器的坑"——32 位计数器绕圈、设备重启清零、或者 ifIndex 变了导致数据错位。

现象原因解决
周期性巨大尖峰Counter32 回绕。千兆口约 34 秒、万兆口约 3.4 秒就绕一圈改用 ifHCInOctets/ifHCOutOctets(Counter64,需 v2c 及以上);缩短轮询间隔到 60s 以内
突然归零后暴涨设备重启,计数器清零监控 sysUpTime.0,变小时丢弃该数据点
数值不动某些虚拟接口/子接口不更新计数器换用物理口的 ifIndex
ifIndex 变了导致图断裂设备重启或插拔模块后 ifIndex 重新分配ifName/ifAlias(ifXTable)做主键,而不是 ifIndex;设备侧开启 snmp-server ifindex persist

故障 5:收不到 Trap

先记住结论:先分清"包根本没到"还是"包到了但被丢弃"——这两类原因完全不同,抓一次包就能分开。 下面三条命令就是用来做这个判断的:先确认接收端在监听,再前台跑看有没有解出来,最后抓包看网卡层面到底有没有流量进来。

1
2
3
4
5
6
7
8
# ① 接收端真的在监听吗
sudo ss -ulnp | grep 162

# ② 前台跑 snmptrapd 看有没有包进来
sudo snmptrapd -f -Lo -d # -d 打印原始报文

# ③ 抓包确认包到没到网卡(区分"没发"还是"发了没处理")
sudo tcpdump -i any -n udp port 162 -vv
包到了但不显示原因
snmptrapd 授权未配/etc/snmp/snmptrapd.confauthCommunity log,execute,net <community>
v3 Trap 用户未配v3 Trap 需在接收端配置对应的 createUser + authUser log
community 不匹配发送端与接收端的 trap community 要一致
包根本没到原因
设备未使能 TrapCisco 需 snmp-server enable traps ...,默认多数 Trap 是关的
trap 目标地址配错 / 走了错误的源接口检查 snmp-server source-interface traps
中间防火墙丢 UDP 162抓包对比设备出口与接收端入口
网络丢包,Trap 无重传改用 Inform(带确认+重传)

故障 6:安全事件 —— SNMP 反射放大攻击

先记住结论:只要你的 UDP 161 能从公网访问,你的设备就随时可能被别人拿去打人——而且是替别人背锅。 根因是 UDP 不校验源 IP,攻击者伪造受害者地址来查你,你把巨大的响应全砸给受害者。

原理:攻击者伪造受害者源 IP,向大量开放 161 的设备发送 GetBulkRequest(请求包 ~60 字节),设备把巨大的响应(可达数 KB)全发给受害者,放大倍数可超过 600 倍

自查与加固

下面第一条命令是"照镜子"——从外网视角扫自己的公网 IP,如果能读到 sysDescr 就说明已经暴露了。后面的清单是按优先级排列的加固动作。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 自查:自己的公网 IP 有没有暴露 SNMP
nmap -sU -p 161 --script snmp-info <你的公网IP>
# 若能读到 sysDescr,说明已暴露

# 加固清单
# 1) 绝不把 UDP 161 暴露到公网,边界防火墙一律 deny
# 2) 删除默认 community(public / private / cisco / admin)
# 3) 只允许特定管理网段访问:rocommunity xxx 10.0.0.0/8
# 4) 用 View 限制可读子树,最小授权
# 5) 全面迁移到 SNMPv3 authPriv
# 6) 不用的设备直接关掉 SNMP:systemctl disable --now snmpd

与其他协议对比

维度SNMPNETCONF (RFC 6241)gNMI / Streaming TelemetrySyslogNetFlow / IPFIX
主要用途指标监控(读)+ 少量配置配置管理(读写)高频指标采集日志/事件流量明细分析
传输UDP 161/162SSH 830 / TLSgRPC over HTTP/2 (TLS)UDP 514 / TCP 6514UDP 2055 等
数据模型MIB / SMI(ASN.1)YANGYANG无结构(纯文本)流记录模板
编码BER 二进制XMLProtobuf文本二进制
交互模式拉(轮询)为主拉 + 通知推(订阅)
采集频率分钟级(轮询开销大)分钟级秒级/亚秒级事件驱动流结束时导出
事务性有(candidate/commit/rollback)
安全v1/v2c 明文,v3 authPriv默认 SSH/TLS 加密默认 TLS默认明文明文
设备支持度极广,几乎所有设备中高端设备新设备极广中高端设备
典型工具Zabbix / snmp_exporter / Cactincclient / AnsibleTelegraf / OpenConfigrsyslog / Lokinfdump / ntopng

选型结论

  • 存量设备只读监控 → SNMP(无可替代)
  • 配置自动化 → NETCONF/YANG 或 Ansible,别用 SNMP SET
  • 高频细粒度指标(如微突发检测) → gNMI Streaming Telemetry
  • “带宽被谁占满了” → NetFlow / sFlow,SNMP 只能告诉你"占满了"

速查表 / 常见面试题

端口 / 版本速查

Agent 监听UDP 161
Trap 接收UDP 162
DTLS/TLS(RFC 6353)10161 / 10162
version 字段编码v1 = 0,v2c = 1,v3 = 3没有 2
默认只读 communitypublic
默认读写 communityprivate
v3 时间窗±150 秒
HMAC 摘要长度(MD5/SHA-1)12 字节(96 bit 截断)

PDU 类型速查

TagPDU版本
0xA0GetRequestv1+
0xA1GetNextRequestv1+
0xA2Response(v1 叫 GetResponse)v1+
0xA3SetRequestv1+
0xA4Trap(v1 专用结构)v1
0xA5GetBulkRequestv2c+
0xA6InformRequestv2c+
0xA7SNMPv2-Trapv2c+
0xA8Reportv3

一行命令速查

这七条是"到了现场直接抄"的版本,把 HOST 换成设备 IP 即可。

1
2
3
4
5
6
7
snmpwalk -v2c -c public HOST system # 系统信息
snmpwalk -v2c -c public HOST IF-MIB::ifDescr # 接口列表
snmptable -v2c -c public -Ci HOST IF-MIB::ifTable # 接口表格化
snmpbulkwalk -v2c -c public -Cr50 HOST 1.3.6.1.2.1 # 快速全量遍历
snmpget -v2c -c public HOST .1.3.6.1.2.1.1.3.0 # 运行时间
snmptranslate -On IF-MIB::ifInOctets # 名字转数字 OID
snmpwalk -v3 -l authPriv -u U -a SHA -A P1 -x AES -X P2 HOST system

常见面试题

Q1:SNMP 为什么用 UDP 而不是 TCP? A:① 网管流量要在网络已经拥塞/异常时仍能送达,TCP 的重传与拥塞退避反而会延误告警;② Agent 侧资源受限(老交换机 CPU/内存很小),维护上千条 TCP 连接不现实;③ 轮询天然是"一问一答"的短交互,不需要连接状态。代价是不可靠,因此 SNMP 在应用层用 request-id + 超时重传弥补,Trap 则用 Inform 补上确认。

Q2:GetNext 和 GetBulk 的区别?为什么 walk 很慢? A:GetNext 每次只返回一个变量,遍历 N 个对象需要 N 次往返(RTT),一张 48 口交换机的 ifTable 有 20 多列 × 48 行 ≈ 1000+ 次往返。GetBulk 通过 max-repetitions 一次返回多个后继变量,把往返次数压缩到几十次。snmpbulkwalk 就是基于 GetBulk 的,比 snmpwalk 快一个数量级——但 v1 不支持 GetBulk。

Q3:v2c 相比 v1 改进了什么?它解决安全问题了吗? A:改进了三点——① 新增 GetBulk 大幅提升遍历效率;② 新增 Inform(带确认的 Trap);③ 新增 Counter64 支持高速接口。没有解决安全问题:v2c 的 “c” 就是 community-based,仍然明文传 community。真正的安全版本是 v3。

Q4:SNMPv3 的三种安全级别?为什么需要 Engine Discovery? A:noAuthNoPriv(不认证不加密)、authNoPriv(HMAC 认证但明文)、authPriv(认证+AES/DES 加密)。需要 Engine Discovery 是因为 USM 采用密钥本地化:实际用于 HMAC/加密的密钥 = Hash(Ku ‖ authoritativeEngineID ‖ Ku),Manager 必须先知道 Agent 的 engineID 才能算出正确密钥。同时 Report 还携带 engineBoots/engineTime 用于建立防重放时间窗。

Q5:Counter32 回绕怎么处理?什么时候必须用 Counter64? A:Counter32 上限 2³²-1 ≈ 42.9 亿字节。1 Gbps 满速约 34 秒回绕一次,10 Gbps 约 3.4 秒。轮询间隔通常 60~300 秒,远大于回绕周期,数据完全失真。因此百兆以上接口一律使用 ifXTable 的 ifHCInOctets/ifHCOutOctets(Counter64),回绕周期长达数千年。注意 Counter64 只在 SNMPv2c 及以上可用。

Q6:Trap 和 Inform 怎么选? A:Trap 无确认、Agent 发完即忘,开销最小,适合高频且可容忍丢失的事件;Inform 有 Response 确认与重传,可靠但 Agent 需缓存报文。关键告警(设备重启、主链路 down、电源故障)用 Inform,常规状态变化用 Trap。另外注意 Inform 会占用 Agent 内存,大量 Inform 可能压垮低端设备。

Q7:sysUpTime 的单位是什么? A:TimeTicks,单位是百分之一秒(10 毫秒),不是秒。数值 360000 表示 3600 秒 = 1 小时。它也是 32 位的,约 497 天后回绕。

Q8:怎么发现一台陌生设备支持哪些 MIB? A:① snmpwalk -v2c -c public HOST .1 全树遍历(慢但完整);② snmpget HOST sysObjectID.0 拿到厂商私有 OID,再去厂商网站下对应 MIB;③ snmpwalk HOST 1.3.6.1.4.1 看私有分支下有什么;④ nmap -sU -p161 --script snmp-* HOST 用 NSE 脚本快速枚举。

Q9:为什么说 SNMP 是 DDoS 放大攻击的帮凶? A:GetBulkRequest 请求包仅约 60 字节,而响应可达数 KB,放大比可超过 600×。攻击者伪造受害者 IP 作源地址,向互联网上大量开放 UDP 161 的设备群发请求,所有响应涌向受害者。这是 UDP 无连接(不校验源 IP)+ 默认 community public + 设备暴露公网三者叠加的结果。防御核心是永不把 161 暴露到公网

Q10:SNMP 会被什么取代? A:在配置管理领域已被 NETCONF/YANG、RESTCONF 取代(SNMP SET 无事务性、无回滚);在高频遥测领域正被 gNMI / Streaming Telemetry 取代(推模式、秒级、Protobuf 高效编码)。但在存量设备的只读监控领域,SNMP 因为设备支持度接近 100%,短期内仍不可替代——Prometheus 的 snmp_exporter 就是把 SNMP 数据桥接到现代监控栈的典型方案。