SNMPv3USM 的一篇文章(中文翻译)

原文地址:http://www.insanum.com/docs/usm.html

SNMPv3 - 用户安全模型

这是描述SNMP协议第三版安全特征的两篇文章中的第一篇. SNMPv3 RFCs描述了一个新的框架用于定义SNMP第一,第二和第三版规范之间的关系. 这个框架以模块的方式划分并且绝大部分依赖以前的工作 (例如 SNMPv1, SNMPv2c,SNMPv2u, 和 SNMPv2*).

在这个框架内的两个核心模块是基于用户的安全模型 (USM) 和基于视图的访问控制模型 (VACM). USM 负责 SNMP包的认证/加密/解密, VACM 负责管理MIB数据的访问. 本文概述了 USM, 下个月我们会看一下 VACM.

USM 的规范定义在 RFC 2574. 以前版本的SNMP有一个众所周知的弱点是缺乏一个坚固的, 一致的安全方案. 在设计 USM的时候, 这些典型的安全威胁必须被解决:

    * 信息修改(数据完整性)
     确保数据在传输中没有被未认证的实体恶意修改.

    * 伪装(数据来源认证)
     确保准确的知道数据来自谁以及来自哪里, 防止未认证的实体假装认证用户的身份.

    * 泄露(数据机密性)
     确保未认证的实体不能偷听数据交换.

    * 消息流修改(消息及时性)
     确保数据及时接收, 防止未认证的实体恶意重组数据.

USM 能保护SNMPv3包不受以上威胁, 它利用多用户中每一个用户提供私钥来认证和保证私密性. 指定使用的认证协议是HMAC-MD5 和 HMAC-SHA. 指定的私密性协议是 CBC-DES. RFC指出安全协议在该RFC被制定的时候被认为安全性对于USM是可接受的. 然而, 未来如果有需要模型允许指定新的认证和私密性协议.

概念

SNMPv3 介绍了许多新的概念. 大部分概念被框架中的多个模块用到. 这里是一些USM用到的概念:

    *snmpEngineID
     一个可管理的域名内的一个SNMP引擎的唯一标识. 这个八进制字符串的值不能是0长度, 全为 '0x00'H, 或 全为'0xFF'H. snmpEngineID 通常是由企业数字, IP 或 MAC 地址,以及一个用于管理而分配的字符串组合计算出来的.

    *snmpEngineBoots
     自从snmpEngineID最后一次设定以来SNMP引擎重启或重新初始化的次数. 这个计数器被初始化为0.

    *snmpEngineTime
     自从snmpEngineBoots计数器最后一次增加以来的秒数. 这个计数器被初始化为0. 如果snmpEngineTime达到最大值(2147483647), 那么snmpEngineBoots加一并且snmpEngineTime再次从0开始计数.

    *snmpSecurityLevel
     有三个可能的安全级别: noAuthNoPriv, authNoPriv, 和 authPriv. noAuthNoPriv级别指明了没有认证或私密性被执行. authNoPriv 级别指明了认证被执行但没有私密性被执行. authPriv级别指明了认证和私密性都被执行. noAuthPriv 安全级别不存在的一个原因是需要一个消息认证摘要来确保安全参数的完整性,也就是私密性参数 (例如. DES salt).

    *授权SNMP引擎
     为了保护消息不被重发, 延迟发送, 和重定向, 一个通讯SNMP引擎被设计作为授权SNMP引擎. 授权SNMP引擎负责接收需要响应的SNMP 消息. 它是一个代理并且管理器总是与之通讯.

SNMPv3 包格式

                   SNMPv3 包格式

                 -------------------------
   /|\          |msgVersion           |
              |-----------------------|
              |msgID                |
              |-----------------------|        USM Security Parameters
              |msgMaxSize           |
              |-----------------------|   /-------------------------------
              |msgFlags               / |msgAuthoritativeEngineID   |
scopeof       |-----------------------| / |-----------------------------|
authentication   |msgSecurityModel     | /   |msgAuthoritativeEngineBoots |
              |-----------------------|/   |-----------------------------|
                                      | msgAuthoritativeEngineTime |
              | msgSecurityParameters|    |-----------------------------|
                                      |msgUserName                |
              |-----------------------|\   |-----------------------------|
       /|\                        | \   |msgAuthenticationParameters |
                                | \ |-----------------------------|
                                  \ |msgPrivacyParameters       |
    | scope of |scopedPDU              \-------------------------------
    | encryption|                      |
                                |
                                |
                                |
   \|/   \|/                        |
                 -------------------------

SNMP第三版的包结构为了适应像USM之类的安全模型做了改变.

    *msgVersion
     SNMP版本 (例如 1, 2 或 3).

    *msgID
     msgID 用于协调管理器和代理之间的请求和响应. 响应中的msgID必须和接收到的请求中的msgID相同.

    *msgMaxSize
     msgMaxSize 传递发送者能够从其他SNMP引擎接受的最大消息大小.

    *msgFlags
     msgFlags 是一个单独的八位组用于表示如何处理消息. 例如, msgFlags中的两个位用于指定包是否被认证和是否被加密.

    *msgSecurityModel
     SNMPv3 被设计为使用多个同时存在的安全模型. msgSecurityModel 字段指定了产生消息的安全模型. 因此,接收者知道使用那个安全模型来对接收到的消息执行安全处理.

    *msgSecurityParameters
     msgSecurityParameters 是一个包含安全模型指定数据的八位组字符串. 该数据仅被 msgSecurityModel指定的安全模型定义和使用.

    *scopedPDU
     scopedPDU 包含普通的 PDU 以及为了处理该 PDU 的用于识别唯一上下文的信息.

USM 安全参数

USM 使用 msgSecurityParameters 存放五个值. 这些值被用于认证模块来确保数据完整性和数据源认证,被用于时序模块来保护消息延迟或重传, 以及被用于私密性模块来保护消息不被泄露.

    *msgAuthoritativeEngineID
     授权引擎的snmpEngineID总是放在这个字段内而不管包是由哪一边产生的.

    *msgAuthoritativeEngineBoots
     授权引擎的snmpEngineBoots.

    *msgAuthoritativeEngineTime
     授权引擎的snmpEngineTime.

    *msgUserName
     用户名, 他的私钥将被用于可能的认证和包加密.

    *msgAuthenticationParameters
     如果包是认证过的, 那么这个字段包含计算好的该包的 HMAC-MD5 或 HMAC-SHA 消息摘要.

    *msgPrivacyParameters
     如果包的 scopedPDU 是被加密过的, 那么这个字段包含用于DES算法输入的 salt (例如 随机变量).

代理发现

正如上面提到的, USM 要求授权引擎的 snmpEngineID, snmpEngineBoots, 和snmpEngineTime 被放置在 msgSecurityParameters 中. 这要求未认证引擎 (例如. 管理器)在GET, NEXT, 或 SET操作完成以前为认证引擎 (例如 代理) 准备这些值.

有一个发现过程来达到这个目的. 这里会遇到有两个发现事务. 第一个是发现代理的 snmpEngineID. 第二个是发现snmpEngineBoots 和 snmpEngineTime.管理器仅仅在安全级别为authNoPriv或authPriv时需要第二个事务. 这是因为msgAuthoritativeEngineBoots 和 msgAuthoritativeEngineTime被时序模块使用而该模块只是认证过程的一部分.

第一个发现事务被发送SNMPv3包的管理器初始化, 这个包的msgAuthoritativeEngineID包含一个伪造的值.当代理接收到一个跟它拥有的 msgAuthoritativeEngineID 不同的包, 这个包会被丢弃并且一个发现包被返回给管理器.返回的发现包包含正确的 snmpEngineID, 管理器必须使用这个 snmpEngineID.

第二个发现机制要求一个认证过的包被发送给代理. 这意味着认证标志被设置在 msgFlags, 并且msgAuthenticationParameters 包含计算过的该包的消息摘要. 用于认证该包的私钥来自 msgUserName指定的用户. 当 msgAuthoritativeEngineBoots 和 msgAuthoritativeEngineTime包含伪造的值时这是一个发现包. 当代理接收到这样的包, 首先做认证. 一旦认证完成,msgAuthoritativeEngineBoots 和 msgAuthoritativeEngineTime 值被检查.由于值是伪造的, 该包被丢弃并且第二个发现包被返回给管理器. 返回的发现包是认证过的, 使用相同的用户, 包含正确的snmpEngineBoots 和 snmpEngineTime 值, 管理器必须使用它们.

及时性

一旦管理器得知了代理的 snmpEngineBoots 和 snmpEngineTime, 管理器必须在本地维护这些值应该是多少.这要求管理器每一秒都增加 snmpEngineTime 这样这个值会非常接近代理维护的主值. 如果 snmpEngineTime溢出了, 那么 snmpEngineBoots 必须增加. 管理器必须为每一个它想要与之通讯的代理在本地维护这些值.

代理进行及时性检查被认为是认证过程的一部分并且在接收到的包被认证过之后立刻进行. 如果msgAuthoritativeEngineBoots 跟代理的当前 snmpEngineBoots 值不同,该包被丢弃并且一个发现包被发送回管理器. 如果检查通过, 那么 msgAuthoritativeEngineTime 被用于跟代理的snmpEngineTime 值做检查. 如果两个值的差异多于150秒, 这个包被丢弃并且一个发现包被发送回管理器.如果两个检查都通过, 那么该包被认为被及时接收到并且继续处理.

+/- 150 秒这个用于比较 snmpEngineTime 的值是RFC默认指定.这个值可以根据你的网络的速度和大小进行合适的修改.

认证

USM 指定使用消息摘要5 (MD5) 和安全哈希算法1 (SHA-1) 算法来认证 SNMPv3 包.这些算法用于为可变长度的消息创建唯一固定大小的消息摘要, 也称为消息签名或指纹. MD5 创建 128 位的摘要 (16 字节) 而SHA-1 创建 160 位的摘要 (20 字节). MD5 和 SHA-1都不能直接用于消息认证代码因为他们不使用私钥作为输入来导出计算过的消息摘要. 这就是为什么使用消息认证密钥哈希 (HMAC) 算法跟MD5 和 SHA-1 组合使用来计算消息摘要. HMAC 算法定义了一个过程会在数据中加入私钥然后计算 MD5 或 SHA-1消息摘要. 这保证了要为同样的数据计算等同消息摘要必须共享一个公共的私钥. 这里是发送和接收认证过的 SNMPv3包要采取的步骤:

发送认证的 SNMPv3 包:

   1. 整个包被创建. 认证标志在 msgFlags 上打开,并且 msgAuthenticationParameters 置零.
   2. 使用 msgUserName指定用户的私钥认证密钥为该包计算消息摘要. 使用什么算法(例如 HMAC-MD5 或HMAC-SHA)由用户表中的用户使用的认证协议指定.
   3. 计算过的消息摘要被插入msgAuthenticationParameters.
   4. 包被发送.

接收认证的 SNMPv3 包:

   1. 包被接收.
   2. 如果 msgFlags 中认证标志被打开,继续第三步的认证过程. 如果该包没有被发送者认证, 认证被跳过.
   3. 保存msgAuthenticationParameters.
   4. msgAuthenticationParameters置零.
   5. 使用 msgUserName指定用户的私钥认证密钥为该包计算消息摘要. 使用什么算法(例如 HMAC-MD5 或HMAC-SHA)由用户表中的用户使用的认证协议指定. 如果用户在用户表中不存在那么该包不能被认证并被丢弃.
   6. 比较计算过的消息摘要和之前保存的msgAuthenticationParameters 中的值. 如果不同该包不是认证的并被丢弃. 如果相同,该包是认证的并且可以继续处理.

私密性
USM 指定使用 Cipher Block Chaining mode to the Data Encryption Standard(CBC-DES) 算法来加密和解密 SNMPv3 包. 加密的范围仅仅覆盖包含scopedPDU, 其中包含 PDU和用于VACM的上下文数据. DES 算法接受三个输入. 这些输入是要被加密的数据, 一个 56 位的私钥, 和一个 56位的随机产生的 salt 用于确保两个不同的初始化向量被用于用相同私钥加密的两个输入的不同数据.通讯中使用加密的双方必须共享同一个私钥和 salt 用于推导初始化向量. 私钥存储在用户表, salt 随着包的msgPrivacyParameters 传递. 这里是发送和接收加密包的步骤.

发送加密的 SNMPv3 包:

   1. 整个包被创建, 并且认证和私密性标志在msgFlags 中被打开.
   2. 计算一个随机的 salt 值.
   3. scopedPDU 被使用 salt 和msgUserName 指定的用户的私钥加密.
   4. salt 被插入msgPrivacyParameters.
   5. 如前所述认证该包.
   6. 发送该包.

接收加密的 SNMPv3 包:

   1. 包被接收.
   2. 如果 msgFlags 中认证标志被打开,那么该包必须如前所述进行认证并继续步骤 3. 如果msgFlags中认证标志被关闭那么跳过解密.
   3. 如果msgFlags中私密性标志被打开,那么继续步骤4的解密过程. 如果包未被发送者加密那么跳过解密.
   4.使用msgSecurityParameters中指定的salt和 msgUserName 指定的用户的私钥解密scopedPDU.
   5. 继续处理包.

用户表
每一个代理维护一个用户表用于存储所有能够通过SNMP访问系统的用户. 表中的每一个用户项包含下列信息, 所有这些都可以通过对USMMIB的SNMP操作来修改:

    * 用户名
     人可读的字符串表示用户的名字.

    * 认证协议
     指示代表该用户发送或接收的消息是否认证以及使用哪一个认证协议. 对这个字段当前可以使用的值是: usmNoAuthProtocol,usmHMACMD5AuthProtocol, 以及 usmHMACSHAAuthProtocol.

    * 认证密钥
     用于认证消息的认证协议使用的本地私钥.

    *私密性协议
     指示代表该用户发送或接收的消息是否加密以及使用哪一个私密性协议. 对这个字段当前可以使用的值是: usmNoPrivProtocol和 usmDESPrivProtocol.

    *私密性密钥
     用于加解密消息的私密性协议使用的本地私钥.

用户表有一个相关联的叫做usmUserSpinLock的自旋锁. 自旋锁是一个建议性锁用于允许几个 SNMP 管理器协同尝试修改一个MIB 表. 概念很简单. 任何是有有一个代理要对用户表做修改, 管理器必须通过GET命令获取 usmUserSpinLock 的值.管理器发送SET命令给代理, 其中包含设置 usmUserSpinLock PDU以及用户表中要被修改的变量. SET命令中usmUserSpinLock 的值必须是之前通过GET命令取得的. 一旦代理接收到包含SET命令的消息,usmUserSpinLock 立刻被处理. 如果当前 usmUserSpinLock 的值跟SET命令中的指定的值不一样, SET操作失败并返回错误. 如果两个值相同, SET命令的PDU指定的用户表的变量被设置. 当代理处理完整个PDU,usmUserSpinLock 的值加1. 正如你所见, 如果 usmUserSpinLock 的值跟设置的时候不同,那么用户表从初次获得 usmUserSpinLock 的值以后被修改过.

本地密钥

本地私钥的概念是允许在许多不同的代理对一个用户使用相同的密码. 强迫每个代理为存在的用户记住不同的密码是非常不灵活的.本地密钥通过一个哈希函数(例如 MD5 或 SHA-1)根据一个私有的密码和用户存在的代理的 snmpEngineID 来计算.结果是每个代理的密钥都完全不同, 尽管它们使用了相同的密码.

改变密钥
USM 引入了 KeyChange 类型来描述使用私钥的习惯. KeyChange定义提供了一个安全的方法来通过网络发送本地密钥这样允许用户改变他们的密钥. 当用户要改变他们的密钥时会碰到以下步骤:

管理器:

   1. 用户数一个新密码.
   2. 本地密钥通过新密码和要改变用户密码的代理的snmpEngineID 重新计算.
   3. 一个单向的函数用于从老的密钥产生一个值.
   4. 这个值跟新的密钥异或 (XOR).
   5. 最终的 KeyChange通过一个SET命令发送到代理.

代理: (接收到 KeyChange SET 操作以后)

   1.跟管理器使用的同样的单向函数从老的密钥产生一个值.
   2. 这个值跟接收到的KeyChange异或 (XOR)产生新的密钥.
   3. 新的密钥被设置到用户表.

创建/克隆 用户

在代理的用户表创建一个新的用户是可能的. 这通过克隆一个存在的用户来实现. 所有的数据从被克隆的用户拷贝到新创建用户的项中.一旦新的项被创建, 建议立刻改变密钥. 注意你只能通过克隆另一个已存在的用户来创建新的用户.这要求该代理的用户表必须被初始化为包含你的环境中需要的最小的用户集合.

Using your SNMPv3 manager of choice,这里有个例子关于如何从已存在的名叫foo的用户创建一个新用户并改变密钥. 注意被创建的新用户的实际名字没有显示在这里,因为这个名字由被设置的变量的OID索引指定. 用户表通过用户名来查找.

首先获得自旋锁的值然后创建用户. 为了确保新用户项不能被立刻使用, 设置它的状态为 createAndWait.

    sValue = GET(usmUserSpinLock)
   SET((usmUserSpinLock = sValue),
       (usmUserCloneFrom = foo),
       (usmUserStatus = createAndWait))

下一步, 改变私密性密钥. 注意你必须知道foo的私钥用于计算 KeyChange. privKeyChange值通过被克隆的用户的私钥计算并且新的私钥用于新的用户. 确认使用自旋锁. 同时, usmUserPublic变量可以被写下作为该包用户密钥的过程的一部分, 随后可以读取这个值来确定密钥改变是否完成.

    sValue =GET(usmUserSpinLock)
   SET((usmUserSpinLock = sValue),
       (usmUserPrivKeyChange = privKeyChange),
       (usmUserPublic = randomValue))
    if(randomValue != GET(usmUserPublic)) then try again

如果新用户不再使用加密, 那么你可以设置 privProtocol 为 usmNoPrivProtocol并且不再修改私密性密钥.

    sValue =GET(usmUserSpinLock)
   SET((usmUserSpinLock = sValue),
       (usmUserPrivProtocol = usmNoPrivProtocol))

现在改变认证私钥. 注意你必须知道foo的认证私钥用于计算 KeyChange. authKeyChange值通过被克隆的用户的认证密钥和用于新用户的密钥计算. 再一次确认使用自旋锁.

    sValue =GET(usmUserSpinLock)
   SET((usmUserSpinLock = sValue),
       (usmUserAuthKeyChange = authKeyChange),
       (usmUserPublic = randomValue))
    if(randomValue != GET(usmUserPublic)) then try again

如果新用户不再使用认证, 那么你可以设置 authProtocol 为 usmNoAuthProtocol并且不再改变认证密钥.

    sValue =GET(usmUserSpinLock)
   SET((usmUserSpinLock = sValue),
       (usmUserAuthProtocol = usmNoAuthProtocol))

最后, 通过设置状态激活这个用户.

    sValue =GET(usmUserSpinLock)
   SET((usmUserSpinLock = sValue),
       (usmUserStatus = active))

结论

这个USM的概述应该使你理解SNMPv3包的认证和加密/解密涉及哪些东西. 另外, 你可以开始考虑当你部署支持SNMPv3的路由器,交换机和服务器时如何配置你的环境中的代理. 下个月我将会看一下VACM以及展示它如何用于管理到MIB数据的访问.

参考

    * SNMPv3:RFCs 2570, 2571, 2572, 2573, 2574, 2575
    * SNMP,SNMPv2, SNMPv3, and RMON 1 and 2 (Third Edition) by WilliamStallings. Addison-Wesley Publishing Company.
    *Understanding SNMP MIBs by David Perkins and Evan McGinnis.Prentice Hall PTR.

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值