摘要

  • RFC 3014 为 SNMP Trap 和 Inform 建立本地通知日志,使管理应用能在异步通知未能送达后重新读取原始变量绑定。
  • 这份日志从来不是完整事实档案:过滤器、访问控制、全局与单日志容量、自动过期、资源压力、重启以及其他管理器都可能改变它。
  • 已记录与已丢弃计数、单调索引和 sysUpTime 断点能够揭示一部分缺口,却不能还原从未准入或已经删除的内容。

网络设备主动发出一条告警,与管理系统最终得到这条告警,并不是同一件事。Trap 可以在途中消失;Inform 虽有确认和重传,也会在重传次数耗尽后停下。等到管理应用下一次轮询,短暂的异常可能已经结束,通知本身也不再存在。

2000 年 11 月以建议标准发布的 RFC 3014 为此定义 Notification Log MIB。它让设备在本地保存 SNMP 通知,作为对丢失 Trap 或 Inform 的补救。应用可以稍后轮询日志,从上次读取的位置继续,并利用保存下来的变量绑定重建 Notification PDU。

这并不是简单地“多存一份”。从那一刻起,同一个管理事件有了两条证据路径:一条异步发送给接收者,另一条留在设备一侧等待读取。如果第一条路径失败,第二条可能提供补偿;但第二条也有自己的准入、保管与失效规则。

RFC 3014 把结构分成配置、统计与日志三部分。配置决定记录什么、能留多少;统计说明写入和丢弃了多少;日志只保存最终存活的通知。这个顺序很重要。人们看到的日志不是设备经历的一切,而是经过配置与资源约束后剩下的集合。

首先是过滤。命名日志引用 SNMP Notification MIB 中的过滤器。规范中的示例只接纳 linkUp 和 linkDown。若某类通知未被选中,它不会进入这份日志。之后的查询即使返回零,也只能说明在该过滤视图里没有保留下来的记录,不能说明其他类型的通知或底层事件从未出现。

访问控制进一步收窄视图。命名日志保留创建者的安全凭据。对于本地产生的通知,系统在写入前必须按通知发起者的规则判断创建者能否访问其中对象。资源有限的设备可以只提供空名称的默认日志;默认日志没有与创建者绑定的隐含准入凭据。

因此,同一台设备上的两个合法观察者可能看到不同历史。差异未必是篡改,也可能是各自过滤器与权限的必然结果。“日志是否完整”必须带上日志名、过滤器、创建者权限、SNMP 引擎和管理上下文,脱离这些坐标便没有可验证含义。

来源坐标也不能省略。一个系统可运行多个彼此独立的 SNMP 引擎;同一引擎又可容纳多个相交或分离的管理上下文。RFC 3014 记录通知来源的引擎标识和上下文名称。没有这些字段,一条 linkDown 并不能准确指出哪一个管理世界里的哪一项状态发生了变化。

第二道边界是容量。nlmConfigGlobalEntryLimit 控制所有日志合计可留的通知条目;nlmConfigLogEntryLimit 控制单一命名日志;nlmConfigGlobalAgeOut 指定条目应保留多少分钟。配置为零可以表示不设该项限制,却不等于设备获得无限内存。

规范明确说明,一个上限值并不保证设备真能保存那么多数据。实际资源不足时,为给新条目腾出空间,最老的记录可以被移除。单日志超过自己的上限时,它自己的最老记录也可以被逐出。配置描述政策,资源决定实际执行面。

全局上限的权力更强。如果一个管理应用把全局容量调低,系统必须删除最老条目直到符合新值。即使这些条目尚未达到过期时间,而且其所在日志也未达到自己的上限,它们仍要让位。一次看似普通的配置更改,实际上缩短了所有观察者的证据窗口。

RFC 3014 甚至写出了管理器之间的冲突。多个应用可能争相设置不同上限;其中一个应用可以在另一个应用读取前让通知被删除,从而影响后者所见数据的可靠性和完整性。规范把这种行为认作可能的拒绝服务攻击,并将对策留待后续研究。

于是,用来弥补不可靠通知路径的日志,本身也有一个可攻击的控制面。通知可能在网络上传丢;也可能被过滤器拒之门外;已经写入的记录可能被容量逐出;仍在保留期内的记录可能因新上限提前消失;管理子系统重启还会改变索引与时间的纪元。每种缺口需要不同解释。

统计计数器正是为了让部分差异可见。RFC 3014 分别统计全局和单日志的已记录通知与已丢弃通知。丢弃计数持续上升,说明现存行并非完整历史,容量或资源压力正在损失证据。

但是,计数器不是被删除的通知。它可以说明某一计数纪元内发生过丢弃,却不能恢复被删条目的通知标识、变量绑定和业务意义。十条丢失记录可能只是重复链路抖动,也可能包含服务中断前唯一一次温度或电源警报。数字无法替内容作证。

每个日志条目还拥有在该命名日志内单调递增的索引。采集器可以记住自己读过的最高索引,下次从那里继续。它还必须检查 sysUpTime 是否出现不连续,因为管理系统初始化会重置索引,也可能带走条目。

连续索引回答的是一个很窄的问题:在当前管理纪元和现存行之中,采集器是否沿序列前进。它不能证明所有通知都通过过滤与权限检查,也不能证明资源充足,更不能证明条目在轮询前没有被逐出。索引出现洞可能暴露丢失;索引没有洞却无法暴露从未准入的东西。

重启让证据纪元变得更清楚。条目是否跨管理系统初始化保留,完全取决于实现;规范说通常不应期待它们会留下。若实现真的保留旧条目,以 sysUpTime 为基础的时间戳会混淆,所以重启前条目的 nlmLogTime 必须设为零。内容也许幸存,原来的相对时间坐标却已经死亡。

本地日历时间同样只是条件性字段:只有具备日期时间能力的系统才实例化它。相对启动时间、本地日历与递增索引是三种不同坐标。跨重启、调钟和多引擎场景,没有任何一个字段能独立给出完整可信的顺序。

对真正保留下来的通知,RFC 3014 在表示层很精确。每个变量绑定按通知索引和变量索引存入,具体值由对应的 SNMP 数据类型对象承载。应用由此可以重建 Notification PDU。这份回执有明确意义:这些字段确实存在于日志所保存的消息中。

它仍不证明消息描述的现实。代理可能误判底层状态;远端通知可能缺少可靠认证;上下文也可能被解释错误。日志忠实保存一个协议声明,并不会把声明提升为物理故障、用户影响或已完成修复。

读取也不是处置。一套监控系统成功取回 linkDown 记录,可以证明那一行已被读到;它不能证明值班人员注意到它、关联了正确接口、开立事件、取得变更授权、恢复服务并从用户侧确认结果。

周边 SNMP 框架后来继续演进。RFC 1905 给出 SNMPv2 协议操作与 InformRequest 背景;RFC 3014 所依赖的 RFC 2573 应用框架和 RFC 2575 视图访问控制,后来分别由 RFC 3413 与 RFC 3415 取代。框架换代没有消除日志准入与读取必须分别举证的事实。

后来的规范继续把 Notification Log 当作通用基础设施。RFC 3877 的 Alarm MIB 可以从告警历史指向适用的通知日志条目;RFC 5676 的 SYSLOG-MSG-MIB 则用它把 syslog 消息映射到 SNMP 管理对象。这证明设计具有复用价值,不证明每个设备都部署了它,更不证明日志完整或事故已经处理。

用 Lu Heng 的“最小初始规范”观察,RFC 3014 的优点在于只统一必需的公共语言:配置、计数、来源坐标、索引和类型值。具体保留容量仍由本地实施者决定。共同层没有假装能够替每个设备分配内存或替每个组织确定取证周期。

但本地决定必须接受运行事实检验。“Running-Code Primacy”要求观察过滤器是否真的生效、条目是否准入、容量是否被改变、计数纪元是否连续、采集器是否真的读取。MIB 定义只能证明协议对象已经发布,不能证明某台运行设备完成了这些动作。

“Reality Layers”则阻止我们把记录和现实合并。事件条件、通知生成、日志准入、条目留存、采集读取、人员解释、授权行动和服务结果,分别属于不同证据层。它们可以互相链接,却不能互相冒充。

RFC 3014 最有生命力的历史贡献,不只是“把告警存下来”。它承认备份证据也有过滤器、所有者、配额和纪元。当通知路径失败时,日志可能补回消息;当日志本身丢失记录时,计数和断点或许能留下缺口的轮廓。再往后,负责任的系统必须明确说出自己已经不知道什么。

来源