snmp

what

SNMP是英文Simple Network Management Protocol的缩写,中文意思是简单网络管理协议。SNMP是一种简单网络管理协议,它属于TCP/IP五层协议中的应用层协议。 SNMP主要用于网络设备的管理(服务器、工作站、路由器、交换机及HUBS等)。它由一组网络管理的标准组成,包含一个应用层协议(application layer protocol)、数据库模式(database schema),和一组数据对象

install in Ubuntu

apt install

1
apt-get install snmpd snmp snmp-mibs-downloader
  • snmpd:snmp服务端软件
  • snmp:snmp客户端软件
  • snmp-mibs-downloader:用来下载更新本地mib库的软件 安装过程中,程序会帮我们自动下载mib库,并保存在/usr/share/mibs目录中 download-mibs 手动下载

SNMPv2 config

配置目录

1
cd /etc/snmp

重启服务

1
2
3
4
service snmpd restart

# 遍历所有mib
snmpwalk -v 2c -c public localhost

snmpd.conf 服务端

获取更多的节点信息

1
2
3
4
5
6
# 注释
view  systemonly  included  .1.3.6.1.2.1.1
view  systemonly  included  .1.3.6.1.2.1.25.1

# 新增
view  systemonly  included  .1

修改v2密码

默认密码为public

1
2
3
4
5
6
# 改
rocommunity public  default    -V systemonly
rocommunity6 public  default  -V systemonly

rocommunity passwdYouWant  default    -V systemonly
rocommunity6 passwdYouWant  default  -V systemonly

允许远程

默认端口是161

1
2
3
4
# 改
agentAddress  udp:127.0.0.1:161

agentAddress udp:161,udp6:[::1]:161

查看效果

1
2
3
4
netstat -antup | grep 161

udp        0      0 0.0.0.0:161            0.0.0.0:*                          11656/snmpd   
udp6      0      0 ::1:161                :::*                                11656/snmpd

客户端

snmp.conf

获取相关节点信息更直观oid -On 显示oid

1
2
# 注释
mibs :
1
service snmp restart

SNMPv3

SNMPv3在SNMP的基础之上增强了安全性以及远程配置功能。

最初,SNMP最大的缺点就是安全性弱。SNMP的第一与第二个版本中,身份验证仅仅是在管理员与代理间传送一个明文的密码而已。目前每一个SNMPv3的信息都包含了被编码成8进制的安全参数。这些安全参数的具体意义由所选用的安全模型决定。

SNMPv3提供了重要的安全特性:

  • 保密性 —— 加密数据包以防止未经授权的源监听。
  • 完整性 —— 数据的完整性特性确保数据在传输的时候没有被干扰,并且包含了可选的数据响应保护机制。
  • 身份验证 —— 检查数据是否来自一个合法的源。
1
2
3
4
5
6
7
vim /etc/default/snmpd

改
SNMPDOPTS='-Lsd -Lf /dev/null -u snmp -g snmp -I -smux,mteTrigger,mteTriggerConf -p /var/run/snmpd.pid'

SNMPDOPTS='-Lsd -Lf /dev/null -u snmp -I -smux -p /var/run/snmpd.pid -c /etc/snmp/snmpd.conf'

SNMPv3有多种不同的用途。 noauth —— 没有授权,加密以及任何安全保护! auth —— 需要身份认证,但是不对通过网络发送的数据进行加密。 priv —— 最可靠模式。需要身份认证而且数据会被加密。

1
2
3
4
5
6
7
8
9
10
vim /etc/snmp/snmpd.conf

#
createUser user1
createUser user2 MD5 user2password
createUser user3 MD5 user3password DES user3encryption
#
rouser user1 noauth 1.3.6.1.2.1.1
rouser user2 auth 1.3.6.1.2.1
rwuser user3 priv 1.3.6.1.2.1

MIB OID

管理信息库MIB 有点像分级目录的结构。不同厂商的设备会有自己的mib

OID(对象标识符),是SNMP代理提供的具有唯一标识的键值。MIB(管理信息基)提供数字化OID到可读文本的映射

使用实例

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import (
	"errors"
	"math/big"
	"regexp"
	"strings"
	"time"

	g "github.com/soniah/gosnmp"
)


func parseIpTable(name string) (ipTable IpTableT) {
	name = strings.Replace(name, ipCidrRouteDest, "", -1)
	ipReg := `(\.[0-9]{1,3}){4}`
	reg := regexp.MustCompile(ipReg)
	res := reg.FindAllString(name, -1)
	ipTable = IpTableT{
		Dest:    strings.TrimLeft(res[0], "."),
		Mask:    strings.TrimLeft(res[1], "."),
		Gateway: strings.TrimLeft(res[2], "."),
	}
	return
}

func snmp2Client(target string, port uint16, password string) *g.GoSNMP {
	g.Default.Target = target
	g.Default.Port = port
	g.Default.Community = password
	g.Default.Timeout = timeOut
	g.Default.Retries = retries
	return g.Default
}

func getMsgFlags(parameters *g.UsmSecurityParameters) g.SnmpV3MsgFlags {
	if parameters.AuthenticationProtocol == g.NoAuth {
		return g.NoAuthNoPriv
	} else if parameters.AuthenticationProtocol != g.NoAuth && parameters.PrivacyProtocol == g.NoPriv {
		return g.AuthNoPriv
	}
	return g.AuthPriv
}
func userSec(user string, authProto uint8, authPasswd string, privProto uint8, privPasswd string) *g.UsmSecurityParameters {
	return &g.UsmSecurityParameters{
		UserName:                 user,
		AuthenticationProtocol:   authProtocol[authProto],
		AuthenticationPassphrase: authPasswd,
		PrivacyProtocol:          privProtocol[privProto],
		PrivacyPassphrase:        privPasswd,
	}
}

func snmp3Client(target string, port uint16, parameters *g.UsmSecurityParameters) *g.GoSNMP {
	client := &g.GoSNMP{
		Target:             target,
		Port:               port,
		Version:            g.Version3,
		Timeout:            timeOut,
		SecurityModel:      g.UserSecurityModel,
		MsgFlags:           getMsgFlags(parameters),
		SecurityParameters: parameters,
	}
	return client
}

func snmpGet(client *g.GoSNMP) (SnmpResultT, error) {
	var result = SnmpResultT{
		Alive: false,
	}
	err := client.Connect()
	if err != nil {
		log.Errorf("connect error %s:%s %s", client.Target, client.Port, err)
		return result, ConnectError
	}
	defer client.Conn.Close()
	res, err := client.Get(oid)
	if err != nil {
		log.Errorf("get error %s:%s %s", client.Target, client.Port, err)
		return result, GetError
	}
	result.Alive = true
	for _, variable := range res.Variables {
		if variable.Name == systemRunTime {
			result.SystemRunTime = g.ToBigInt(variable.Value)
		} else if variable.Name == ipSystemStatsOutRequestsIpv4 {
			result.Out = g.ToBigInt(variable.Value)
		} else if variable.Name == ipSystemStatsInDeliversIpv4 {
			result.In = g.ToBigInt(variable.Value)
		}
	}
	return result, nil
}

func snmpWalk(client *g.GoSNMP) ([]IpTableT, error) {
	err := client.Connect()
	if err != nil {
		log.Errorf("connect error %s:%s %s", client.Target, client.Port, err)
		return nil, ConnectError
	}
	defer client.Conn.Close()

	results, err := client.BulkWalkAll(ipCidrRouteDest)
	if err != nil {
		log.Errorf("walk error %s:%s %s", client.Target, client.Port, err)
		return nil, GetError
	}
	var res []IpTableT
	for _, r := range results {
		res = append(res, parseIpTable(r.Name))
	}
	return res, nil
}

func Snmp2(target string, port uint16, password string) (SnmpResultT, error) {
	client := snmp2Client(target, port, password)
	getResult, err := snmpGet(client)
	if err != nil {
		return getResult, err
	}
	ipRoute, err := snmpWalk(client)
	if err != nil {
		return getResult, err
	}

	getResult.IpRoute = ipRoute
	return getResult, nil
}
func Snmp3(target string, port uint16, user string, authProto uint8, authPasswd string, privProto uint8, privPasswd string) (SnmpResultT, error) {
	userParam := userSec(user, authProto, authPasswd, privProto, privPasswd)
	client := snmp3Client(target, port, userParam)
	getResult, err := snmpGet(client)
	if err != nil {
		return getResult, err
	}
	ipRoute, err := snmpWalk(client)
	if err != nil {
		return getResult, err
	}

	getResult.IpRoute = ipRoute
	return getResult, nil
}

func Snmp(s *model.SnmpDevice) (SnmpResultT, error) {
	if s.Proto == V2 {
		return Snmp2(s.Ip, s.Port, s.Community)
	}
	return Snmp3(s.Ip, s.Port, s.UserName, s.AuthProto, s.AuthPassword, s.PrivateProto, s.PrivatePassword)
}