一、USM相关网址
SNMPv3使用了基于用户的安全模型USM.
- RFC 3411 Architecture for SNMP Frameworks http://www.ietf.org/rfc/rfc3411.txt
- RFC 3414 User-based Security Model (USM) http://www.ietf.org/rfc/rfc3414.txt
二、SNMP Entity
SNMPv3定义了新的体系结构,并在其中包含了对SNMPv1和SNMPv2c的兼容,即这个新的体系结构也适用于SNMPv1及SNMPv2c,弥补了SNMP没有完整体系结构的缺点。
在SNMPv3中,管理进程与代理统称为SNMP实体(entity)。SNMP实体由SNMP协议引擎(engine)和应用程序(application)组成。SNMP实体包含一系列模块,模块之间相互作用来提供服务。
RFC3411里面定义在一个SNMPv3 entity里面包括以下部分。
- Dispatcher
1个SNMP entity里面只有1个Dispatcher,负责消息的收发。 - Message Processing Subsystem
在SNMP-FRAMEWORK-MIB里面定义了如下几种消息处理模式
SnmpMessageProcessingModel
0 reserved for SNMPv1
1 reserved for SNMPv2c
2 reserved for SNMPv2u and SNMPv2*
3 reserved for SNMPv3 - Security Subsystem
在SNMP-FRAMEWORK-MIB里面定义了如下几种安全模式
SnmpSecurityModel
0 reserved for ‘any’
1 reserved for SNMPv1
2 reserved for SNMPv2c
3 User-Based Security Model (USM)
定义了如下几种安全级别
SnmpSecurityLevel
noAuthNoPriv(1), --无认证无加密
authNoPriv(2), --有认证无加密
authPriv(3) --有认证有加密 - Access Control Subsystem
- Applications包括
- command generators, which monitor and manipulate management data,
- command responders, which provide access to management data,
- notification originators, which initiate asynchronous messages,
- notification receivers, which process asynchronous messages,
- proxy forwarders, which forward messages between entities.
三、SNMP Context
An SNMP context, or just "context" for short, is a collection of management information accessible by an SNMP entity.
An SNMP entity potentially has access to many contexts. The combination of a contextEngineID and a contextName unambiguously identifies a context within an administrative domain.
SNMP context可以看作是管理信息的一个集合。
一个SNMP entity里面可以访问多个SNMP context。
contextEngineID和contextName结合起来识别一个特定的SNMP context。
四、USM
-
Authentication Protocol
支持HMAC-MD5-96 和 HMAC-SHA-96两种认证协议。
*HMAC算法->http://blog.csdn.net/fw0124/article/details/8473858
*HMAC-MD5-96表示HMAC算法使用MD5作为杂凑函数,输出结果使用前96位(MD5输出结果128)。
*HMAC-SHA1-96表示HMAC算法使用SHA1作为杂凑函数,输出结果使用前96位(SHA1输出结果160位)。 -
authKey
用于HMAC认证的用户密钥。
实际上使用的HMAC密钥是此用户密钥和engineID经过计算得出的,这个过程称为localize。 -
Privacy Protocol
支持CBC-DES和CFB-AES两种加密方法。
*分组加密模式->http://blog.csdn.net/fw0124/article/details/8472560
*CBC-DES表示使用CBC加密模式,DES加密算法。
*CFB-AES表示使用CFB加密模式,AES加密算法。 -
privKey
用于加密的用户密钥。
实际上使用的加密密钥是此用户密钥和engineID经过计算得出的,这个过程称为localize。 -
防止消息延迟或者重放攻击/protect against the threat of message delay or replay
-在request里面包含msgID,response里面必须返回这个msgID,否则此reponse会被丢弃。
-在request里面包含engineBoots和engineTime,agent会检查它们是否在150秒的时间窗口内。
*engineBoots表示SNMP engine的reboot次数
*engineTime表示上次reboot之后经过的秒数 -
时间同步/Time Synchronization
Time synchronization, required by a non-authoritative SNMP engine in order to proceed with authentic communications, has occurred when the non-authoritative SNMP engine has obtained a local notion of the authoritative SNMP engine’s values of snmpEngineBoots and snmpEngineTime from the authoritative SNMP engine. These values must be (and remain) within the authoritative SNMP engine’s Time Window. So the local notion of the authoritative SNMP engine’s values must be kept loosely synchronized with the values stored at the authoritative SNMP engine.
In addition to keeping a local copy of snmpEngineBoots and snmpEngineTime from the authoritative SNMP engine, a non-authoritative SNMP engine must also keep one local variable, latestReceivedEngineTime. This value records the highest value of snmpEngineTime that was received by the non-authoritative SNMP engine from the authoritative SNMP engine.
A non-authoritative SNMP engine must keep local notions of these values (snmpEngineBoots, snmpEngineTime and latestReceivedEngineTime) for each authoritative SNMP engine with which it wishes to
communicate. Since each authoritative SNMP engine is uniquely and unambiguously identified by its value of snmpEngineID, the non-authoritative SNMP engine may use this value as a key in order to cache its local notions of these values.(为了防止消息重放,延迟和重定向,每个通信中涉及的SNMP引擎之一被指定为权威SNMP引擎。 当SNMP消息包含期望响应的有效载荷(那些包含确认的类PDU [RFC3411]的消息)时,这样的消息的接收者是权威的。 当SNMP消息包含不期望响应的有效载荷(那些包含未确认类PDU [RFC3411]的消息)时,这样的消息的发送者是权威的。
In order to protect against message replay, delay and redirection,one of the SNMP engines involved in each communication is designated to be the authoritative SNMP engine. When an SNMP message contains a payload which expects a response (those messages that contain a Confirmed Class PDU [RFC3411]), then the receiver of such messages is authoritative. When an SNMP message contains a payload which does not expect a response (those messages that contain an Unconfirmed Class PDU [RFC3411]), then the sender of such a message is authoritative.
权威引擎ID:request及inform消息中此值为接收方引擎id。Trap及response消息中此值为发送方引擎id.)时间同步由non-authoritative SNMP engine发起,以获得authoritative SNMP engine的snmpEngineBoots和snmpEngineTime并存于本地,另外本地还保存latestReceivedEngineTime这个变量,它是最近一次收到authoritative SNMP engine发来的消息中的snmpEngineTime。
对于authoritative SNMP engine,如果收到的消息中包含的engineBoots不等于自身的engineBoots,或者engineBoots相等但是收到的engineTime处于时间窗口外,也就是自身的engineTime+/-150秒之外,就会产生一个notInTimeWindow的错误,并增加usmStatsNotInTimeWindows的统计counter, 然后生成一个包含usmStatsNotInTimeWindows的report返回给调用方。
对于non-authoritative SNMP engine,如果收到的消息中包含的engineBoots大于自身的engineBoots,或者engineBoots相等但是收到的engineTime大于latestReceivedEngineTime,那么需要更新保存于本地的engineBoots, engineTime和latestReceivedEngineTime。如果收到的消息中包含的engineBoots小于自身的engineBoots,或者engineBoots相等但是收到的engineTime小于自身的engineTime-150秒,就会认为这个消息处于时间窗口外。
五、SNMPv3 消息格式
一个SNMPv3的Message包括以下部分:
- msgVersion
- msgID
- msgMaxSize
发送方支持的最大消息长度/the maximum message size supported by a sender of an SNMP message. - msgFlags
8位字段,包含3个flag,最后三位从高到低依次为 reportableFlag, privFlag, authFlag.
reportableFlag如果设置为1,那么如果满足产生report的条件,就会返回一个report给发送方。
所有的request(GET,SET)或者inform,reportableFlag设置为1;Response,Trap,Report中需要设置为0。
privFlag为1表示PDU是加密的。authFlag为1表示PDU是认证的。 - msgSecurityModel
0 reserved for ‘any’
1 reserved for SNMPv1
2 reserved for SNMPv2c
3 User-Based Security Model (USM) - msgAuthoritativeEngineID
- msgAuthoritativeEngineBoots
- msgAuthoritativeEngineTime
- msgUserName
- msgAuthenticationParameters
12个字节的HMAC消息摘要(HMAC-MD5-96 或者 HMAC-SHA-96) - msgPrivacyParameters
用来产生DES加密算法的初始向量(IV)。 - contextEngineID
- contextName
- PDU
包含了实际请求或者应答数据。
12+13+14一起称为scopedPDU
六、SNMPv3发送和接受消息的处理过程
RFC 3414中详细的描述了这个过程。
下载SNMP4J(http://www.snmp4j.org/html/download.html)的源代码,亦可以比较清楚地看到发送和接受消息的处理过程。
- 发送消息
发送消息主要的处理在org.snmp4j.security.USM.generateRequestMessage()中(此函数又调用了generateResponseMessage(),实际上的处理在这个函数中)。- 首先根据请求数据生成平文的PDU,在PDU头上加上contextEngineID和contextName,得到scopedPDU。
- 其次对上面所说的SNMPv3 Message Format的1~14各部分设定相应的值,得到整个消息体,
其中msgAuthenticationParameters的12个字节数据置为全零。 - 再次对scopedPDU部分进行加密。
- 最后使用HMAC算法作用在加密后的整个消息体上,生成12个字节信息摘要,替换msgAuthenticationParameters。
- 接收消息(接受消息和发送相反)
接受消息主要的处理在org.snmp4j.security.USM.processIncomingMsg()中。- 首先把收到的消息体中msgAuthenticationParameters的12个字节数据替换为全零。
- 其次使用HMAC算法作用在替换了msgAuthenticationParameters后的消息体上,生成12个字节信息摘要,把这个信息摘要和原始的msgAuthenticationParameters比较,如果不等,返回错误。
- 最后解密scopedPDU。
- Key Localization
用户的认证(authKey)和加密密码(privKey)不会直接使用。
对于同一个用户的密码,通过Key Localization,用于不同的authoritative SNMP engine的密钥实际上是不一样的。
对于认证密码,Key Localization的过程如下:
org.snmp4j.security.AuthGeneric.passwordToKey(OctetString passwordString, byte[] engineID)
a) 使用用户密码重复填充1个64字节块,使用此64字节块重复填充得到1M字节的数据,
b) 使用认证算法(MD5/SHA1)作用于上面得到的1M字节的数据,得到的摘要为Ku
c) 在snmp engine id的前后加上Ku, 然后再次使用认证算法(MD5/SHA1),得到的摘要即为localized key: Kul
加密密码的处理过程如下:
org.snmp4j.security.SecurityProtocols.passwordToKey(OID privProtocolID, OID authProtocolID, OctetString passwordString, byte[] engineID)
authProtocolID和privProtocolID分别是当前用户的Authentication Protocol和Privacy Protocol.
a) 根据authProtocolID得到当前的AuthenticationProtocol
b) 调用org.snmp4j.security.AuthGeneric.passwordToKey(passwordString, engineID),实际上就是上面认证密码的Key Localization过程。
c) 根据privProtocolID得到加密算法,比较加密算法要求的密钥最小/最大长度和上面得到的localized privKey的长度,
如果过长截断,如果过短,调用privProtocol.extendShortKey()方法延长。 - 认证
org.snmp4j.security.AuthGeneric.authenticate(byte[] authenticationKey, byte[] message, int messageOffset , int messageLength, ByteArrayWindow digest)
认证实际上就是根据HMAC计算消息摘要(digest)的过程。
传入的authenticationKey就是localized authKey.
计算摘要的过程见HMAC算法->http://blog.csdn.net/fw0124/article/details/8473858
注意只使用计算得到摘要的前12个字节(96位) - 加密解密
CBC-DES加密的处理在函数
org.snmp4j.security.PrivDES.encrypt(byte[] unencryptedData, int offset, int length, byte[] encryptionKey, long engineBoots, long engineTime, DecryptParams decryptParams)
里面。
参数encryptionKey就是16字节的localized privKey, 它的前8个字节用来作为DES key, 因为DES只使用56 bits,每个字节的最低位实际上被丢弃。
The first 8 octets of the 16-octet secret (private privacy key) are used as a DES key. Since DES uses only 56 bits, the Least Significant Bit in each octet is disregarded.
CBC模式需要一个64 bit的IV(Initialization Vector)。
encryptionKey的后8个字节用作pre-IV。
为了让每个packet能有不同的IV, 需要对pre-IV进行salt。
使用32-bit的snmpEngineBoots和一个32-bit的随机数一起产生一个64-bit(8字节)的salt。
salt的前4个字节是32-bit的snmpEngineBoots,后4个字节是32-bit的随机数。
然后salt和pre-IV进行异或运算得到IV, IV=salt XOR pre-IV。
最后salt放入msgPrivacyParameters字段发送给接受方用来产生正确的IV进行解密。
解密的处理在函数org.snmp4j.security.PrivDES.decrypt(byte[], int, int, byte[], long, long, DecryptParams)里面。
七、参考网址
参考链接