简单网络管理协议SNMP
SNMP是一种用于监控诸如,路由器,交换机,打印机,服务器,防火墙等设备的管理协议。它运行在UDP协议之上,常用端口是161,162。其中161端口用于管理请求,162端口用于trap告警通知。
作为IETF定义的一种标准协议(RFC:3411-3418),存在很多实现版本(每种实现针对不同场景和需求进行了优化或扩展),比如最常用的开源版本net-snmp,使用纯JAVA语言实现的SNMP4J,PYTHON编写的PySNMP,运用在嵌入式设备、高性能网络设备Agent的SNMP++版本,甚至很多厂商都有自己的私有实现,下文的所有操作都基于net-snmp版本
sudo apt install snmp snmpd snmptrapd snmp-mibs-downloader
sudo download-mibs // 下载mibs数据库
SNMP的全称简单网络管理协议,简单的含义是仅包含少数核心操作,但其实现可能相当复杂。下表列出协议规定需要实现的基本操作
| 操作 | 解释 |
|---|---|
| GET | 获取某个值,例如设备名、系统运行时间 |
| GETNEXT | 获取下一个OID的值(用于遍历) |
| SET | 修改某个值,例如设置位置、启用端口 |
| WALK | 连续GETNEXT操作,相当于扫描整个MIB树 |
| TRAP | 设备主动发送事件通知(如链路断开) |
| INFORM | 主动发送事件通知的同时,需接收方ACK确认,可靠的消息投递 |
1.核心概念
| 术语 | 解释 |
|---|---|
| Manager(管理者) | 发起查询、控制请求的设备(比如 NMS 网络管理系统) |
| Agent(代理) | 被管理设备上运行的进程,响应请求并发送trap |
| MIB(管理信息库) | 存储管理数据的数据库,结构是树形 |
| OID(对象标识符) | 唯一标识一个MIB对象,例如系统名、CPU 使用率等 |
| Community String | 类似密码,控制访问(public只读,private可写) |
对象标识符
用于唯一标识网络设备中可管理对象的标识符。它们在MIB(管理信息库)中定义,并遵循树状的结构。OID主要有三种表示形式,便于人类阅读的模块::名字形式(SNMPv2-MIB::sysDescr.0),适合机器解析的纯数字形式(.1.3.6.1.2.1.1.1.0),混合形式(iso.3.6.1.2.1.1.1.0),详细定义可移步至参考文献1
示例:1.3.6.1.2.1.1.1.0
| 数字部分 | 名称 | 含义 |
|---|---|---|
| 1 | iso | 国际标准化组织 |
| 3 | org | 组织(Organization) |
| 6 | dod | 国防部(Department of Defense) |
| 1 | internet | Internet相关 |
| 2 | mgmt | 管理 |
| 1 | mib-2 | 管理信息库版本2 |
| 1 | system | 系统信息 |
| 1 | sysDescr | 系统描述 |
| 0 | 实例编号 | 表示这是一个具体实例 |
资源视图
在SNMP中,“资源视图”(View)是SNMP中的重要概念,属于访问控制模型(VACM View-based Access Control Model)的一部分。它用于定义一个用户可以访问或不能访问哪些OID子树
# 定义systemonly资源视图,该视图仅能访问
view systemonly included .1.3.6.1.2.1.1
view systemonly included .1.3.6.1.2.1.25.1
权限管理
SNMPv1和SNMPv2c并没有用户的概念,它们通过community字符串来进行身份验证和访问控制,数据使用明文传输的协议
# rocommunity是标准的配置命令,public相当于通信密码,default表示任意访问源(限制访问源)
rocommunity public default -V systemonly
rocommunity6 public default -V systemonly
SNMPv3中不再使用rocommunity,取而代之需要使用createuser创建用户,认证算法使用SHA-512,加密算法使用AES,加密算法用于数据传输
# authpriv表示认证(auth)+加密(priv),用户也可以设置成
createuser authPrivUser SHA-512 myauthphrase AES myprivphrase
rouser authPrivUser authpriv -V systemonly
| 安全级别 | 认证(auth) | 加密 | 配置中对应的写法 |
|---|---|---|---|
| noAuthNoPriv | 无认证 | 无加密 | noauth |
| authNoPriv | 有认证 | 无加密 | auth |
| authPriv | 有认证 | 有加密 | authpriv |
上述配置是典型的RFC3414标准的USM配置方案(User-based Security Model),其实关于SNMP协议模块化的实现方案RFCS-3410-3419中描述运行用户选择安全方案。

- USM目前工业界事实标准
- TSM(Transport Security Model),将认证/加密从SNMP消息层剥离到传输层,支持多种安全传输协议(如DTLS、SSH、TLS),单个安全通道可承载多个SNMP会话,未全部支持
- Kerberos安全模型,大多数实现版本不支持该安全模型
2.基本操作
- snmptranslate,OID的数字形式与文本形式的相互转换
# 数字形式
snmptranslate -On .iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0
.1.3.6.1.2.1.1.1.0
# 全路径名称
snmptranslate -Of .1.3.6.1.2.1.1.1.0
.iso.org.dod.internet.mgmt.mib-2.system.sysDescr.0
# 模块::名字
snmptranslate .1.3.6.1.2.1.1.1.0
SNMPv2-MIB::sysDescr.0
snmptranslate -IR sysUpTime.0
SNMPv2-MIB::sysUpTime.0
# 所有加载的模块
# 1. net-snmp定义的模块
# 2. 自定义的模块
# 3. iana定义的模块
# 4. ietf模块,一般需要访问的oid都位于此目录中
tree /usr/share/snmp/mibs
.
├── LM-SENSORS-MIB.txt # lm-sensors工具(Linux下硬件传感器监控)设计的一个MIB模块文件
├── NET-SNMP-AGENT-MIB.txt
├── NET-SNMP-EXAMPLES-MIB.txt
├── NET-SNMP-EXTEND-MIB.txt
├── NET-SNMP-MIB.txt
├── NET-SNMP-PASS-MIB.txt
├── NET-SNMP-TC.txt
├── NET-SNMP-VACM-MIB.txt
├── UCD-DEMO-MIB.txt
├── UCD-DISKIO-MIB.txt
├── UCD-DLMOD-MIB.txt
├── UCD-IPFWACC-MIB.txt
├── UCD-SNMP-MIB.txt
├── iana -> /var/lib/mibs/iana # IANA MIB模块主要用于存储和管理IANA分配的各种标准化编号、协议、地址族等信息
└── ietf -> /var/lib/mibs/ietf
# 查询功能,使用正则表达式查询所有符合条件的对象
snmptranslate -TB memory
UCD-SNMP-MIB::memory
HOST-RESOURCES-MIB::hrMemorySize
# 打印snmp数结构
snmptranslate -Tp IF-MIB::ifInOctets
+-- -R-- Counter ifInOctets(10)
# MIB文档的即时查阅
snmptranslate -Td IF-MIB::ifInOctets
IF-MIB::ifInOctets
ifInOctets OBJECT-TYPE
-- FROM IF-MIB
SYNTAX Counter32
MAX-ACCESS read-only
STATUS current
DESCRIPTION "The total number of octets received on the interface,
including framing characters.
Discontinuities in the value of this counter can occur at
re-initialization of the management system, and at other
times as indicated by the value of
ifCounterDiscontinuityTime."
::= { iso(1) org(3) dod(6) internet(1) mgmt(2) mib-2(1) interfaces(2) ifTable(2) ifEntry(1) 10 }
- snmpget,snmpwalk,获取对象
强调:访问的资源一定要包含在访问视图中
snmpwalk -v2c -c public 127.0.0.1 HOST-RESOURCES-MIB::hrSWRunTable
HOST-RESOURCES-MIB::hrSWRunIndex.1 = INTEGER: 1
HOST-RESOURCES-MIB::hrSWRunID.1 = OID: SNMPv2-SMI::zeroDotZero
HOST-RESOURCES-MIB::hrSWRunName.1 = STRING: "systemd"
HOST-RESOURCES-MIB::hrSWRunPath.1 = STRING: "/sbin/init"
HOST-RESOURCES-MIB::hrSWRunParameters.1 = ""
HOST-RESOURCES-MIB::hrSWRunType.1 = INTEGER: application(4)
HOST-RESOURCES-MIB::hrSWRunStatus.1 = INTEGER: runnable(2)
# 更好展示table类型数据
snmptable -v2c -c public 127.0.0.1 HOST-RESOURCES-MIB::hrSWRunTable
# 获取hrSWRunTable的数据结构,这里的R表示该字段可读,RW表示读写
# Textual Convention表示文本性的约束,国际化的显示字符串
# hrSWRunIndex(1)表示结构中的第一个元素
snmptranslate -Tp HOST-RESOURCES-MIB::hrSWRunTable
+--hrSWRunTable(2)
|
+--hrSWRunEntry(1)
| Index: hrSWRunIndex
|
+-- -R-- Integer32 hrSWRunIndex(1)
| Range: 1..2147483647
+-- -R-- String hrSWRunName(2)
| Textual Convention: InternationalDisplayString
| Size: 0..64
+-- -R-- ObjID hrSWRunID(3)
| Textual Convention: ProductID
+-- -R-- String hrSWRunPath(4)
| Textual Convention: InternationalDisplayString
| Size: 0..128
+-- -R-- String hrSWRunParameters(5)
| Textual Convention: InternationalDisplayString
| Size: 0..128
+-- -R-- EnumVal hrSWRunType(6)
| Values: unknown(1), operatingSystem(2), deviceDriver(3), application(4)
+-- -RW- EnumVal hrSWRunStatus(7)
Values: running(1), runnable(2), notRunnable(3), invalid(4)
snmpget -v2c -c public 127.0.0.1 HOST-RESOURCES-MIB::hrMemorySize.0
HOST-RESOURCES-MIB::hrMemorySize.0 = INTEGER: 2018684 KBytes
- snmpset,设置对象
snmp除了可以查询当前设备的相关运行状态,网络流量,软件包信息,也可以设置一些基本策略,比如开关网卡,防火墙访问控制策略,甚至通过net-snmp的扩展模块,可以远程执行预设操作,当然动作都是在拥有足够的权限的条件下才能完成
snmpset -v2c -c private 127.0.0.1 ifAdminStatus.2 i 2 # 关闭第二个接口
比如下面的例子中使用extend指令扩展net-snmp功能调用脚本,使用pass指令将特定子树前缀的访问特殊处理
# 修改snmpd.conf文件增加如下内容,pass_persist使用长连接
extend test /tmp/test.sh
pass .1.3.6.1.4.1.2021.999 /usr/local/bin/mysnmphandler
pass_persist .1.3.6.1.4.1.2021.998 /usr/local/bin/mysnmpd.py
snmptranslate -On NET-SNMP-EXTEND-MIB::nsExtendOutput1Line.\"test\"
snmpget -v2c -c public 127.0.0.1 .1.3.6.1.4.1.8072.1.3.2.3.1.1.4.116.101.115.116
snmpwalk -v2c -c public 127.0.0.1 NET-SNMP-EXTEND-MIB::nsExtendObjects
3.高级案例
- 配置trap规则,发送告警信息
注意: ubuntu-snmpd需要修改snmpd进程的启动项,开启mteTrigger和mteTriggerConf功能
mte,Managed Trigger and Event表示管理触发器和事件
使用trapsink或者net-snmp支持的新版指令trapsess,指定trap信息的接受方
# 受控主机配置trapsink
trapsink 127.0.0.1 public # 定义trap信息的接受目的,trapsess 127.0.0.1 public
createuser internalUser SHA-512 myauthphrase AES myprivphrase
rouser internalUser noauth -V systemonly
iquerySecName internalQuery # 指定内部查询使用的安全名称
linkUpDownNotifications yes # 当网卡状态发生变化时,发送trap信息
authtrapenable 1 # snmp身份验证失败的信息发送至服务器
defaultMonitors yes # 启用默认的监控
monitor -r 5 machineTooBusy hrProcessorLoad > 60 # 定义声明一个DisMan监控规则,每5秒检测一次,cpu使用率达到60,触发trap信息
trap告警信息的接受方,使用authCommunity命令配置,运行public密钥的发送端,将接收到的trap信息记录到日志中,运行执行与trap相关联的脚本,允许将trap转发到其它网络位置
authCommunity log,execute,net public
traphandle default /usr/bin/logger -t snmptrap
使用stress工具,在snmptrap主机观测
stress -c 4
Apr 24 14:50:04 zabbix snmptrap: <UNKNOWN>
Apr 24 14:50:04 zabbix snmptrap: UDP: [192.168.5.57]:60176->[192.168.5.59]:162
Apr 24 14:50:04 zabbix snmptrap: DISMAN-EVENT-MIB::sysUpTimeInstance 0:0:01:05.02
Apr 24 14:50:04 zabbix snmptrap: SNMPv2-MIB::snmpTrapOID.0 DISMAN-EVENT-MIB::mteTriggerFired
Apr 24 14:50:04 zabbix snmptrap: DISMAN-EVENT-MIB::mteHotTrigger.0 machineTooBusy
Apr 24 14:50:04 zabbix snmptrap: DISMAN-EVENT-MIB::mteHotTargetName.0
Apr 24 14:50:04 zabbix snmptrap: DISMAN-EVENT-MIB::mteHotContextName.0
Apr 24 14:50:04 zabbix snmptrap: DISMAN-EVENT-MIB::mteHotOID.0 HOST-RESOURCES-MIB::hrProcessorLoad.196609
Apr 24 14:50:04 zabbix snmptrap: DISMAN-EVENT-MIB::mteHotValue.0 100
Apr 24 14:50:04 zabbix snmptrap: SNMP-COMMUNITY-MIB::snmpTrapAddress.0 192.168.5.57
Apr 24 14:50:04 zabbix snmptrap: SNMP-COMMUNITY-MIB::snmpTrapCommunity.0 "public"
Apr 24 14:50:04 zabbix snmptrap: SNMPv2-MIB::snmpTrapEnterprise.0 DISMAN-EVENT-MIB::dismanEventMIBNotificationPrefix
使用snmpinform命令可以发送,inform消息,在未收到对方应答的情况,发送方会重试再次发送,直到消息真正送达。只有snmpv2以上版本支持该消息
createUser -e 0x0102030405 trap MD5 test AES test # 需要详细阅读man 5 snmptrapd.conf
disableAuthorization yes # 尝试多次,增加身份认证的v3版本,均未成功,直接关闭认证
snmpinform -v 3 -u trap localhost 42 SNMPv2-MIB::coldStart
snmptrap -e 0x0102030405 -v 3 -u trap localhost 42 SNMPv2-MIB::coldStart
2025-04-25 03:28:11 <UNKNOWN> [UDP: [192.168.5.57]:42990->[192.168.5.59]:162]:
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (42) 0:00:00.42 SNMPv2-MIB::snmpTrapOID.0 = OID: SNMPv2-MIB::coldStart
配合agentxtrap,可以由外部脚本/子代理手动触发告警信息
实际部署中,一个系统可能有多个子进程负责不同的监控任务,而这些任务希望在检测到异常时发出Trap。但又不希望每个进程都实现完整的SNMP协议,通过AgentX协议,把这些子进程变成snmpd的"子代理",共享OID空间,通过agentxtrap工具向snmpd报告trap,由snmpd统一处理和发送,下图简单展示zabbix从主机192.168.5.57采集的相关数据
- zabbix结合可视化
在zabbix面板中添加主机,比如这里的192.168.5.57该主机运行snmpd服务,选择snmp模板,将其分组至服务器,配置接口为snmp,等待一分钟后,snmp图标绿色表示数据采集成功
