SNMP 简介

SNMP 简单网络管理协议是目前 TCP/IP 网络中应用最为广泛的网络管理协议。

SNMP,Simple Network Management Protocol,简单网络管理 协议。该协议能够支持网络管理系统,用来监测连接到网络上的设备是否有任何引起管理上关注的情况。它由一组网上管理的标准组成,包含一个应用层协议、数据库模式(database schema),和一组数据对象。

SNMP 广泛应用于网络管理和网络监控,它会将管理数据以变量的形式提供给管理端,即运行于 NMS 上的管理软件。管理软件使用的是 MIB,它描述了系统的状态及配置参数。于是,这些保存在 MIB 中的变量就可以供远程查询,或修改。

NMS:Network Management Station,网络管理节点,即处于网络管理角色的主机。

MIB:Management Information Base。一种数据库,用于在通信网络中管理条目。主要于 SNMP 相关,有时也在 OSI/ISO 网络管理模型的语境中使用。在 SNMP 中,通常是指 MIB 模块。

MIB 数据库是树形的,其中的每个条目用 OID 表示,即 Object IDentifier.

SNMP 的前身是简单网关监控协议,即 SGMP,用来对通信线路进行管理。随后,人们对 SGMP 进行了很大的修改,特别是加入了符合 Internet 定义的 SMI 和 MIB:体系结构,改进后的协议就是著名的 SNMP。SNMP 的目标是管理互联网上众多厂家生产的软硬件平台,因此 SNMP 受互联网标准网络管理框架的影响也很大。SNMP 现已开发到 v3,功能更加丰富。

SNMP 管理网络组成

一个 SNMP 管理网络通常包含三个基本组件:

  • 被管理的设备:受控设备
  • 在被管理设备上运行的软件:Agent,即 SNMP 受控端
  • 在管理端运行的管理软件:SNMP 管理端

被管理的设备

被管理的设备是指一个网络节点,它开放了 SNMP 接口,允许外部对其进行单向(只读)或双向(读写)访问,以读取特定的节点信息。被管理的可以是任何类型的设备,包括但不限于路由器、服务器、交换机、调制解调器、网桥、集线器、IP 电话、PC、打印机等。

受控端

即 agent,为了避免与 proxy 一词混淆,在 SNMP 语境中,本人依然坚持将其译为受控端。

SNMP 受控端了解本机的一些管理信息,它会将其转换为 SNMP 专有的形式。

管理端

这一端的主机会运行特定的应用程序来监控被管理的设备。

SNMP 协议

SNMP 工作于 IP 协议栈的应用层,所有的 SNMP 消息都是通过 UDP 协议传输的。

  • 被动模式:管理端从任意端口发出请求,SNMP 受控端从 UDP 161 端口接收,再将应答消息返回源端口。
  • 主动模式:受控端从任意端口发出通知,管理端从其 UDP 162 端口接收跟踪与请求通知的消息。
  • 如果使用 TLS 或 DTLS:请求从 UDP 10162 端口发出,由 UDP 10161 接收。

TLS:Transport Layer Security;DTLS:Datagram Transport Layer Security

版本历程

SNMP v1

1990 年 5月,RFC1157 定义了 SNMP 的第一个版本 SNMP v1。

RFC1157 和另一个关于管理信息的文件 RFC1155 一起,提供了一种监控和管理计算机网络的系统方法。因此,SNMP 得到了广泛应用,并成为网络管理的事实上的标准。

v1 指定了四种核心协议数据单元(PDU):

  • GET :用来得到一条管理信息
  • GETNEXT :用来反复得到管理信息的序列
  • SET :用来给一个被管理的子系统制造一个变化
  • TRAP :用来报告一个关于被管理子系统的警告或其他异步事件

v1 因其脆弱的安全性而备受争议。客户端的认证使用明码发送。在 80 年代,SNMP 第一版被设计出来的时期,互联网标准的认证/安全并不被主要的协议设计团体所重视。

SNMP v2

SNMP 在 90 年代初得到了迅猛发展,同时也暴露出了明显的不足,例如难以实现大量的数据传输,缺少身份验证和加密机制。因此,1993 年发布了 SNMP v2,具有以下特点:

  • 支持分布式网络管理
  • 扩展了数据类型,可以实现大量数据的同时传输,提高了效率和性能
  • 丰富了故障处理能力
  • 增加了集合处理功能
  • 加强了数据定义语言

SNMP v2(RFC 1441–RFC 1452)修订了 v1,并且包含了在性能、安全、机密性和管理者之间通信这些领域的改进。它引入了 GETBULK 以取代反复的 GETNEXT,借以在单个请求中获取大量的管理数据。然而,SNMP v2 的新安全系统被认为过于复杂,而不被广泛接受。

SNMP v2c(基于社区的 SNMP 第二版)定义于 RFC 1901–RFC 1908,一开始也非正式的被称为 SNMP v1.5。SNMP v2c 包含 SNMP 第二版除了受争议的新 SNMP 第二版安全模型以外的部分,并以 SNMP v1 的简单的基于社区的安全性方案取而代之。

SNMP v2u(基于用户的 SNMP 第二版)定义于 RFC 1909–RFC 1910。这是一个 SNMP v1 和 SNMP v2 的折衷方案,试图提供比 SNMP v1 更好的安全性,又不遭遇 SNMP v2 的高复杂度。这产生了一个被商业化的变种,称为 SNMP v2*,而且它的机制最后被 SNMP v3 的两个安全性框架之一采用。

SNMP v1 和 SNMP v2c 的互操作性

在目前的指定中,SNMP v2 和 SNMP v1 在两个关键领域不兼容:消息格式和协议操作。

SNMP v2c 消息使用和 SNMP v1 不同的标头和 PDU 格式。SNMP v2c 也使用两个未在 SNMP v1 指定的协议操作。

此外,RFC 1908 定义了两个可能的 SNMP v1/v2 共存策略:proxy agents 和双语网上管理系统(bilingual network-management systems)。

SNMP v3

IETF 把在 RFC3411-RFC3418 (STD0062)中定义的 SNMP v3 作为 2004 年的标准版本。IETF 将先前的版本定为 Obsolete 或 Historical。

实际上,SNMP 的实现通常支持多个版本:典型的 SNMP v1、SNMP v2c 以及 SNMP v3。

SNMP v3 提供三项重要的服务:

  • 认证
  • 隐私
  • 访问控制

为了保护通信字符串,SNMP v3 使用 DES(Data Encryption Standard)算法加密数据通信;另外,SNMP v3 还能够用 MD5 和 SHA 技术验证节点的标识符,从而防止攻击者冒充管理节点的身份操作网络。有关 SNMP v3 的详细说明,请参见 http://www.ietf.org/rfc/rfc2570.txt。

主要的 PDU 类型

PDU:Protocol Data Unit,协议数据单元。

SNMP v1 指定了 5 个核心 PDU,SNMP v2 增加了 GetBulkRequest 和 InformRequest,SNMP v3 增加了 Report PDU。

变量绑定:就是将变量的数据通过一定的数据访问技术来和相应的实体捆绑在一起,使之成为一个整体。是数据绑定的一种形式,也是变量访问的一种方法。数据绑定是现代程序设计的基础,很多的应用程序都需要数据作为后台的支持。前台显示的东西都是控件中的内容,而控件本身是没有任何数据的,只是人为的添加了以后才显示出来的。通常可以手动设置显示数据和读取后台数据,读取后台的数据并放到相应控件中显示就成为数据的绑定。数据绑定是现代应用程序具备的基本功能。这样能够给客户提供很好的交互性。例如:在 web 应用程序开发过程中,Gridview 控件的数据基本上都是通过数据绑定来显示的。

GetRequest

由管理端发给受控端,以获取某些变量的值或变量列表,需要获取的变量在变量绑定中指定,当然不会使用变量值字段。获取变量值的过程由受控端以原子方式完成,最终将变量值做为应答返回给管理端。

SetRequest

由管理端发给受控端,以修改某些变量的值或变量列表。请求中指定了变量绑定,对变量的修改由受控端以原子方式完成,最终将修改后的当前变量值做为应答返回给管理端。

GetNextRequest

由管理端发给受控端,尝试发现受控端上可用的变量及其值。在应答中返回变量绑定,按字典顺序返回 MIB 中所有的变量。从 OID 0 开始,通过对 GetNextRequest 的迭代应用,可以在受控端遍历整个 MIB。通过在请求中,为变量指定其字段的 OID,来读取特定的记录。

GetBulkRequest

由管理端发给受控端,请求同时进行多个 GetNextRequest 的迭代。它是 GetNextRequest 的优化版本。在返回的应答消息中包含多个变量绑定。可以使用 PUD 相关的 non-repeatersmax-repetitions 字段,以控制应答的具体行为。由 SNMP v2 引入。

Response

针对管理端的 GetRequest、SetRequest、GetNextRequest、GetBulkRequest、InformRequest 各请求,返回变量绑定及应答。可以通过 error-status 和 error-index 字段提供错误信息。

Trap

由受控端发给管理端的异步通知消息。在被动模式中,由管理端发出请求来查询受控端的信息,无需显式请求,这些 PDU 就会发给管理端。而使用 Trap,受控端则可以主动地把一些特别重要的事件通知给管理端。该 PDU 包含当前的 sysUpTime 值、用于标识 trap 类型的 OID、以及可选的变量绑定。Trap 的目标地址通常由应用程序以特定的方式来判断,大多使用 MIB 中的 trap 配置变量。

InformRequest

该 PDU 为应答的异步通知消息。它是从 v2 引入的,最早用于管理端之间的通信。后期的实现也允许用于受控端与管理端的通信。

管理端与受控端的认证

Community String

在 SNMP v1 和 SNMP v2 中,管理端与受控端通信时,会使用 community string 来建立信任连接,可以将其理解为密码的一种形式。

大多数的受控端都会支持 3 个不同的密码:一个用于 只读,一个用于 读写,一个用于 追踪。 这三个密码用来控制不同类型的活动。

  • 只读密码:用于 get 类型的请求
  • 读写密码:用于 set 类型的请求
  • 追踪密码:用于接收追踪信息

虽然 SNMP v3 也可以使用这种密码,但它更支持安全的身份验证,即使用用户名/密码的方式,同时还会使用一个密钥。

管理端在发送请求时,都会同时附带上这种通信密码。如果密码正确,受控端才会应答,否则会忽略,不予应答。

按照惯例,多数支持 SNMP v1 和 v2c 的设备在出厂时都会将其只读密码设定为 public,因此,做为管理员应该习惯于将所有密码修改为自定义的,以保证初步的安全。

受控端 SNMPD 的配置

snmpd 是受控端的一种,主要用于 Linux 平台。使用时,通常绑定到某个端口,等待管理端的请求。收到请求以后,它会进行处理,收集所请求的信息,进行请求的操作,返回请求的信息。

而对于其他平台的设备如交换机,则有其自己的配置方式,需要查询各自的使用说明。

不同版本的使用

如何判断当前系统使用哪个版本的 SNMP 呢?根本没有这样的命令。snmpd 无法显示版本,一切都取决于如何编辑配置文件中的参数。

  • 默认情况下,如果配置参数中包含 rocommunityrwcommunity,即代表使用 v1 和 v2。
  • 如果不包含,则代表使用 v3,同时 v1 和 v2 的请求将被忽略。
  • 要想让 v3 生效,必须配置用户、密码、加密方法,而不能使用 community string。

通用配置

即 v1 v2 v3 都可以使用的配置参数。

侦听的地址和端口

用于限制 SNMP 绑定到哪个网络接口上。

侦听所有接口

侦听 IPv4 和 IPv6 的所有接口。

agentAddress udp:161,udp6:[::1]:161  
侦听本地
agentAddress  udp:127.0.0.1:161

v1 v2 的配置

内容简单,主要就是配置 commnunity string,以及限定管理端地址范围。

语法:

rocommunity XXXX [default|hostname|network/bits] [oid]
rwcommunity XXXX [default|hostname|network/bits] [oid]

范例:

rocommunity public
rocommunity public localhost
rocommunity secret 10.0.0.0/16
rwcommunity private localhost .1.3.6.1.4.1.42.2.15

v3 的配置

v3 的配置比较复杂,通常需要安装工具包 net-snmp 来辅助操作。

$ sudo yum install net-snmp-utils
创建用户

创建用户时,必须保证 snmpd 没有在运行,所以,如有必要应先将其停止。

$ sudo systemctl stop snmpd
方法一

使用 net-snmp-create-v3-user 工具来创建 SNMP v3 用户。

语法:

net-snmp-create-v3-user [-ro] [-A authpass] [-X privpass] [-a MD5|SHA] [-x DES|AES] [username]

范例:

$ sudo net-snmp-create-v3-user -A my_authpasswd -X my_privpasswd -a SHA -x AES myv3user
$ sudo net-snmp-create-v3-user -ro -A my_authpasswd -X my_privpasswd -a SHA -x AES myv3user

如果使用了 -ro 参数,则创建只读用户;不使用则创建读写用户。

以上命令执行成功后,会把生成的新用户的信息自动添加到 /var/lib/net-snmp/snmpd.conf/etc/snmp/snmpd.conf 这两个配置文件中。

自动生成的配置如下:

com2sec notConfigUser  default       public
group   notConfigGroup v1           notConfigUser
group   notConfigGroup v2c           notConfigUser
view    systemview    included   .1.3.6.1.2.1.1
view    systemview    included   .1.3.6.1.2.1.25.1.1
access  notConfigGroup ""      any       noauth    exact  systemview none none
syslocation Unknown (edit /etc/snmp/snmpd.conf)
syscontact Root <root@localhost> (configure /etc/snmp/snmp.local.conf)
dontLogTCPWrappersConnects yes
rouser myv3user
方法二

使用 net-snmp-create-v3-user交互模式 来创建用户:

$ sudo net-snmp-create-v3-user

Enter a SNMPv3 user name to create:
myv3user
Enter authentication pass-phrase:
myv3password
Enter encryption pass-phrase:
[press return to reuse the authentication pass-phrase]

adding the following line to /var/lib/net-snmp/snmpd.conf:
createUser geekuser MD5 "myv3password" DES
adding the following line to /etc/snmp/snmpd.conf:
rwuser myv3user
方法三

手动修改配置文件。

首先,在 /var/lib/net-snmp/snmpd.conf 中添加一行:

createUser myv3user MD5 "myv3password" DES

然后,在 /etd/snmp/snmpd.conf 中添加一行:

rwuser myv3user
测试

用户创建完毕,可以启动 snmpd 了:

$ sudo systemctl start snmpd

然后可以在本地或异地用 snmpwalk 工具来测试一下,是否能获取到受控端信息:

$ sudo snmpwalk -v3 -u myv3user -l authNoPriv -a MD5 -A myv3password localhost
$ sudo snmpwalk -v3 -u myv3user -l authNoPriv -a MD5 -A myv3password 192.168.1.78
$ sudo snmpwalk -v3 -u myv3user -l authPriv -a SHA -A "myv3password" -x AES -X "myv3password" 192.168.1.79 sysName.0 system.sysUpTime.0

监控范例

常用的监视项目

处理器、存储器、存储设备、网上环境为最常被监视的项目,这些项目的细节信息如下表:

CPU

项目 访问方式 OID MIB
用户占用时间比 GET .1.3.6.1.4.1.2021.11.9.0 UCD-SNMP-MIB::ssCpuUser
系统占用时间比 GET .1.3.6.1.4.1.2021.11.10.0 UCD-SNMP-MIB::ssCpuSystem
闲置时间比 GET .1.3.6.1.4.1.2021.11.11.0 UCD-SNMP-MIB::ssCpuIdle
每个 Core 的用量 WALK .1.3.6.1.2.1.25.3.3.1.2 HOST-RESOURCES-MIB::hrProcessorLoad

存储器

项目 访问方式 OID MIB
存储器容量 GET .1.3.6.1.4.1.2021.4.5.0 UCD-SNMP-MIB::memTotalReal
存储器消耗量 GET .1.3.6.1.4.1.2021.4.6.0 UCD-SNMP-MIB::memAvailReal
存储器剩余量 GET .1.3.6.1.4.1.2021.4.11.0 UCD-SNMP-MIB::memTotalFree
虚拟内存容量 GET .1.3.6.1.4.1.2021.4.3.0 UCD-SNMP-MIB::memTotalSwap
虚拟内存剩余量 GET .1.3.6.1.4.1.2021.4.4.0 UCD-SNMP-MIB::memAvailSwap

存储设备

项目 访问方式 OID MIB
各磁盘容量 WALK .1.3.6.1.4.1.2021.9.1.6.1 UCD-SNMP-MIB::dskTotal
各磁盘消耗量 WALK .1.3.6.1.4.1.2021.9.1.7.1 UCD-SNMP-MIB::dskAvail
各磁盘消耗量百分比 WALK .1.3.6.1.4.1.2021.9.1.9.1 UCD-SNMP-MIB::dskPercent

网上环境

项目 访问方式 OID MIB
网上设备名称 WALK .1.3.6.1.2.1.31.1.1.1.1 IF-MIB::ifName

SNMP v1 v2c

监控指标

  • 监控设备正常运行时间 :sysUpTimeInstance
  • 操作系统版本清单 :sysDescr
  • 收集接口信息 :ifName,ifDescr,ifSpeed,ifType,ifPhysAddr
  • 测量网上接口吞吐量 :ifInOctets,ifOutOctets
  • 查询远程ARP缓存 :ipNetToMedia

输出

下面的输出作为在一个路由器上的snmpwalk的例子展示了设备的基本信息:

 snmpwalk -c public punch system

 SNMPv2-MIB::sysDescr.0 = STRING: Cisco Internetwork Operating System Software IOS (tm) C2600
 Software (C2600-IO3-M), Version 12.2(15)T5, RELEASE SOFTWARE (fc1)
 TAC Support: http://www.cisco.com/tac

 Copyright (c) 1986-2003 by cisco Systems, Inc.

 Compiled Thu 12-Jun-03 15:49 by eaarm
 SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.9.1.187
 DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (835747999) 96 days, 17:31:19.99
 SNMPv2-MIB::sysContact.0 = STRING: wikiuser
 SNMPv2-MIB::sysName.0 = STRING: punch
 SNMPv2-MIB::sysLocation.0 = STRING: test
 SNMPv2-MIB::sysServices.0 = INTEGER: 78
 SNMPv2-MIB::sysORLastChange.0 = Timeticks: (0) 0:00:00.00

SNMP v3

由于 SNMP v3 加强了安全设计,访问上要提供较多信息。

在 Shell 环境下安全获取一台主机所有 CPU 核心使用状况的方法:

$ sudo snmpwalk -v 3 -l authPriv -u user \
                -a SHA -A userpass \
                -x AES -X userpass \
                10.33.1.1 \
                1.3.6.1.2.1.25.3.3.1.26

HOST-RESOURCES-MIB::hrProcessorLoad.196608 = INTEGER: 7
HOST-RESOURCES-MIB::hrProcessorLoad.196609 = INTEGER: 8
  • -l authPriv :要认证,也要传输加密
  • -a :认证密码保护方式
  • -A :认证密码
  • -x :传输加密方式
  • -X :传输密钥
  • 1.3.6.1.2.1.25.3.3.1.2 表示要监视所有 CPU Core 使用状况

常用 SNMP 工具

snmpwalk

SNMP v1

snmpwalk -v1 -c <community> <ipaddress>[:<dest_port>] <oid>
snmpwalk -v1 -c public 127.0.0.1:161 system

SNMP v2

snmpwalk -v2c -c <community> <ipaddress>[:<dest_port>] [oid]
snmpwalk -v2c -c public 127.0.0.1:161 system

SNMP v3

snmpwalk -v3  -l <noAuthNoPriv|authNoPriv|authPriv>
              -u <username>
              [-a <MD5|SHA>]
              [-A <authphrase>]
              [-x DES]
              [-X <privaphrase>]
              <ipaddress>[:<dest_port>]
              [oid]
snmpwalk -v3  -l authPriv
              -u snmpadmin
              -a MD5
              -A PaSSword  
              -x DES
              -X PRIvPassWord
              127.0.0.1:161
              system.sysUpTime.0

参数解释:

-v3 :版本

-u :SNMP 用户名

-l :安全等级

-a :认证协议

-A :身份验证密码

-X :私钥

范例:

对一台 HP 交换机进行 walk:

$ sudo snmpwalk -v 3 -l authPriv -u snmpuser -a MD5 -x AES -A snmpauthpass -X snmprivpass 192.168.0.11 system

SNMPv2-MIB::sysDescr.0 = STRING: HP Comware Platform Software, Software Version 5.20.99 Release 2220P09
HP A5120-48G-PoE+ EI Switch with 2 Interface Slots
Copyright (c) 2010-2013 Hewlett-Packard Development Company, L.P.
SNMPv2-MIB::sysObjectID.0 = OID: SNMPv2-SMI::enterprises.25506.11.1.36
DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (3400412358) 393 days, 13:35:23.58
SNMPv2-MIB::sysContact.0 = STRING: IT ServiceDesk (IT.ServiceDesk@company.com / 000000000)
SNMPv2-MIB::sysName.0 = STRING: CORP-BLDG1-SW-5120
SNMPv2-MIB::sysLocation.0 = STRING: CORP-BLDG1-DATAROOM
SNMPv2-MIB::sysServices.0 = INTEGER: 78

snmpget

$ sudo snmpget -c public -v 2c 192.168.1.29 ifOutOctets.6
IF-MIB::ifOutOctets.6 = Counter32: 5506429

安全考量

即使设备已经支持 SNMP v3,许多厂商使用的还是标准的通信字符串,这些字符串对黑客组织来说根本不是秘密。因此,虽然 SNMP v3 比以前的版本提供了更多的安全特性,如果配置不当,其实际效果仍旧有限。

由于 SNMP 强大的网络管理功能,对于大型网络来说是很有帮助的。为了避免 SNMP 通信时被黑客截获数据而被入侵,有必要对所管理的网络设备进行 SNMP 协议的限制。

由于部分网络设备其 SNMP 默认是开启的,不使用时应该关闭服务。使用的话,应该严格限制其访问权限。

如果某些设备确实有必要运行SNMP,则必须保障这些设备的安全。首先要做的是确定哪些设备正在运行SNMP服务。除非定期对整个网络进行端口扫描,全面掌握各台机器、设备上运行的服务,否则的话,很有可能遗漏一、二个SNMP服务。特别需要注意的是,网络交换机、打印机之类的设备同样也会运行SNMP服务。确定SNMP服务的运行情况后,再采取下面的措施保障服务安全。

更新、打补丁

安装 SNMP 服务的补丁,将 SNMP 服务升级到 v2 或更高。联系设备的制造商,了解有关安全漏洞和升级补丁的情况。

保护 SNMP 通信字符串

一个很重要的保护措施是修改所有默认的通信字符串。根据设备文档的说明,逐一检查、修改各个标准的、非标准的通信字符串,不要遗漏任何一项,必要时可以联系制造商获取详细的说明。

过滤 SNMP

另一个可以采用的保护措施是在网络边界上过滤 SNMP 通信和请求,即在防火墙或边界路由器上,阻塞 SNMP 请求使用的端口。

端口安全

标准的 SNMP 服务使用 161 和 162 端口,厂商私有的实现一般使用 199、391、705 和 1993 端口。禁用这些端口通信后,外部网络访问内部网络的能力就受到了限制。

访问控制

另外,在内部网络的路由器上,应该编写一个 ACL,只允许某个特定的可信任的 SNMP 管理系统操作 SNMP。