Linux: Snmp
- TAGS: Linux
SNMP 简单网络管理协议
网络管理系统:监控(监视并控制)网络中各种设备的运行状态。
SNMP,Simple Network Management Protocol,简单网络管理协议,用于网络设备的管理。
SNMP是一组协议标准,包括三个部分——管理信息库(MIB)、管理信息结构(SMI)和管理通信协议(SNMP)。
管理信息库(MIB)给出了管理对象的具体定义。
SNMP发展过程中一个重要的补充是 RMON,Remote Monitor,远程监控。
SNMPv1 版本的缺陷是 :SNMPv1只提供简单的共同体名认证,安全措施很弱。
BER,Basic Encoding Rules,基本编码规则,用于对SNMP数据类型进行编码。
SNMP管理模型
网络管理的四个层次。 网元/网络/服务/商务 管理层。
由三部分组成,管理者(Manager)、管理代理(Agent)、管理信息库(MIB)。
SMI,Structure of Management Information,管理信息结构,用来规定管理信息库的定义。
SMI对一个管理对象的描述包括三个部分——名字、语法和编码。
抽象语法表示
ASN.1,Abstract Syntax Notation 1。描述了一种对数据进行表示、编码、传输和解码的数据格式。
ASN.1有四种类型:简单类型、结构类型、标签类型、其他类型。
安装
# 安装net-snmp wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo yum install net-snmp -y cd /etc/snmp/ cp snmpd.conf snmpd.conf.bak cat snmpd.conf.bak |grep -vE '^$|^#' > snmpd.conf cat >/etc/snmp/snmpd.conf<<\EOF com2sec notConfigUser default public group notConfigGroup v1 notConfigUser group notConfigGroup v2c notConfigUser view all included .1 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 all none none 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 EOF systemctl start snmpd yum -y install net-snmp-utils
RHEL5, 6 使用 snmpd 时, 默认启动服务只监听 127.0.0.1:199
可通过下面方法更改监听需求
vi /etc/snmp/snmpd.conf smuxsocket 0.0.0.0:199
检查
snmpwalk -v 2c -c flt123 192.168.2.250 hrSWRunPerfMem|sed '/: 0 KB/d'|cut -d " " -f4|awk '{s+=$1}END{print s}' 对程序占用内存相加求和 (py3) [root@rabbitmq01 ~]# snmpwalk -v 2c -c public localhost 1.3.6.1.2.1 |grep ifDescr IF-MIB::ifDescr.1 = STRING: lo IF-MIB::ifDescr.2 = STRING: eth0 (py3) [root@rabbitmq01 ~]# snmpwalk -v 2c -c flt123 localhost 1.3.6.1.2.1|cut -d ":" -f1 >s (py3) [root@rabbitmq01 ~]# cat s|wc -l 3928 (py3) [root@rabbitmq01 ~]# cat s |sort -u |uniq DISMAN-EVENT-MIB EtherLike-MIB HOST-RESOURCES-MIB IF-MIB IP-FORWARD-MIB IP-MIB IPV6-MIB MTA-MIB NOTIFICATION-LOG-MIB RMON-MIB SCTP-MIB SNMPv2-MIB SNMPv2-SMI TCP-MIB UDP-MIB
HOST-RESOURCES-MIB主要包括:
- hrSystem:主要包括系统启动时间、当前进程数、最大支持进程数等等。
- hrstorage:主要包括物理内存大小,各个分区、虚拟内存的大小和使用情况
- hrdevice:硬件设备情况、每个cpu的负载情况等
- hrswrun:操作系统类型的标志、进程列表(进程的状态、名字、路径、参数等)
- hrSWRunPerf:每个进程占用的内存、以及占用的CPU时间(累计)
- hrSWinstalled:系统安装的软件信息
HOST-RESOURCES-MIB::hrSWRunStatus.8171 = INTEGER: running(1) HOST-RESOURCES-MIB::hrSWRunStatus.8332 = INTEGER: runnable(2) HOST-RESOURCES-MIB::hrSWInstalledName.250 = STRING: "net-snmp-libs-5.5-49.el6_5.4" HOST-RESOURCES-MIB::hrSWInstalledType.250 = INTEGER: application(4) HOST-RESOURCES-MIB::hrSWInstalledDate.250 = STRING: 2014-10-14,10:1:21.0,+8:0
RFC1213-MIB主要包括(跟服务器相关的):
- .iso.org.dod.internet.mgmt.mib-2.udp.udpTable:服务器上的UDP端口占用情况。
- .iso.org.dod.internet.mgmt.mib-2.tcp.tcpConnTable:服务器上的TCP连接情况
UCD-SNMP-MIB主要包括: 1.3.6.1.4.1.2021 在linux系统里
- 2021.4 memory
- 2021.10 laTable 负载
- 2021.11 systemStats
- 2021.100 version
- 2021.101 snmperrs
Statistics for MIB UCD-SNMP-MIB:
Objects: 171 | OIDS: 162 | Object Groups: 0 |
Traps: 0 | Notifications: 2 | Notification Groups: 0 |
Tables: 7 | Tabulars: 63 | Scalars/Other: 90 |
(py3) [root@rabbitmq01 ~]# snmpd -v NET-SNMP version: 5.7.2 Web: http://www.net-snmp.org/ Email: net-snmp-coders@lists.sourceforge.net (py3) [root@rabbitmq01 ~]# snmpwalk -v 2c -O n -c public localhost 1.3.6.1.2.1.system # 检查snmp是否正确 (py3) [root@rabbitmq01 ~]# snmptranslate -Tp .1 # 列出整MIB树结构 (py3) [root@rabbitmq01 ~]# snmptranslate -On -IR system #(-On表示以数字格式输出,-IR表示随机访问MIB .1.3.6.1.2.1.1 (py3) [root@rabbitmq01 ~]# snmptranslate -Onf -IR system #(-f表示列出名称型的OID) .iso.org.dod.internet.mgmt.mib-2.system (py3) [root@rabbitmq01 ~]# snmptranslate -Tl|more # 字符加数字形式 (py3) [root@rabbitmq01 ~]# snmptranslate -Ts|more 字符形式 (py3) [root@rabbitmq01 ~]# snmptranslate -To|more 数字形式 (py3) [root@rabbitmq01 ~]# snmptranslate -Tt|more 层次形式 (py3) [root@rabbitmq01 ~]# snmptranslate -Ta|more dump DEFINITIONS ::= BEGIN org OBJECT IDENTIFIER ::= { iso 3 } dod OBJECT IDENTIFIER ::= { org 6 } (py3) [root@rabbitmq01 ~]# snmptranslate -Tp 1.3.6.1.2.1.3 +--at(3) | +--atTable(1) | +--atEntry(1) | Index: atIfIndex, atNetAddress | +-- -RW- INTEGER atIfIndex(1) +-- -RW- String atPhysAddress(2) (py3) [root@rabbitmq01 ~]# snmptranslate -Tz |more "org" "1.3" "dod" "1.3.6" "internet" "1.3.6.1" "directory" "1.3.6.1.1" "mgmt" "1.3.6.1.2" "mib-2" "1.3.6.1.2.1" 测试topsec防火墙的mib (py3) [root@rabbitmq01 ~]# snmpwalk -v 2c -c public localhost interface IF-MIB::ifNumber.0 = INTEGER: 2 IF-MIB::ifIndex.1 = INTEGER: 1 IF-MIB::ifIndex.2 = INTEGER: 2 IF-MIB::ifDescr.1 = STRING: lo IF-MIB::ifDescr.2 = STRING: eth0 (py3) [root@rabbitmq01 ~]# snmpwalk -v 2c -c public localhost 1.3.6.1.4.1 (py3) [root@rabbitmq01 ~]# snmptranslate -Tp 1.3.6.1.4.1 |more +--enterprises(1) | +--ucdavis(2021)
net-snmp配置文件详解
net-snmp的配置文件是有一定的层次结构的,配置起来也很方便。网上找了很多资料,大概把这个配置文件的各个信息搞懂了一点。其实在net-snmp的EXAMPLE.conf文件中对齐有详细的描述,不过是英文的。
开启子代理模式
开发net-snmp子代理后,如果想要使用它,必须开启子代理功能。如果不开启,子代理运行的时候将会报错 Warning: Failed to connect to the agentx master agent ([NIL])
设置snmpd监听的地址端口
snmpd默认是监听本地所有的IP地址的 UDP 161端口 等待snmp请求。如果不希望使用默认的监听设置,可以使用自定义的选项
# Listen for connections from the local system only # 只监听本地的连接 agentAddress udp:127.0.0.1:161 # Listen for connections on all interfaces (both IPv4 *and* IPv6) # 监听所有接口的连接 #agentAddress udp:161,udp6:[::1]:161
主要4步骤
1. 定义安全体名和共同体名称
共同体这个是SNMPv2中的,如果只是使用SNMPv3协议,可以不需要。
rocommunity 共同体名
rwcommunity 共同体名
使用 rocommunity 来定义一个只读权限的共同体,使用 rwcommunity 来定义一个读写权限的共同体。
定义完共同体之后就要定义一个安全体,并把共同体映射到一个安全体中去。安全体用于控制外部访问的来源的。
使用com2sec关键字来定义安全体。
#第一步,定义安全体名称,将一个共同体映射到一个安全体名称里: #sec.name: 安全体名称 #source:可以访问的ip地址范围,默认值"default”,即任何ip都可以访问。 #community:共同体名称 # # sec.name souce community com2sec read default public com2sec write default public com2sec test default public # 1. com2sec # 命令格式一:com2sec [-Cn context] sec.name source community # 功能: map an SNMPv1 or SNMPv2c community string to a security name,即将实体(community)字符串映射为安全的 # 名字,v1 和v2版本都是明文密码,也就无所谓安全性了。v3中增加了安全性。 # 参数说明:-Cn context:可选的,在v3版本中使用 # sec.name: 内部映射的名字,字符串,后面用到 # community:实体字符串,外部使用的名字 # source:可以访问的ip地址范围,默认值"default”,即任何ip都可以访问。 # 也可以限制ip范围,有两种方式:IP/MASK和IP/BITS # IP/MASK:10.10.10.0/255.255.255.0 # IP/BITS :10.10.10.0/24:只有ip地址在10.10.10.0 # mask为24个1,即255.255.255.0 # 命令格式二:com2sec6 [-Cn context] sec.name source community # 针对ipv6,其他和com2sec相同 # 命令格式三:com2secunix [-Cn context] sec.name sockpath community # 只限本地socket可以访问 #------------------------------------------------------------------------ #因为SNMPv3已经使用usm作为安全模型,使用,去掉共同体定义。 #com2sec 是net-snmp中定义安全体名字的关键字,表示这一行定义一个安全体名字。
2. 定义安全组
定义完安全体之后,就要定义安全组了。安全体是用于控制访问的的来源的,安全组就是控制安全体中允许的来源的访问授权模式的。
#com2sec 是net-snmp中定义安全体名字的关键字,表示这一行定义一个安全体名字。 #第二步,定义安全组,将安全体名称加进一个安全组中 # #groupName 安全组名称 #securityModel 安全模型,可选值:v1,v2c,usm #securityName 安全体名称 # groupName securityModel securityName group readgroup usm read group writegroup usm write group testgroup usm test #group是定义安全组的关键字 # 2. group # 命令格式:group groupName securityModel sec.name # 功能:将sec.name映射到一个group中,组中具有相同的存取权限。组中至少有两个 # sec.name,如果只有一个sec.name,也会被解释为两个。即有两个相同的 # 参数说明:groupName:组名 # securityModel:v1、v2c、usm、tsm、ksm其一
3. 定义视图,供安全组使用
定义完安全组后,需要定义一个视图。视图就是这个安全体的可见范围。
对于每一个安全体,需要向其授权一些视图,视图确定了可以访问那些节点。
#第三步,定义视图,供安全组使用 #view.name 视图名 #incl/excl 对下面的MIB子树是包括还是排除(included/excluded) #subtree 视图中所涉及的mib子树 #mask(optional) 掩码 # view.name incl/excl subtree [mask] view all included .1 view test included system view test included system.sysLocation #view if2 included .1.3.6.1.2.1.2.2.1.0.2 FFA0 # 此处定义的就是VACM中的视图子树和掩码,配置将出现在VACM相关表中。 # 此处对网络接口2定义了一个视图,将来作为一个独立的context,mask参见VACM。 # view 是定义视图的关键字 #这里 all,范围是 .1。 # 3. view # 命令格式:view viewName type oid[mask] # 功能:定义一个view,表示整个OID树的子树,同一个子树可以定义多个view # 参数说明: viewName:view名字 # type:有两个值:include 和 exclude # oid:可以访问的oid # [mask]:对oid的mask # 例如:view all include 1.3.6.1.2.1.4 0xf0 # 0xf0:1111 0000,即访问的oid的前4位必须是1.3.6.1,否则不能访问,即 # 可以访问1.3.6.1下所有的子oid
4. 向安全组授权相应的视图
#第四步,向安全组授权相应的视图 # group 安全组名 # context 上下文v1,v2中始终为空 # sec.model 安全模型,可选值:v1,v2,usm # sec.level 安全级别 可选值:auth,noauth,priv, v1,v2c中只能为noauth # prefix 前缀。指定context如何与PDU中的context匹配,V3使用 # read 授权的读视图 # write 授权的写视图 # notif 授权的trap视图 # group context sec.model sec.level prefix read write notif access readgroup "" any noauth exact all none none access writegroup "" any noauth exact all none none access testgroup "" any noauth exact all none none #acess readgroup "interface2" usm priv exact if2 if2 if2 # 4. access # 命令格式:access groupName context model level prefx read write notify # 功能:设置访问某一个view的存取权限 # 参数说明: groupName:控制存取权限的组名 # context:v1和v2c版本,context必须设置为"" # model:v1、v2c、usm、tsm、ksm # 最后3中是v3版本的授权模式,usm(User-Based Security Model)是默认授权模式,tsm用于SSH or DTLS,ksm用于支持Kerberos # level:可以去3种值:noauth、auth、priv # noauth:允许无权限访问(v1,v2c使用) # auth:必须有权限才能访问 # priv:强制加密访问 # prefx:exact or prefix # read、write、notify:指明某一个view的权限是否可以GET*, SET*、 # TRAP/INFORM,如果该view不能read,则置none
5. 添加用户(仅限SNMPv3)
SNMPv3使用了用户加密鉴权的认证方式,所以需要创建相关的用户。这里也可以用net-snmp-config –create-snmpv3-user来实现。
创建用户使用createUser关键字来进行。后面的参数依次是用户名、验证方式、验证码、加密方式、加密码
创建的用户需要指明用户的权限,使用关键字rouser和rwuser来操作。
rouser用于指定用户的权限为只读,如果后面加上priv来指明需要加密。可以使用auth来指明需要认证。
rwuser用于指定用户的权限为读写,其他的与上面一致。
# 第五步,添加用户 # user 验证方式 验证码 加密方式 加密码 createUser fx MD5 "md5123456" DES "des123456" createUser fxr MD5 "md5123456" #用户的权限设置 rwuser fx priv #读写用户,用户名fx,指明需要加密 rouser fxr #只读用户 #rouser [-s SECMODEL] USER [noauth|auth|priv [OID | -V VIEW [CONTEXT]]] #rwuser [-s SECMODEL] USER [noauth|auth|priv [OID | -V VIEW [CONTEXT]]]
SNMP Trap发送目的地设置
以上都是对SNMP代理程序的外部请求的相关设置。SNMP代理还有一个重要的功能就是主动向网管端发送“通知”。
对此需要指定网关端的目的地址。
使用snmpsink来指定发送SNMPv1版本的Trap的目的地址和共同体名称
使用snmp2sink来指定发送SNMPv2版本的Trap的目的地址和共同体名称
使用informasink来指定发送INFORMs的目的地址和共同体名称
使用trappsess来指定发送SNMPv3版本的Trap的相关信息。其中引擎ID和用户名,验证方式,验证码等都必须和接收trap的网关软件端设置的一致。
# 发送 SNMPv1 traps trapsink localhost public # 发送 SNMPv2c traps trap2sink localhost public # 发送 SNMPv2c INFORMs informsink localhost public # 发送SNMPv3 traps #trapsess -v 2 -u 用户名 -e 引擎ID -a 验证方式 -A 验证码 -l 鉴权方式 目的IP trapsess -v 3 -u myuser -e 0x010203040506 -a MD5 -A 111111111 -l authNoPriv 192.168.1.108
范例: 配合使用cloudforse 的snmpd.conf配置
[root@datanode03 snmp]# vim snmpd.conf #第一步,定义安全体名称,将一个共同体映射到一个安全体名称里: #com2sec 是net-snmp中定义安全体名字的关键字,表示这一行定义一个安全体名字。 #sec.name: 安全体名称 #source:可以访问的ip地址范围,默认值"default”,即任何ip都可以访问。 #community:共同体名称 # # sec.name souce community com2sec cici 10.161.212.216 public com2sec cici 114.215.191.163 public com2sec cici 10.161.171.134 public #第二步,定义安全组,将安全体名称加进一个安全组中 #groupName 安全组名称 #securityModel 安全模型,可选值:v1,v2c,usm #securityName 安全体名称 # # groupName securityModel securityName group ciciGroup v1 cici group ciciGroup v2c cici #第三步,定义视图,供安全组使用 #view.name 视图名 #incl/excl 对下面的MIB子树是包括还是排除(included/excluded) #subtree 视图中所涉及的mib子树 #mask(optional) 掩码 # view.name incl/excl subtree [mask] view systemview included .1.3.6.1.2.1.1 view systemview included .1.3.6.1.2.1.25.1.1 view systemview included .1.3.6.1.2.1.2 view all included .1 80 #第四步,向安全组授权相应的视图 #group 安全组名 #context 上下文v1,v2中始终为空 #sec.model 安全模型,可选值:v1,v2,usm #sec.level 安全级别 可选值:auth,noauth,priv, v1,v2c中只能为noauth #prefix 前缀。指定context如何与PDU中的context匹配,V3使用 #read 授权的读视图 #write 授权的写视图 #notif 授权的trap视图 # group context sec.model sec.level prefix read write notif access ciciGroup "" any noauth exact all none none view all included .1 syslocation Unknown (edit /etc/snmp/snmpd.conf) syscontact Root <root@localhost> (configure /etc/snmp/snmp.local.conf) dontLogTCPWrappersConnects yes [root@datanode03 snmp]# systemctl start snmpd 我们需要一个测试,验证 SNMP 配置的正确性。在监控主机中执行以下命令: yum -y install net-snmp-utils snmpwalk参数选项: –h:显示帮助。 –v:指定snmp的版本, 1或者2c或者3。 –c:指定连接设备SNMP密码。团体名 –V:显示当前snmpwalk命令行版本。 –r:指定重试次数,默认为0次。 –t:指定每次请求的等待超时时间,单为秒,默认为3秒。 –l:指定安全级别:noAuthNoPriv|authNoPriv|authPriv。 –a:验证协议:MD5|SHA。只有-l指定为authNoPriv或authPriv时才需要。 –A:验证字符串。只有-l指定为authNoPriv或authPriv时才需要。 –x:加密协议:DES。只有-l指定为authPriv时才需要。 –X:加密字符串。只有-l指定为authPriv时才需要。 snmpwalk使用方法很简单,如下: snmpwalk -v 1或2c(代表SNMP版本) -c SNMP密码 IP地址 OID(对象标示符) –v:指定snmp的版本, 1或者2,该参数必须有。 –c:指定连接设备SNMP读密码,该参数必须有。 IP:指定要walk的设备的IP地址,该参数必须有。 OID:代表要获取设备的指标oid,该参数不是必须的。 http://www.net-snmp.org/docs/mibs/ip.html https://www.cnblogs.com/createyuan/p/3997228.html [root@rabbit-hd-212216 ~]# snmpwalk -v 1 10.46.72.199 -c public system SNMPv2-MIB::sysDescr.0 = STRING: Linux datanode03 3.10.0-327.22.2.el7.x86_64 #1 SMP Thu Jun 23 17:05:11 UTC 2016 x86_64 SNMPv2-MIB::sysObjectID.0 = OID: NET-SNMP-MIB::netSnmpAgentOIDs.10 DISMAN-EVENT-MIB::sysUpTimeInstance = Timeticks: (382) 0:00:03.82 SNMPv2-MIB::sysContact.0 = STRING: Root <root@localhost> (configure /etc/snmp/snmp.local.conf) SNMPv2-MIB::sysName.0 = STRING: datanode03 。。。。。。。。。。。。。。。。。。 [root@rabbit-hd-212216 ~]# 上述信息说明 SNMP 已经正常工作了。
自定义脚本
现在我们在目标主机上来写一些脚本来获取 Memory、CPU、DiskIO 等状态。
Memory 脚本:
#!/bin/sh /usr/bin/free -m | grep Mem |awk '{print $4}' /usr/bin/free -m | grep Mem |awk '{print $2}' [root@chenyi ~]# sh memory.sh 809 1006
CPU 脚本:
#!/bin/sh idle=`sar -u 1 3 | grep Average | awk '{print $6}'` used=`echo "101 - $idle" | bc -l -s` echo $used echo $idle
Disk I/O 脚本:
#!/bin/sh used1=`sar -d 1 3 | tail -1 | awk '{print $4}'` used2=`echo "$used1 / 2" | bc -l` echo $used2 echo $used2
现在我们已经能得到这数据了,怎么才能让监控主机通过 snmpd 得到这些数据呢?可以在目标主机的/etc/snmp/snmpd.conf文件中加入这些配置:
exec .1.3.6.1.4.1.2021.53 memory /bin/sh /root/memory.sh exec .1.3.6.1.4.1.2021.54 cpu /bin/sh /root/cpu.sh exec .1.3.6.1.4.1.2021.55 disk /bin/sh /root/disk.sh [root@chenyi ~]# service snmpd restart 停止 snmpd: [确定] 正在启动 snmpd: [确定]
这样在监控主机上运行:
[root@chenyi ~]# snmpwalk -v 1 192.168.1.220 -c public .1.3.6.1.4.1.2021.53 UCD-SNMP-MIB::ucdavis.53.1.1 = INTEGER: 1 UCD-SNMP-MIB::ucdavis.53.2.1 = STRING: "memory" UCD-SNMP-MIB::ucdavis.53.3.1 = STRING: "/bin/sh /root/memory.sh" UCD-SNMP-MIB::ucdavis.53.100.1 = INTEGER: 0 UCD-SNMP-MIB::ucdavis.53.101.1 = STRING: "442" UCD-SNMP-MIB::ucdavis.53.101.2 = STRING: "1006" UCD-SNMP-MIB::ucdavis.53.102.1 = INTEGER: 0
其中UCD-SNMP-MIB::ucdavis.53.101.1 = STRING: "442"中的 442 就是 mem.sh 输出的第一个数据,1006 是 mem.sh 输出的第二个数据。
[root@chenyi ~]# snmpwalk -v 1 192.168.1.220 -c public .1.3.6.1.4.1.2021.53 | grep 53.101 | awk -F\" '{print $2}' 443 1006
我们已经通过 snmpd 从监控主机上得到了目标主机上内存使用状态的两个参数,其它脚本也是一样的。
来个配置
#定义一个使用 community 'myCommunity' 和源网络 172.17.1.0/24 的用户 'myUser' com2sec myUser 172.17.1.0/24 myCommunity #将 myUser 加到 'myGroup' 组,定义组权限 group myGroup v1 myUser group myGroup v2c myUser view all included .1 access myGroup "" any noauth exact all all none