Internet Engineering Task Force (IETF)                        T. Kivinen
Request for Comments: 5879                               AuthenTec, Inc.
Category: Informational                                      D. McDonald
ISSN: 2070-1721                                       Oracle Corporation
                                                                May 2010
        
Internet Engineering Task Force (IETF)                        T. Kivinen
Request for Comments: 5879                               AuthenTec, Inc.
Category: Informational                                      D. McDonald
ISSN: 2070-1721                                       Oracle Corporation
                                                                May 2010
        

Heuristics for Detecting ESP-NULL Packets

检测ESP-NULL数据包的启发式算法

Abstract

摘要

This document describes a set of heuristics for distinguishing IPsec ESP-NULL (Encapsulating Security Payload without encryption) packets from encrypted ESP packets. These heuristics can be used on intermediate devices, like traffic analyzers, and deep-inspection engines, to quickly decide whether or not a given packet flow is encrypted, i.e., whether or not it can be inspected. Use of these heuristics does not require any changes made on existing IPsec hosts that are compliant with RFC 4303.

本文档描述了一组用于区分IPsec ESP-NULL(封装安全有效负载而不加密)数据包和加密ESP数据包的启发式方法。这些启发式算法可用于中间设备,如流量分析器和深度检查引擎,以快速确定给定数据包流是否加密,即是否可以检查。使用这些启发式不需要对符合RFC 4303的现有IPsec主机进行任何更改。

Status of This Memo

关于下段备忘

This document is not an Internet Standards Track specification; it is published for informational purposes.

本文件不是互联网标准跟踪规范;它是为了提供信息而发布的。

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Not all documents approved by the IESG are a candidate for any level of Internet Standard; see Section 2 of RFC 5741.

本文件是互联网工程任务组(IETF)的产品。它代表了IETF社区的共识。它已经接受了公众审查,并已被互联网工程指导小组(IESG)批准出版。并非IESG批准的所有文件都适用于任何级别的互联网标准;见RFC 5741第2节。

Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc5879.

有关本文件当前状态、任何勘误表以及如何提供反馈的信息,请访问http://www.rfc-editor.org/info/rfc5879.

Copyright Notice

版权公告

Copyright (c) 2010 IETF Trust and the persons identified as the document authors. All rights reserved.

版权所有(c)2010 IETF信托基金和确定为文件作者的人员。版权所有。

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

本文件受BCP 78和IETF信托有关IETF文件的法律规定的约束(http://trustee.ietf.org/license-info)自本文件出版之日起生效。请仔细阅读这些文件,因为它们描述了您对本文件的权利和限制。从本文件中提取的代码组件必须包括信托法律条款第4.e节中所述的简化BSD许可证文本,并提供简化BSD许可证中所述的无担保。

Table of Contents

目录

   1. Introduction ....................................................3
      1.1. Applicability: Heuristic Traffic Inspection and
           Wrapped ESP ................................................4
      1.2. Terminology ................................................4
   2. Other Options ...................................................5
      2.1. AH .........................................................5
      2.2. Mandating by Policy ........................................6
      2.3. Modifying ESP ..............................................6
   3. Description of Heuristics .......................................6
   4. IPsec Flows .....................................................7
   5. Deep-Inspection Engine ..........................................9
   6. Special and Error Cases .........................................9
   7. UDP Encapsulation ..............................................10
   8. Heuristic Checks ...............................................10
      8.1. ESP-NULL Format ...........................................11
      8.2. Self Describing Padding Check .............................12
      8.3. Protocol Checks ...........................................14
           8.3.1. TCP Checks .........................................15
           8.3.2. UDP Checks .........................................16
           8.3.3. ICMP Checks ........................................16
           8.3.4. SCTP Checks ........................................17
           8.3.5. IPv4 and IPv6 Tunnel Checks ........................17
   9. Security Considerations ........................................17
   10. References ....................................................18
      10.1. Normative References .....................................18
      10.2. Informative References ...................................18
   Appendix A.  Example Pseudocode ...................................20
     A.1.  Fastpath ..................................................20
     A.2.  Slowpath ..................................................23
        
   1. Introduction ....................................................3
      1.1. Applicability: Heuristic Traffic Inspection and
           Wrapped ESP ................................................4
      1.2. Terminology ................................................4
   2. Other Options ...................................................5
      2.1. AH .........................................................5
      2.2. Mandating by Policy ........................................6
      2.3. Modifying ESP ..............................................6
   3. Description of Heuristics .......................................6
   4. IPsec Flows .....................................................7
   5. Deep-Inspection Engine ..........................................9
   6. Special and Error Cases .........................................9
   7. UDP Encapsulation ..............................................10
   8. Heuristic Checks ...............................................10
      8.1. ESP-NULL Format ...........................................11
      8.2. Self Describing Padding Check .............................12
      8.3. Protocol Checks ...........................................14
           8.3.1. TCP Checks .........................................15
           8.3.2. UDP Checks .........................................16
           8.3.3. ICMP Checks ........................................16
           8.3.4. SCTP Checks ........................................17
           8.3.5. IPv4 and IPv6 Tunnel Checks ........................17
   9. Security Considerations ........................................17
   10. References ....................................................18
      10.1. Normative References .....................................18
      10.2. Informative References ...................................18
   Appendix A.  Example Pseudocode ...................................20
     A.1.  Fastpath ..................................................20
     A.2.  Slowpath ..................................................23
        
1. Introduction
1. 介绍

The ESP (Encapsulating Security Payload [RFC4303]) protocol can be used with NULL encryption [RFC2410] to provide authentication, integrity protection, and optionally replay detection, but without confidentiality. ESP without encryption (referred to as ESP-NULL) offers similar properties to IPsec's AH (Authentication Header [RFC4302]). One reason to use ESP-NULL instead of AH is that AH cannot be used if there are NAT (Network Address Translation) devices on the path. With AH, it would be easy to detect packets that have only authentication and integrity protection, as AH has its own protocol number and deterministic packet length. With ESP-NULL, such detection is nondeterministic, in spite of the base ESP packet format being fixed.

ESP(封装安全有效负载[RFC4303])协议可与空加密[RFC2410]一起使用,以提供身份验证、完整性保护和可选的重播检测,但无需保密。无加密的ESP(称为ESP-NULL)提供与IPsec的AH(身份验证头[RFC4302])类似的属性。使用ESP-NULL而不是AH的一个原因是,如果路径上有NAT(网络地址转换)设备,就不能使用AH。使用AH,很容易检测到只有身份验证和完整性保护的数据包,因为AH有自己的协议号和确定的数据包长度。对于ESP-NULL,这种检测是不确定的,尽管基本ESP数据包格式是固定的。

In some cases, intermediate devices would like to detect ESP-NULL packets so they could perform deep inspection or enforce access control. This kind of deep inspection includes virus detection, spam filtering, and intrusion detection. As end nodes might be able to bypass those checks by using encrypted ESP instead of ESP-NULL, these kinds of scenarios also require very specific policies to forbid such circumvention.

在某些情况下,中间设备希望检测ESP-NULL数据包,以便执行深入检查或实施访问控制。这种深度检查包括病毒检测、垃圾邮件过滤和入侵检测。由于终端节点可以通过使用加密的ESP而不是ESP-NULL绕过这些检查,因此此类场景还需要非常具体的策略来禁止此类规避。

These sorts of policy requirements usually mean that the whole network needs to be controlled, i.e., under the same administrative domain. Such setups are usually limited to inside the network of one enterprise or organization, and encryption is not used as the network is considered safe enough from eavesdroppers.

这些策略要求通常意味着需要控制整个网络,即在同一管理域下。这种设置通常仅限于一个企业或组织的网络内部,并且由于网络被认为足够安全,不会被窃听,因此不使用加密。

Because the traffic inspected is usually host-to-host traffic inside one organization, that usually means transport mode IPsec is used. Note, that most of the current uses of IPsec are not host-to-host traffic inside one organization, but for the intended use cases for the heuristics, this will most likely be the case. Also, the tunnel mode case is much easier to solve than transport mode as it is much easier to detect the IP header inside the ESP-NULL packet.

因为被检查的流量通常是一个组织内的主机对主机流量,这通常意味着使用传输模式IPsec。请注意,IPsec的大多数当前用途不是一个组织内部的主机到主机通信,但对于启发式的预期用途,最有可能是这种情况。此外,隧道模式的情况比传输模式更容易解决,因为它更容易检测ESP-NULL数据包内的IP报头。

It should also be noted that even if new protocol modifications for ESP support easier detection of ESP-NULL in the future, this document will aid in the transition of older end-systems. That way, a solution can be implemented immediately, and not after 5-10 years of upgrade and deployment. Even with protocol modification for end nodes, the intermediate devices will need heuristics until they can assume that those protocol modifications can be found from all the end devices. To make sure that any solution does not break in the future, it would be best if such heuristics are documented -- i.e.,

还应注意,即使ESP的新协议修改支持将来更容易检测ESP-NULL,本文档也将有助于旧终端系统的转换。这样,解决方案就可以立即实施,而不是在升级和部署5-10年之后。即使对终端节点进行协议修改,中间设备也将需要启发式,直到它们能够假设可以从所有终端设备中找到这些协议修改。为确保任何解决方案在未来不会中断,最好记录此类启发式方法,即。,

publishing an RFC for what to do now, even though there might be a new protocol coming in the future that will solve the same problem in a better way.

发布RFC以了解现在要做的事情,即使将来可能会有一个新的协议以更好的方式解决同样的问题。

1.1. Applicability: Heuristic Traffic Inspection and Wrapped ESP
1.1. 适用性:启发式交通检查和电子稳定程序

There are two ways to enable intermediate security devices to distinguish between encrypted and unencrypted ESP traffic:

有两种方法可使中间安全设备区分加密和未加密的ESP流量:

o The heuristics approach has the intermediate node inspect the unchanged ESP traffic, to determine with extremely high probability whether or not the traffic stream is encrypted.

o 启发式方法让中间节点检查未更改的ESP流量,以极高的概率确定流量流是否加密。

o The Wrapped ESP (WESP) approach [RFC5840], in contrast, requires the ESP endpoints to be modified to support the new protocol. WESP allows the intermediate node to distinguish encrypted and unencrypted traffic deterministically, using a simpler implementation for the intermediate node.

o 相反,包装ESP(WESP)方法[RFC5840]要求修改ESP端点以支持新协议。WESP允许中间节点使用更简单的中间节点实现来确定地区分加密和未加密的流量。

Both approaches are being documented simultaneously by the IPsecME Working Group, with WESP being put on Standards Track while the heuristics approach is being published as an Informational RFC. While endpoints are being modified to adopt WESP, both approaches will likely coexist for years, because the heuristic approach is needed to inspect traffic where at least one of the endpoints has not been modified. In other words, intermediate nodes are expected to support both approaches in order to achieve good security and performance during the transition period.

IPsecME工作组同时记录了这两种方法,WESP被纳入标准轨道,而启发式方法作为信息RFC发布。虽然正在修改端点以采用WESP,但这两种方法可能会共存多年,因为在至少一个端点未被修改的情况下,需要使用启发式方法来检查流量。换句话说,期望中间节点支持这两种方法,以便在过渡期间实现良好的安全性和性能。

1.2. Terminology
1.2. 术语

This document uses following terminology:

本文件使用以下术语:

Flow

A TCP/UDP or IPsec flow is a stream of packets that are part of the same TCP/UDP or IPsec stream, i.e., TCP or UDP flow is a stream of packets having same 5 tuple (source and destination IP and port, and TCP/UDP protocol). Note, that this kind of flow is also called microflow in some documents.

TCP/UDP或IPsec流是属于相同TCP/UDP或IPsec流的数据包流,即TCP或UDP流是具有相同5元组(源和目标IP和端口,以及TCP/UDP协议)的数据包流。请注意,在某些文档中,这种流也称为微流。

Flow Cache

流缓存

deep-inspection engines and similar devices use a cache of flows going through the device, and that cache keeps state of all flows going through the device.

深度检查引擎和类似设备使用流经设备的流缓存,该缓存保持流经设备的所有流的状态。

IPsec Flow

IPsec流

An IPsec flow is a stream of packets sharing the same source IP, destination IP, protocol (ESP/AH), and Security Parameter Index (SPI). Strictly speaking, the source IP does not need to be a part of the flow identification, but it can be. For this reason, it is safer to assume that the source IP is always part of the flow identification.

IPsec流是共享相同源IP、目标IP、协议(ESP/AH)和安全参数索引(SPI)的数据包流。严格来说,源IP不需要成为流标识的一部分,但可以。因此,更安全的做法是假设源IP始终是流标识的一部分。

2. Other Options
2. 其他选择

This document will discuss the heuristic approach of detecting ESP-NULL packets. There are some other options that can be used, and this section will briefly discuss them.

本文将讨论检测ESP-NULL数据包的启发式方法。还可以使用其他一些选项,本节将简要讨论这些选项。

2.1. AH
2.1. 啊

The most logical approach would use the already defined protocol that offers authentication and integrity protection, but not confidentiality, namely AH. AH traffic is clearly marked as not encrypted, and can always be inspected by intermediate devices.

最合乎逻辑的方法是使用已经定义的协议,该协议提供身份验证和完整性保护,但不提供机密性,即AH。AH流量清楚地标记为未加密,并且始终可以由中间设备进行检查。

Using AH has two problems. First, as it also protects the IP headers, it will also protect against NATs on the path; thus, it will not work if there is a NAT on the path between end nodes. In some environments this might not be a problem, but some environments, include heavy use of NATs even inside the internal network of the enterprise or organization. NAT-Traversal (NAT-T, [RFC3948]) could be extended to support AH also, and the early versions of the NAT-T proposals did include that, but it was left out as it was not seen as necessary.

使用AH有两个问题。首先,由于它还可以保护IP头,因此它还可以防止路径上的NAT;因此,如果在终端节点之间的路径上存在NAT,则它将不起作用。在某些环境中,这可能不是问题,但在某些环境中,甚至在企业或组织的内部网络中也大量使用NAT。NAT遍历(NAT-T,[RFC3948])也可以扩展以支持AH,并且NAT-T提案的早期版本确实包括了这一点,但由于认为没有必要,因此被忽略了。

Another problem is that in the new IPsec Architecture [RFC4301] the support for AH is now optional, meaning not all implementations support it. ESP-NULL has been defined to be mandatory to implement by "Cryptographic Algorithm Implementation Requirements for Encapsulating Security Payload (ESP) and Authentication Header (AH)" [RFC4835].

另一个问题是,在新的IPsec体系结构[RFC4301]中,对AH的支持现在是可选的,这意味着并非所有实现都支持AH。“封装安全有效负载(ESP)和身份验证头(AH)的加密算法实现要求”将ESP-NULL定义为强制实现[RFC4835]。

AH also has quite complex processing rules compared to ESP when calculating the Integrity Check Value (ICV), including things like zeroing out mutable fields. Also, as AH is not as widely used as ESP, the AH support is not as well tested in the interoperability events.

与ESP相比,AH在计算完整性检查值(ICV)时具有相当复杂的处理规则,包括将可变字段归零等。此外,由于AH的使用不如ESP广泛,AH支持在互操作性事件中没有得到很好的测试。

2.2. Mandating by Policy
2.2. 政策授权

Another easy way to solve this problem is to mandate the use of ESP-NULL with common parameters within an entire organization. This either removes the need for heuristics (if no ESP-encrypted traffic is allowed at all) or simplifies them considerably (only one set of parameters needs to be inspected, e.g., everybody in the organization who is using ESP-NULL must use HMAC-SHA-1-96 as their integrity algorithm). This does work unless one of a pair of communicating machines is not under the same administrative domain as the deep-inspection engine. (IPsec Security Associations (SAs) must be satisfactory to all communicating parties, so only one communicating peer needs to have a sufficiently narrow policy.) Also, such a solution might require some kind of centralized policy management to make sure everybody in an administrative domain uses the same policy, and that changes to that single policy can be coordinated throughout the administrative domain.

解决此问题的另一个简单方法是强制在整个组织内使用带有公共参数的ESP-NULL。这要么消除了对启发式的需求(如果根本不允许ESP加密流量),要么大大简化了它们(只需要检查一组参数,例如,组织中使用ESP-NULL的每个人都必须使用HMAC-SHA-1-96作为其完整性算法)。除非一对通信机器中的一台与深度检查引擎不在同一管理域下,否则这是可行的。(IPsec安全关联(SA)必须满足所有通信方的要求,因此只有一个通信对等方需要具有足够窄的策略。)此外,这种解决方案可能需要某种集中的策略管理,以确保管理域中的每个人都使用相同的策略,对单一政策的改变可以在整个行政领域内协调。

2.3. Modifying ESP
2.3. 修改ESP

Several documents discuss ways of modifying ESP to offer intermediate devices information about an ESP packet's use of NULL encryption. The following methods have been discussed: adding an IP-option, adding a new IP-protocol number plus an extra header [RFC5840], adding new IP-protocol numbers that tell the ESP-NULL parameters [AUTH-ONLY-ESP], reserving an SPI range for ESP-NULL [ESP-NULL], and using UDP encapsulation with a different format and ports.

几个文档讨论了修改ESP以向中间设备提供有关ESP数据包使用空加密的信息的方法。讨论了以下方法:添加IP选项、添加新的IP协议号加上额外的标头[RFC5840]、添加告知ESP-NULL参数[AUTH-ONLY-ESP]的新IP协议号、为ESP-NULL[ESP-NULL]保留SPI范围,以及使用具有不同格式和端口的UDP封装。

All of the aforementioned documents require modification to ESP, which requires that all end nodes be modified before intermediate devices can assume that this new ESP format is in use. Updating end nodes will require a lot of time. An example of slow end-node deployment is Internet Key Exchange Protocol version 2 (IKEv2). Considering an implementation that requires both IKEv2 and a new ESP format, it would take several years, possibly as long as a decade, before widespread deployment.

上述所有文档都需要修改ESP,这要求在中间设备可以假定此新ESP格式正在使用之前修改所有终端节点。更新结束节点将需要大量时间。低端节点部署的一个示例是Internet密钥交换协议版本2(IKEv2)。考虑到一个需要IKEv2和新ESP格式的实现,在广泛部署之前需要几年时间,可能长达十年。

3. Description of Heuristics
3. 启发式描述

The heuristics to detect ESP-NULL packets will only require changes to those intermediate devices that do deep inspection or other operations that require the detection of ESP-NULL. As those nodes require changes regardless of any ESP-NULL method, updating intermediate nodes is unavoidable. Heuristics do not require updates or modifications to any other devices on the rest of the network, including (especially) end nodes.

检测ESP-NULL数据包的启发式方法只需要更改进行深度检查的中间设备或其他需要检测ESP-NULL的操作。由于无论采用何种ESP-NULL方法,这些节点都需要更改,因此更新中间节点是不可避免的。启发式不需要更新或修改网络其余部分的任何其他设备,包括(特别是)终端节点。

In this document, it is assumed that an affected intermediate node will act as a stateful interception device, meaning it will keep state of the IPsec flows -- where flows are defined by the ESP SPI and IP addresses forming an IPsec SA -- going through it. The heuristics can also be used without storing any state, but performance will be worse in that case, as heuristic checks will need to be done for each packet, not only once per flow. This will also affect the reliability of the heuristics.

在本文档中,假定受影响的中间节点将充当有状态拦截设备,这意味着它将保持IPsec流的状态—其中流由ESP SPI和形成IPsec SA的IP地址定义—通过它。启发式算法也可以在不存储任何状态的情况下使用,但在这种情况下性能会更差,因为需要对每个数据包进行启发式检查,而不是每个流只进行一次。这也会影响启发式算法的可靠性。

Generally, an intermediate node runs heuristics only for the first few packets of the new flow (i.e., the new IPsec SA). After those few packets, the node detects parameters of the IPsec flow, it skips detection heuristics, and it can perform direct packet-inspecting action based on its own policy. Once detected, ESP-NULL packets will never be detected as encrypted ESP packets, meaning that valid ESP-NULL packets will never bypass the deep inspection.

通常,中间节点仅对新流(即,新IPsec SA)的前几个数据包运行启发式。在这几个包之后,节点检测IPsec流的参数,它跳过检测试探法,并且它可以根据自己的策略执行直接的包检查操作。一旦检测到,ESP-NULL数据包将永远不会被检测为加密的ESP数据包,这意味着有效的ESP-NULL数据包将永远不会绕过深度检查。

The only failure mode of these heuristics is to assume encrypted ESP packets are ESP-NULL packets, thus causing completely random packet data to be deeply inspected. An attacker can easily send random-looking ESP-NULL packets that will cause heuristics to detect packets as encrypted ESP, but that is no worse than sending non-ESP fuzz through an intermediate node. The only way an ESP-NULL flow can be mistaken for an encrypted ESP flow is if the ESP-NULL flow uses an authentication algorithm of which the packet inspector has no knowledge.

这些启发式算法的唯一失败模式是假设加密的ESP数据包是ESP-NULL数据包,从而导致对完全随机的数据包数据进行深入检查。攻击者可以很容易地发送随机外观的ESP-NULL数据包,这将导致启发式算法将数据包检测为加密的ESP,但这并不比通过中间节点发送非ESP模糊更糟糕。ESP-NULL流被误认为加密的ESP流的唯一方法是,如果ESP-NULL流使用了数据包检查器不知道的身份验证算法。

For hardware implementations, all the flow lookup based on the ESP next header number (50), source address, destination address, and SPI can be done by the hardware (there is usually already similar functionality there, for TCP/UDP flows). The heuristics can be implemented by the hardware, but using software will allow faster updates when new protocol modifications come out or new protocols need support.

对于硬件实现,所有基于ESP下一个报头号(50)、源地址、目标地址和SPI的流查找都可以由硬件完成(对于TCP/UDP流,通常已经有类似的功能)。启发式算法可以由硬件实现,但当新协议修改出现或新协议需要支持时,使用软件将允许更快的更新。

As described in Section 7, UDP-encapsulated ESP traffic may also have Network Address Port Translation (NAPT) applied to it, and so there is already a 5-tuple state in the stateful inspection gateway.

如第7节所述,UDP封装的ESP通信可能还应用了网络地址端口转换(NAPT),因此有状态检查网关中已经存在5元组状态。

4. IPsec Flows
4. IPsec流

ESP is a stateful protocol, meaning there is state stored in both end nodes of the ESP IPsec SA, and the state is identified by the pair of destination IP and SPI. Also, end nodes often fix the source IP address in an SA unless the destination is a multicast group. Typically, most (if not all) flows of interest to an intermediate device are unicast, so it is safer to assume the receiving node also uses a source address, and the intermediate device should therefore

ESP是一种有状态协议,这意味着ESP IPsec SA的两个终端节点中都存储有状态,并且状态由目标IP和SPI对标识。此外,除非目标是多播组,否则终端节点通常会固定SA中的源IP地址。通常,到中间设备的大多数(如果不是全部)感兴趣的流是单播的,因此假设接收节点也使用源地址更安全,因此中间设备应该使用源地址

do the same. In some cases, this might cause extraneous cached ESP IPsec SA flows, but by using the source address, two distinct flows will never be mixed. For sites that heavily use multicast, such traffic is deterministically identifiable (224.0.0.0/4 for IPv4 and ff00::0/8 for IPv6), and an implementation can save the space of multiple cache entries for a multicast flow by checking the destination address first.

做同样的事。在某些情况下,这可能会导致无关的缓存ESP IPsec SA流,但通过使用源地址,两个不同的流将永远不会混合。对于大量使用多播的站点,此类流量是确定可识别的(对于IPv4为224.0.0.0/4,对于IPv6为ff00::0/8),并且实现可以通过首先检查目标地址来为多播流节省多个缓存项的空间。

When the intermediate device sees a new ESP IPsec flow, i.e., a new flow of ESP packets where the source address, destination address, and SPI number form a triplet that has not been cached, it will start the heuristics to detect whether or not this flow is ESP-NULL. These heuristics appear in Section 8.

当中间设备看到一个新的ESP IPsec流,即源地址、目标地址和SPI编号形成一个尚未缓存的三元组的新ESP数据包流时,它将启动试探法来检测该流是否为ESP-NULL。这些启发式方法见第8节。

When the heuristics finish, they will label the flow as either encrypted (which tells that packets in this flow are encrypted, and cannot be ESP-NULL packets) or as ESP-NULL. This information, along with the ESP-NULL parameters detected by the heuristics, is stored to a flow cache, which will be used in the future when processing packets of the same flow.

当启发式完成时,它们会将流标记为加密(这表明此流中的数据包已加密,不能是ESP-NULL数据包)或ESP-NULL。该信息与启发式算法检测到的ESP-NULL参数一起存储到流缓存中,将来处理相同流的数据包时将使用该缓存。

Both encrypted ESP and ESP-NULL flows are processed based on the local policy. In normal operation, encrypted ESP flows are passed through or dropped per local policy, and ESP-NULL flows are passed to the deep-inspection engine. Local policy will also be used to determine other packet-processing parameters. Local policy issues will be clearly marked in this document to ease implementation.

加密的ESP和ESP-NULL流均基于本地策略进行处理。在正常操作中,根据本地策略传递或丢弃加密的ESP流,并将ESP-NULL流传递到深度检查引擎。本地策略还将用于确定其他数据包处理参数。本文件将明确标记地方政策问题,以便于实施。

In some cases, the heuristics cannot determine the type of flow from a single packet; and in that case, it might need multiple packets before it can finish the process. In those cases, the heuristics return "unsure" status. In that case, the packet processed based on the local policy and flow cache is updated with "unsure" status. Local policy for "unsure" packets could range from dropping (which encourages end-node retransmission) to queuing (which may preserve delivery, at the cost of artificially inflating round-trip times if they are measured). When the next packet to the flow arrives, it is heuristically processed again, and the cached flow may continue to be "unsure", marked as ESP, or marked as an ESP-NULL flow.

在某些情况下,启发式算法无法确定来自单个数据包的流的类型;在这种情况下,它可能需要多个数据包才能完成该过程。在这些情况下,启发式返回“不确定”状态。在这种情况下,基于本地策略和流缓存处理的数据包更新为“不确定”状态。“不确定”数据包的本地策略可能从丢弃(鼓励端节点重新传输)到排队(可能会保留传递,但如果测量往返时间,则会人为增加往返时间)。当流的下一个数据包到达时,它会再次被试探性地处理,并且缓存的流可能会继续“不确定”,标记为ESP或标记为ESP-NULL流。

There are several reasons why a single packet might not be enough to detect the type of flow. One of them is that the next header number was unknown, i.e., if heuristics do not know about the protocol for the packet, they cannot verify it has properly detected ESP-NULL parameters, even when the packet otherwise looks like ESP-NULL. If the packet does not look like ESP-NULL at all, then the encrypted ESP

单个数据包可能不足以检测流的类型,有几个原因。其中之一是下一个报头编号未知,即,如果启发式算法不知道数据包的协议,则无法验证它是否正确检测到ESP-NULL参数,即使数据包看起来像ESP-NULL。如果数据包看起来根本不像ESP-NULL,那么加密的ESP

status can be returned quickly. As ESP-NULL heuristics need to know the same protocols as a deep-inspection device, an ESP-NULL instance of an unknown protocol can be handled the same way as a cleartext instance of the same unknown protocol.

状态可以快速返回。由于ESP-NULL启发式需要知道与深度检查设备相同的协议,未知协议的ESP-NULL实例可以与相同未知协议的明文实例相同的方式处理。

5. Deep-Inspection Engine
5. 深度检验机

A deep-inspection engine running on an intermediate node usually checks deeply into the packet and performs policy decisions based on the contents of the packet. The deep-inspection engine should be able to tell the difference between success, failure, and garbage. Success means that a packet was successfully checked with the deep-inspection engine, and it passed the checks and is allowed to be forwarded. Failure means that a packet was successfully checked, but the actual checks done indicated that packets should be dropped, i.e., the packet contained a virus, was a known attack, or something similar.

在中间节点上运行的深度检查引擎通常深入检查数据包,并根据数据包的内容执行策略决策。深度检查引擎应该能够区分成功、失败和垃圾。成功意味着使用深度检查引擎成功地检查了数据包,并且它通过了检查并被允许转发。失败意味着成功检查了数据包,但实际检查表明应丢弃数据包,即数据包包含病毒、已知攻击或类似情况。

Garbage means that the packet's protocol headers or other portions were unparseable. For the heuristics, it would be useful if the deep-inspection engine could differentiate the garbage and failure cases, as garbage cases can be used to detect certain error cases (e.g., where the ESP-NULL parameters are incorrect, or the flow is really an encrypted ESP flow, not an ESP-NULL flow).

垃圾意味着数据包的协议头或其他部分是不可解析的。对于启发式,如果深度检查引擎能够区分垃圾和故障情况,这将非常有用,因为垃圾情况可用于检测某些错误情况(例如,ESP-NULL参数不正确,或者流实际上是加密的ESP流,而不是ESP-NULL流)。

If the deep-inspection engine only returns failure for all garbage packets in addition to real failure cases, then a system implementing the ESP-NULL heuristics cannot recover from error situations quickly.

如果深度检查引擎仅返回所有垃圾数据包的故障以及实际故障情况,那么实现ESP-NULL启发式的系统无法快速从错误情况中恢复。

6. Special and Error Cases
6. 特殊情况和错误情况

There is a small probability that an encrypted ESP packet (which looks like it contains completely random bytes) will have plausible bytes in expected locations, such that heuristics will detect the packet as an ESP-NULL packet instead of detecting that it is encrypted ESP packet. The actual probabilities will be computed later in this document. Such a packet will not cause problems, as the deep-inspection engine will most likely reject the packet and return that it is garbage. If the deep-inspection engine is rejecting a high number of packets as garbage, it might indicate an original ESP-NULL detection for the flow was wrong (i.e., an encrypted ESP flow was improperly detected as ESP-NULL). In that case, the cached flow should be invalidated and discovery should happen again.

加密的ESP数据包(看起来它包含完全随机的字节)在预期位置具有合理的字节的可能性很小,因此启发式算法会将该数据包检测为ESP-NULL数据包,而不是检测它是加密的ESP数据包。实际概率将在本文件后面计算。这样的数据包不会引起问题,因为深度检查引擎很可能会拒绝该数据包并返回它是垃圾。如果深度检查引擎拒绝大量数据包作为垃圾,则可能表明流的原始ESP-NULL检测错误(即,加密的ESP流被不正确地检测为ESP-NULL)。在这种情况下,缓存的流应该无效,并且应该再次进行发现。

Each ESP-NULL flow should also keep statistics about how many packets have been detected as garbage by deep inspection, how many have passed checks, or how many have failed checks with policy violations

每个ESP-NULL流还应该保留关于有多少数据包被深度检查检测为垃圾的统计信息,有多少通过了检查,或者有多少通过了违反策略的检查

(i.e., failed because of actual inspection policy failures, not because the packet looked like garbage). If the number of garbage packets suddenly increases (e.g., most of the packets start to look like garbage according to the deep-inspection engine), it is possible the old ESP-NULL SA was replaced by an encrypted ESP SA with an identical SPI. If both ends use random SPI generation, this is a very unlikely situation (1 in 2^32), but it is possible that some nodes reuse SPI numbers (e.g., a 32-bit memory address of the SA descriptor); thus, this situation needs to be handled.

(即,失败是因为实际的检查策略失败,而不是因为数据包看起来像垃圾)。如果垃圾数据包的数量突然增加(例如,根据深度检查引擎,大多数数据包开始看起来像垃圾),则旧的ESP-NULL SA可能被具有相同SPI的加密ESP SA替换。如果两端都使用随机SPI生成,这是一种非常不可能的情况(1/2^32),但有些节点可能重用SPI编号(例如,SA描述符的32位内存地址);因此,这种情况需要处理。

Actual limits for cache invalidation are local policy decisions. Sample invalidation policies include: 50% of packets marked as garbage within a second, or if a deep-inspection engine cannot differentiate between garbage and failure, failing more than 95% of packets in last 10 seconds. For implementations that do not distinguish between garbage and failure, failures should not be treated too quickly as an indication of SA reuse. Often, single packets cause state-related errors that block otherwise normal packets from passing.

缓存失效的实际限制是本地策略决定。示例无效策略包括:50%的数据包在一秒钟内标记为垃圾,或者如果深度检查引擎无法区分垃圾和失败,则在过去10秒钟内超过95%的数据包失败。对于不区分垃圾和故障的实现,不应将故障太快地视为SA重用的指示。通常,单个数据包会导致与状态相关的错误,从而阻止正常数据包的传递。

7. UDP Encapsulation
7. UDP封装

The flow lookup code needs to detect UDP packets to or from port 4500 in addition to the ESP packets, and perform similar processing to them after skipping the UDP header. Port-translation by NAT often rewrites what was originally 4500 into a different value, which means each unique port pair constitutes a separate IPsec flow. That is, UDP-encapsulated IPsec flows are identified by the source and destination IP, source and destination port number, and SPI number. As devices might be using IKEv2 Mobility and Multihoming (MOBIKE) ([RFC4555]), that also means that the flow cache should be shared between the UDP encapsulated IPsec flows and non-encapsulated IPsec flows. As previously mentioned, differentiating between garbage and actual policy failures will help in proper detection immensely.

除了ESP数据包外,流查找代码还需要检测到进出端口4500的UDP数据包,并在跳过UDP报头后对其执行类似的处理。NAT的端口转换通常将原来的4500重写为不同的值,这意味着每个唯一的端口对构成一个单独的IPsec流。也就是说,UDP封装的IPsec流由源和目标IP、源和目标端口号以及SPI号标识。由于设备可能正在使用IKEv2移动和多归属(MOBIKE)([RFC4555]),这也意味着流缓存应该在UDP封装的IPsec流和非封装的IPsec流之间共享。如前所述,区分垃圾和实际策略失败将极大地有助于正确检测。

Because the checks are run for packets having just source port 4500 or packets having just destination port 4500, this might cause checks to be run for non-ESP traffic too. Some traffic may randomly use port 4500 for other reasons, especially if a port-translating NAT is involved. The UDP encapsulation processing should also be aware of that possibility.

由于检查是针对仅具有源端口4500的数据包或仅具有目标端口4500的数据包运行的,因此这可能会导致检查也针对非ESP流量运行。由于其他原因,某些流量可能会随机使用端口4500,特别是在涉及端口转换NAT的情况下。UDP封装处理也应该意识到这种可能性。

8. Heuristic Checks
8. 启发式检查

Normally, HMAC-SHA1-96 or HMAC-MD5-96 gives 1 out of 2^96 probability that a random packet will pass the Hashed Message Authentication Code (HMAC) test. This yields a 99.999999999999999999999999998% probability that an end node will correctly detect a random packet as

通常,HMAC-SHA1-96或HMAC-MD5-96给出随机数据包通过哈希消息认证码(HMAC)测试的概率为1/2^96。这将产生99.9999999999999999999999999 8%的概率,即终端节点将正确地检测到随机数据包

being invalid. This means that it should be enough for an intermediate device to check around 96 bits from the input packet. By comparing them against known values for the packet, a deep-inspection engine gains more or less the same probability as that which an end node is using. This gives an upper limit of how many bits heuristics need to check -- there is no point of checking much more than that many bits (since that same probability is acceptable for the end node). In most of the cases, the intermediate device does not need probability that is that high, perhaps something around 32-64 bits is enough.

无效的。这意味着中间设备从输入数据包中检查大约96位就足够了。通过将它们与包的已知值进行比较,深度检查引擎获得的概率与终端节点使用的概率大致相同。这给出了启发式算法需要检查的比特数的上限——检查的比特数不能超过这个上限(因为对于终端节点来说,相同的概率是可以接受的)。在大多数情况下,中间设备不需要那么高的概率,也许32-64位左右就足够了。

IPsec's ESP has a well-understood packet layout, but its variable-length fields reduce the ability of pure algorithmic matching to one requiring heuristics and assigning probabilities.

IPsec的ESP具有众所周知的数据包布局,但其可变长度字段降低了纯算法匹配到需要启发式和分配概率的匹配的能力。

8.1. ESP-NULL Format
8.1. ESP-NULL格式

The ESP-NULL format is as follows:

ESP-NULL格式如下所示:

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                Security Parameter Index (SPI)                 |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      Sequence Number                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    IV (optional)                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    Payload Data (variable)                    |
       ~                                                               ~
       |                                                               |
       +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |               |     Padding (0-255 bytes)                     |
       +-+-+-+-+-+-+-+-+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                               |  Pad Length   | Next Header   |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |             Integrity Check Value (variable)                  |
       ~                                                               ~
       |                                                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        
        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                Security Parameter Index (SPI)                 |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                      Sequence Number                          |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    IV (optional)                              |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                    Payload Data (variable)                    |
       ~                                                               ~
       |                                                               |
       +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |               |     Padding (0-255 bytes)                     |
       +-+-+-+-+-+-+-+-+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                               |  Pad Length   | Next Header   |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |             Integrity Check Value (variable)                  |
       ~                                                               ~
       |                                                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        

Figure 1

图1

The output of the heuristics should provide information about whether the packet is encrypted ESP or ESP-NULL. In case it is ESP-NULL, the heuristics should also provide the Integrity Check Value (ICV) field length and the Initialization Vector (IV) length.

启发式的输出应提供有关数据包是加密的ESP还是ESP-NULL的信息。如果为ESP-NULL,则启发式还应提供完整性检查值(ICV)字段长度和初始化向量(IV)长度。

The currently defined ESP authentication algorithms have 4 different lengths for the ICV field.

当前定义的ESP认证算法有4种不同长度的ICV字段。

Different ICV lengths for different algorithm:

不同算法的不同ICV长度:

       Algorithm                           ICV Length
       -------------------------------     ----------
       AUTH_HMAC_MD5_96                    96
       AUTH_HMAC_SHA1_96                   96
       AUTH_AES_XCBC_96                    96
       AUTH_AES_CMAC_96                    96
       AUTH_HMAC_SHA2_256_128              128
       AUTH_HMAC_SHA2_384_192              192
       AUTH_HMAC_SHA2_512_256              256
        
       Algorithm                           ICV Length
       -------------------------------     ----------
       AUTH_HMAC_MD5_96                    96
       AUTH_HMAC_SHA1_96                   96
       AUTH_AES_XCBC_96                    96
       AUTH_AES_CMAC_96                    96
       AUTH_HMAC_SHA2_256_128              128
       AUTH_HMAC_SHA2_384_192              192
       AUTH_HMAC_SHA2_512_256              256
        

Figure 2

图2

In addition to the ESP authentication algorithms listed above, there is also the encryption algorithm ENCR_NULL_AUTH_AES_GMAC, which does not provide confidentiality but provides authentication, just like ESP-NULL. This algorithm has an ICV Length of 128 bits, and it also requires 8 bytes of IV.

除了上面列出的ESP身份验证算法外,还有加密算法ENCR_NULL_AUTH_AES_GMAC,它与ESP-NULL一样,不提供机密性,但提供身份验证。该算法的ICV长度为128位,它还需要8字节的IV。

In addition to the ICV length, there are also two possible values for IV lengths: 0 bytes (default) and 8 bytes (for ENCR_NULL_AUTH_AES_GMAC). Detecting the IV length requires understanding the payload, i.e., the actual protocol data (meaning TCP, UDP, etc.). This is required to distinguish the optional IV from the actual protocol data. How well the IV can be distinguished from the actual protocol data depends on how the IV is generated. If the IV is generated using a method that generates random-looking data (i.e., encrypted counter, etc.) then distinguishing protocol data from the IV is quite easy. If an IV is a counter or similar non-random value, then there are more possibilities for error. If the protocol (also known as the, "next header") of the packet is one that is not supported by the heuristics, then detecting the IV length is impossible; thus, the heuristics cannot finish. In that case, the heuristics return "unsure" and require further packets.

除了ICV长度外,IV长度还有两个可能的值:0字节(默认值)和8字节(对于ENCR_NULL_AUTH_AES_GMAC)。检测IV长度需要了解有效负载,即实际协议数据(指TCP、UDP等)。这是区分可选IV和实际协议数据所必需的。IV与实际协议数据的区别程度取决于IV的生成方式。如果使用生成随机数据(即,加密计数器等)的方法生成IV,则很容易将协议数据与IV区分开来。如果IV是计数器或类似的非随机值,则有更多的错误可能性。如果数据包的协议(也称为“下一个报头”)是启发式算法不支持的协议,那么检测IV长度是不可能的;因此,启发式无法完成。在这种情况下,启发式返回“不确定”,并需要进一步的数据包。

This document does not cover RSA authentication in ESP ([RFC4359]), as it is considered beyond the scope of this document.

本文档不包括ESP中的RSA身份验证([RFC4359]),因为它被认为超出了本文档的范围。

8.2. Self Describing Padding Check
8.2. 自描述填充检查

Before obtaining the next header field, the ICV length must be measured. Four different ICV lengths lead to four possible places for the pad length and padding. Implementations must be careful when trying larger sizes of the ICV such that the inspected bytes do not

在获取下一个标题字段之前,必须测量ICV长度。四种不同的ICV长度会导致衬垫长度和衬垫的四个可能位置。在尝试更大尺寸的ICV时,实现必须小心,这样检查的字节就不会丢失

belong to data that is not payload data. For example, a 10-byte ICMP echo request will have zero-length padding, but any checks for 256-bit ICVs will inspect sequence number or SPI data if the packet actually contains a 96-bit or 128-bit ICV.

属于非有效负载数据的数据。例如,10字节ICMP回送请求将具有零长度填充,但如果数据包实际包含96位或128位ICV,则对256位ICV的任何检查都将检查序列号或SPI数据。

ICV lengths should always be checked from shortest to longest. It is much more likely to obtain valid-looking padding bytes in the cleartext part of the payload than from the ICV field of a longer ICV than what is currently inspected. For example, if a packet has a 96-bit ICV and the implementation starts checking for a 256-bit ICV first, it is possible that the cleartext part of the payload contains valid-looking bytes. If done in the other order, i.e., a packet having a 256-bit ICV and the implementation checks for a 96-bit ICV first, the inspected bytes are part of the longer ICV field, and should be indistinguishable from random noise.

应始终从最短到最长检查ICV长度。与当前检查的内容相比,从较长ICV的ICV字段中获得有效的填充字节的可能性要大得多。例如,如果数据包具有96位ICV,并且实现首先开始检查256位ICV,则有效负载的明文部分可能包含看起来有效的字节。如果按照其他顺序进行,即,具有256位ICV的数据包和首先检查96位ICV的实现,则检查的字节是较长ICV字段的一部分,并且应该与随机噪声无法区分。

Each ESP packet always has between 0-255 bytes of padding, and payload, pad length, and next header are always right aligned within a 4-byte boundary. Normally, implementations use a minimal amount of padding, but the heuristics method would be even more reliable if some extra padding is added. The actual padding data has bytes starting from 01 and ending at the pad length, i.e., exact padding and pad length bytes for 4 bytes of padding would be 01 02 03 04 04.

每个ESP数据包始终具有0-255字节的填充,有效负载、填充长度和下一个报头始终在4字节边界内右对齐。通常情况下,实现使用最小的填充量,但是如果添加一些额外的填充,启发式方法将更加可靠。实际的填充数据具有从01开始并以焊盘长度结束的字节,即,4字节填充的确切填充和焊盘长度字节将为01 02 03 04。

Two cases of ESP-NULL padding are matched bytes (like the 04 04 shown above), or the 0-byte padding case. In cases where there is one or more bytes of padding, a node can perform a very simple and fast test -- a sequence of N N in any of those four locations. Given four 2-byte locations (assuming the packet size allows all four possible ICV lengths), the upper-bound probability of finding a random encrypted packet that exhibits non-zero length ESP-NULL properties is:

ESP-NULL填充的两种情况是匹配的字节(如上面所示的04),或者是0字节填充。在有一个或多个字节填充的情况下,节点可以执行一个非常简单和快速的测试——在这四个位置中的任意一个位置执行一个N的序列。给定四个2字节位置(假设数据包大小允许所有四种可能的ICV长度),找到具有非零长度ESP-NULL属性的随机加密数据包的上限概率为:

   1 - (1 - 255 / 65536) ^ 4 == 0.015 == 1.5%
        
   1 - (1 - 255 / 65536) ^ 4 == 0.015 == 1.5%
        

In the cases where there are 0 bytes of padding, a random encrypted ESP packet has:

在填充为0字节的情况下,随机加密的ESP数据包具有:

1 - (1 - 1 / 256) ^ 4 == 0.016 == 1.6%.

1 - (1 - 1 / 256) ^ 4 == 0.016 == 1.6%.

Together, both cases yield a 3.1% upper-bound chance of misclassifying an encrypted packet as an ESP-NULL packet.

两种情况加在一起,将加密数据包误分类为ESP-NULL数据包的概率上限为3.1%。

In the matched bytes case, further inspection (counting the pad bytes backward and downward from the pad-length match) can reduce the number of misclassified packets further. A padding length of 255 means a specific 256^254 sequence of bytes must occur. This virtually eliminates pairs of 'FF FF' as viable ESP-NULL padding.

在匹配字节的情况下,进一步检查(从焊盘长度匹配向后和向下计算焊盘字节)可以进一步减少误分类数据包的数量。填充长度255表示必须出现特定的256^254字节序列。这实际上消除了成对的“FF FF”作为可行的ESP-NULL填充。

Every one of the 255 pairs for padding length N has only a 1 / 256^N probability of being correct ESP-NULL padding. This shrinks the aforementioned 1.5% of matched pairs to virtually nothing.

填充长度为N的255对中的每一对都只有1/256^N的概率是正确的ESP-NULL填充。这将上述1.5%的匹配对缩小到几乎为零。

At this point, a maximum of 1.6% of possible byte values remain, so the next header number is inspected. If the next header number is known (and supported), then the packet can be inspected based on the next header number. If the next header number is unknown (i.e., not any of those with protocol checking support) the packet is marked "unsure", because there is no way to detect the IV length without inspecting the inner protocol payload.

此时,最大可能保留1.6%的字节值,因此检查下一个标头编号。如果下一个报头号已知(并受支持),则可以基于下一个报头号检查数据包。如果下一个报头编号未知(即,不支持协议检查的任何报头编号),则数据包被标记为“不确定”,因为在不检查内部协议有效负载的情况下无法检测IV长度。

There are six different next header fields that are in common use (TCP (6), UDP (17), ICMP (1), Stream Control Transmission Protocol (SCTP) (132), IPv4 (4), and IPv6 (41)), and if IPv6 is in heavy use, that number increases to nine (Fragment (44), ICMPv6 (58), and IPv6 options (60)). To ensure that no packet is misinterpreted as an encrypted ESP packet even when it is an ESP-NULL packet, a packet cannot be marked as a failure even when the next header number is one of those that is not known and supported. In those cases, the packets are marked as "unsure".

共有六个常用的不同的下一个报头字段(TCP(6)、UDP(17)、ICMP(1)、流控制传输协议(SCTP)(132)、IPv4(4)和IPv6(41)),如果IPv6大量使用,则该数字将增加到九个(片段(44)、ICMPv6(58)和IPv6选项(60))。为确保即使是ESP-NULL数据包,也不会将任何数据包误解为加密的ESP数据包,即使下一个报头号是未知且不受支持的报头号,也不能将数据包标记为故障。在这些情况下,数据包被标记为“不确定”。

An intermediate node's policy, however, can aid in detecting an ESP-NULL flow even when the protocol is not a common-case one. By counting how many "unsure" returns obtained via heuristics, and after the receipt of a consistent, but unknown, next header number in same location (i.e., likely with the same ICV length), the node can conclude that the flow has high probability of being ESP-NULL (since it is unlikely that so many packets would pass the integrity check at the destination unless they are legitimate). The flow can be classified as ESP-NULL with a known ICV length but an unknown IV length.

然而,中间节点的策略可以帮助检测ESP-NULL流,即使协议不是常见情况下的协议。通过计算通过启发式获得的“不确定”返回的数量,以及在相同位置(即,可能具有相同ICV长度)接收到一致但未知的下一个报头编号后,节点可以得出以下结论:流极有可能为ESP-NULL(因为不太可能有这么多数据包通过目的地的完整性检查,除非它们是合法的)。该流可以分类为ESP-NULL,具有已知的ICV长度,但具有未知的IV长度。

Fortunately, in unknown protocol cases, the IV length does not matter. If the protocol is unknown to the heuristics, it will most likely be unknown by the deep-inspection engine also. It is therefore important that heuristics should support at least those same protocols as the deep-inspection engine. Upon receipt of any inner next header number that is known by the heuristics (and deep-inspection engine), the heuristics can detect the IV length properly.

幸运的是,在未知方案的情况下,静脉长度并不重要。如果启发式算法不知道协议,那么深度检查引擎也很可能不知道协议。因此,启发式应该至少支持与深度检查引擎相同的协议,这一点很重要。在收到启发式算法(和深度检查引擎)已知的任何内部下一个标题编号后,启发式算法可以正确检测IV长度。

8.3. Protocol Checks
8.3. 协议检查

Generic protocol checking is much easier with preexisting state. For example, when many TCP/UDP flows are established over one IPsec SA, a rekey produces a new SA that needs heuristics to detect its parameters, and those heuristics benefit from the existing TCP/UDP flows that were present in the previous IPsec SA. In that case, it

使用预先存在的状态,通用协议检查要容易得多。例如,当在一个IPsec SA上建立多个TCP/UDP流时,重新密钥会生成一个新的SA,该SA需要试探法来检测其参数,并且这些试探法会从先前IPsec SA中存在的现有TCP/UDP流中受益。在这种情况下,它

is just enough to check that if a new IPsec SA has packets belonging to the flows of some other IPsec SA (previous IPsec SA before rekey), and if those flows are already known by the deep-inspection engine, it will give a strong indication that the new SA is really ESP-NULL.

只需检查新的IPsec SA是否具有属于其他IPsec SA流的数据包(重新密钥之前的IPsec SA),并且如果深度检查引擎已经知道这些流,则它将给出新SA确实为ESP-NULL的强烈指示。

The worst case scenario is when an end node starts up communication, i.e., it does not have any previous flows through the device. Heuristics will run on the first few packets received from the end node. The later subsections mainly cover these start-up cases, as they are the most difficult.

最坏的情况是当终端节点启动通信时,即,它没有通过设备的任何先前流。启发式将在从终端节点接收的前几个数据包上运行。后面的小节主要介绍这些启动案例,因为它们是最困难的。

In the protocol checks, there are two different types of checks. The first check is for packet validity, i.e., certain locations must contain specific values. For example, an inner IPv4 header of an IPv4 tunnel packet must have its 4-bit version number set to 4. If it does not, the packet is not valid, and can be marked as a failure. Other positions depending on ICV and IV lengths must also be checked, and if all of them are failures, then the packet is a failure. If any of the checks are "unsure", the packet is marked as such.

在协议检查中,有两种不同类型的检查。第一个检查是数据包有效性,即某些位置必须包含特定值。例如,IPv4隧道数据包的内部IPv4标头必须将其4位版本号设置为4。如果没有,则数据包无效,并可标记为失败。还必须检查取决于ICV和IV长度的其他位置,如果所有位置都失败,则数据包失败。如果任何一项检查“不确定”,则会将数据包标记为“不确定”。

The second type of check is for variable, but easy-to-parse values. For example, the 4-bit header length field of an inner IPv4 packet. It has a fixed value (5) as long as there are no inner IPv4 options. If the header-length has that specific value, the number of known "good" bits increases. If it has some other value, the known "good" bit count stays the same. A local policy might include reaching a bit count that is over a threshold (for example, 96 bits), causing a packet to be marked as valid.

第二种类型的检查用于变量,但很容易解析值。例如,内部IPv4数据包的4位报头长度字段。只要没有内部IPv4选项,它就有一个固定值(5)。如果报头长度具有该特定值,则已知“良好”位的数量将增加。如果它有其他值,则已知的“良好”位计数保持不变。本地策略可能包括达到超过阈值的位计数(例如,96位),从而导致数据包被标记为有效。

8.3.1. TCP Checks
8.3.1. TCP检查

When the first TCP packet is fed to the heuristics, it is most likely going to be the SYN packet of the new connection; thus, it will have less useful information than other later packets might have. The best valid packet checks include checking that header length and flags have valid values and checking source and destination port numbers, which in some cases can be used for heuristics (but in general they cannot be reliably distinguished from random numbers apart from some well-known ports like 25/80/110/143).

当第一个TCP包被馈送到启发式算法时,它很可能是新连接的SYN包;因此,它的有用信息将比其他稍后的数据包的有用信息少。最佳有效数据包检查包括检查报头长度和标志是否具有有效值,以及检查源端口号和目标端口号,在某些情况下,这些端口号可用于启发式(但一般来说,除了一些众所周知的端口(如25/80/110/143)外,它们无法与随机数可靠区分。

The most obvious field, TCP checksum, might not be usable, as it is possible that the packet has already transited a NAT box that changed the IP addresses but assumed any ESP payload was encrypted and did not fix the transport checksums with the new IP addresses. Thus, the IP numbers used in the checksum are wrong; thus, the checksum is wrong. If the checksum is correct, it can again be used to increase the valid bit count, but verifying checksums is a costly operation, thus skipping that check might be best unless there is hardware to

最明显的字段TCP校验和可能不可用,因为数据包可能已经传输了一个NAT框,该NAT框更改了IP地址,但假定任何ESP有效负载都已加密,并且没有使用新的IP地址修复传输校验和。因此,校验和中使用的IP号码是错误的;因此,校验和是错误的。如果校验和正确,则可以再次使用它来增加有效位计数,但验证校验和是一项代价高昂的操作,因此跳过该检查可能是最好的,除非有硬件支持

help the calculation. Window size, urgent pointer, sequence number, and acknowledgment numbers can be used, but there is not one specific known value for them.

帮助计算。可以使用窗口大小、紧急指针、序列号和确认号,但它们没有一个特定的已知值。

One good method of detection is that if a packet is dropped, then the next packet will most likely be a retransmission of the previous packet. Thus, if two packets are received with the same source and destination port numbers, and where sequence numbers are either the same or right after each other, then it's likely a TCP packet has been correctly detected. This heuristic is most helpful when only one packet is outstanding. For example, if a TCP SYN packet is lost (or dropped because of policy), the next packet would always be a retransmission of the same TCP SYN packet.

一种很好的检测方法是,如果一个数据包被丢弃,那么下一个数据包很可能是前一个数据包的重传。因此,如果接收到的两个数据包具有相同的源端口号和目标端口号,并且序列号相同或紧随其后,则很可能TCP数据包已被正确检测到。当只有一个包未完成时,这种启发式方法最有帮助。例如,如果TCP SYN数据包丢失(或由于策略而丢弃),则下一个数据包将始终是同一TCP SYN数据包的重新传输。

Existing deep-inspection engines usually do very good TCP flow checking already, including flow tracking, verification of sequence numbers, and reconstruction of the whole TCP flow. Similar methods can be used here, but they are implementation dependent and not described here.

现有的深度检查引擎通常已经完成了非常好的TCP流检查,包括流跟踪、序列号验证和整个TCP流的重建。这里可以使用类似的方法,但它们依赖于实现,这里不进行描述。

8.3.2. UDP Checks
8.3.2. UDP检查

UDP header has even more problems than the TCP header, as UDP has even less known data. The checksum has the same problem as the TCP checksum, due to NATs. The UDP length field might not match the overall packet length, as the sender is allowed to include TFC (traffic flow confidentiality; see Section 2.7 of "IP Encapsulating Security Payload" [RFC4303]) padding.

UDP报头比TCP报头有更多的问题,因为UDP的已知数据更少。由于NAT,校验和与TCP校验和存在相同的问题。UDP长度字段可能与整个数据包长度不匹配,因为允许发送方包含TFC(流量机密性;请参阅“IP封装安全有效负载”[RFC4303]第2.7节)填充。

With UDP packets similar multiple packet methods can be used as with TCP, as UDP protocols usually include several packets using same port numbers going from one end node to another, thus receiving multiple packets having a known pair of UDP port numbers is good indication that the heuristics have passed.

对于UDP数据包,可以使用与TCP类似的多个数据包方法,因为UDP协议通常包括使用相同端口号的多个数据包,这些数据包从一个终端节点传输到另一个终端节点,因此接收到具有已知UDP端口号对的多个数据包很好地表明启发式已经通过。

Some UDP protocols also use identical source and destination port numbers; thus, that is also a good check.

一些UDP协议也使用相同的源端口号和目标端口号;因此,这也是一个很好的检查。

8.3.3. ICMP Checks
8.3.3. ICMP检查

As ICMP messages are usually sent as return packets for other packets, they are not very common packets to get as first packets for the SA, the ICMP ECHO_REQUEST message being a noteworthy exception. ICMP ECHO_REQUEST has a known type, code, identifier, and sequence number. The checksum, however, might be incorrect again because of NATs.

由于ICMP消息通常作为其他数据包的返回数据包发送,因此它们不是作为SA的第一个数据包获得的非常常见的数据包,ICMP ECHO_请求消息是一个值得注意的例外。ICMP ECHO_请求具有已知的类型、代码、标识符和序列号。但是,由于NAT,校验和可能再次不正确。

For ICMP error messages, the ICMP message contains part of the original IP packet inside. Then, the same rules that are used to detect IPv4/IPv6 tunnel checks can be used.

对于ICMP错误消息,ICMP消息中包含原始IP数据包的一部分。然后,可以使用用于检测IPv4/IPv6隧道检查的相同规则。

8.3.4. SCTP Checks
8.3.4. SCTP检查

SCTP [RFC4960] has a self-contained checksum, which is computed over the SCTP payload and is not affected by NATs unless the NAT is SCTP-aware. Even more than the TCP and UDP checksums, the SCTP checksum is expensive, and may be prohibitive even for deep packet inspections.

SCTP[RFC4960]具有自包含校验和,该校验和是在SCTP有效负载上计算的,并且不受NAT的影响,除非NAT是SCTP感知的。SCTP校验和比TCP和UDP校验和更昂贵,甚至对于深度数据包检查也可能是禁止的。

SCTP chunks can be inspected to see if their lengths are consistent across the total length of the IP datagram, so long as TFC padding is not present.

只要不存在TFC填充,就可以检查SCTP数据块的长度在IP数据报的总长度上是否一致。

8.3.5. IPv4 and IPv6 Tunnel Checks
8.3.5. IPv4和IPv6隧道检查

In cases of tunneled traffic, the packet inside contains a full IPv4 or IPv6 packet. Many fields are usable. For IPv4, those fields include version, header length, total length (again TFC padding might confuse things there), protocol number, and 16-bit header checksum. In those cases, the intermediate device should give the decapsulated IP packet to the deep-inspection engine. IPv6 has fewer usable fields, but the version number, packet length (modulo TFC confusion), and next header all can be used by deep packet inspection.

在隧道通信的情况下,内部的数据包包含完整的IPv4或IPv6数据包。许多字段都是可用的。对于IPv4,这些字段包括版本、头长度、总长度(同样,TFC填充可能会混淆)、协议号和16位头校验和。在这些情况下,中间设备应将未封装的IP数据包发送给深度检查引擎。IPv6的可用字段较少,但版本号、数据包长度(模TFC混淆)和下一个报头都可以由深度数据包检查使用。

If all traffic going through the intermediate device is either from or to certain address blocks (for example, either to or from the company intranet prefix), this can also be checked by the heuristics.

如果通过中间设备的所有通信量来自或指向特定地址块(例如,来自或指向公司内部网前缀),也可以通过启发式方法进行检查。

9. Security Considerations
9. 安全考虑

Attackers can always bypass ESP-NULL deep packet inspection by using encrypted ESP (or some other encryption or tunneling method) instead, unless the intermediate node's policy requires dropping of packets that it cannot inspect. Ultimately, the responsibility for performing deep inspection, or allowing intermediate nodes to perform deep inspection, must rest on the end nodes. That is, if a server allows encrypted connections also, then an attacker who wants to attack the server and wants to bypass a deep-inspection device in the middle, will use encrypted traffic. This means that the protection of the whole network is only as good as the policy enforcement and protection of the end node. One way to enforce deep inspection for all traffic, is to forbid encrypted ESP completely, in which case ESP-NULL detection is easier, as all packets must be ESP-NULL based

攻击者总是可以使用加密的ESP(或其他加密或隧道方法)绕过ESP-NULL深度数据包检查,除非中间节点的策略要求丢弃它无法检查的数据包。最终,执行深度检查或允许中间节点执行深度检查的责任必须由终端节点承担。也就是说,如果服务器也允许加密连接,那么攻击者想要攻击服务器并且想要绕过中间的深度检查设备,将使用加密的流量。这意味着对整个网络的保护只与对终端节点的策略实施和保护一样好。对所有流量实施深度检查的一种方法是完全禁止加密的ESP,在这种情况下,ESP-NULL检测更容易,因为所有数据包都必须基于ESP-NULL

on the policy (heuristics may still be needed to find out the IV and ICV lengths, unless further policy restrictions eliminate the ambiguities).

在政策方面(可能仍然需要试探法来确定IV和ICV长度,除非进一步的政策限制消除了歧义)。

Section 3 discusses failure modes of the heuristics. An attacker can poison flows, tricking inspectors into ignoring legitimate ESP-NULL flows, but that is no worse than injecting fuzz.

第3节讨论了启发式的失败模式。攻击者可以毒害流,诱使检查员忽略合法的ESP-NULL流,但这并不比注入fuzz更糟糕。

Forcing the use of ESP-NULL everywhere inside the enterprise, so that accounting, logging, network monitoring, and intrusion detection all work, increases the risk of sending confidential information where eavesdroppers can see it.

强制在企业内部的任何地方使用ESP-NULL,以便记帐、日志记录、网络监控和入侵检测都能正常工作,这增加了将机密信息发送到窃听者可以看到的地方的风险。

10. References
10. 工具书类
10.1. Normative References
10.1. 规范性引用文件

[RFC2410] Glenn, R. and S. Kent, "The NULL Encryption Algorithm and Its Use With IPsec", RFC 2410, November 1998.

[RFC2410]Glenn,R.和S.Kent,“空加密算法及其在IPsec中的使用”,RFC 2410,1998年11月。

[RFC4301] Kent, S. and K. Seo, "Security Architecture for the Internet Protocol", RFC 4301, December 2005.

[RFC4301]Kent,S.和K.Seo,“互联网协议的安全架构”,RFC 43012005年12月。

[RFC4302] Kent, S., "IP Authentication Header", RFC 4302, December 2005.

[RFC4302]Kent,S.,“IP认证头”,RFC43022005年12月。

[RFC4303] Kent, S., "IP Encapsulating Security Payload (ESP)", RFC 4303, December 2005.

[RFC4303]Kent,S.,“IP封装安全有效载荷(ESP)”,RFC 4303,2005年12月。

10.2. Informative References
10.2. 资料性引用

[AUTH-ONLY-ESP] Hoffman, P. and D. McGrew, "An Authentication-only Profile for ESP with an IP Protocol Identifier", Work in Progress, August 2007.

[AUTH-ONLY-ESP]Hoffman,P.和D.McGrew,“具有IP协议标识符的ESP的仅认证配置文件”,正在进行的工作,2007年8月。

[ESP-NULL] Bhatia, M., "Identifying ESP-NULL Packets", Work in Progress, December 2008.

[ESP-NULL]Bhatia,M.“识别ESP-NULL数据包”,正在进行的工作,2008年12月。

[RFC3948] Huttunen, A., Swander, B., Volpe, V., DiBurro, L., and M. Stenberg, "UDP Encapsulation of IPsec ESP Packets", RFC 3948, January 2005.

[RFC3948]Huttunen,A.,Swander,B.,Volpe,V.,DiBurro,L.,和M.Stenberg,“IPsec ESP数据包的UDP封装”,RFC 3948,2005年1月。

[RFC4359] Weis, B., "The Use of RSA/SHA-1 Signatures within Encapsulating Security Payload (ESP) and Authentication Header (AH)", RFC 4359, January 2006.

[RFC4359]Weis,B.“在封装安全有效载荷(ESP)和身份验证头(AH)中使用RSA/SHA-1签名”,RFC 4359,2006年1月。

[RFC4555] Eronen, P., "IKEv2 Mobility and Multihoming Protocol (MOBIKE)", RFC 4555, June 2006.

[RFC4555]Eronen,P.,“IKEv2移动和多址协议(MOBIKE)”,RFC4555,2006年6月。

[RFC4835] Manral, V., "Cryptographic Algorithm Implementation Requirements for Encapsulating Security Payload (ESP) and Authentication Header (AH)", RFC 4835, April 2007.

[RFC4835]Manral,V.“封装安全有效载荷(ESP)和身份验证头(AH)的密码算法实现要求”,RFC 4835,2007年4月。

[RFC4960] Stewart, R., "Stream Control Transmission Protocol", RFC 4960, September 2007.

[RFC4960]Stewart,R.,“流控制传输协议”,RFC 49602007年9月。

[RFC5840] Grewal, K., Montenegro, G., and M. Bhatia, "Wrapped Encapsulating Security Payload (ESP) for Traffic Visibility", RFC 5840, April 2010.

[RFC5840]Grewal,K.,黑山,G.,和M.Bhatia,“用于流量可见性的包装封装安全有效载荷(ESP)”,RFC 58402010年4月。

Appendix A. Example Pseudocode
附录A.伪代码示例

This appendix is meant for the implementors. It does not include all the required checks, and this is just example pseudocode, so final implementation can be very different. It mostly lists things that need to be done, but implementations can optimize steps depending on their other parts. For example, implementation might combine heuristics and deep inspection tightly together.

本附录适用于实施者。它不包括所有必需的检查,这只是示例伪代码,因此最终实现可能会非常不同。它主要列出了需要完成的事情,但实现可以根据其他部分优化步骤。例如,实现可能将启发式和深度检查紧密结合在一起。

A.1. Fastpath
A.1. 快速通道

The following example pseudocode show the fastpath part of the packet processing engine. This part is usually implemented in hardware.

下面的示例伪代码显示了数据包处理引擎的快速路径部分。这一部分通常用硬件实现。

   ////////////////////////////////////////////////////////////
   // This pseudocode uses following variables:
   //
   // SPI_offset:    Number of bytes between start of protocol
   //                data and SPI.  This is 0 for ESP and
   //                8 for UDP-encapsulated ESP (i.e, skipping
   //                UDP header).
   //
   // IV_len:        Length of the IV of the ESP-NULL packet.
   //
   // ICV_len:       Length of the ICV of the ESP-NULL packet.
   //
   // State:         State of the packet, i.e., ESP-NULL, ESP, or
   //                unsure.
   //
   // Also following data is taken from the packet:
   //
   // IP_total_len:  Total IP packet length.
   // IP_hdr_len:    Header length of IP packet in bytes.
   // IP_Src_IP:     Source address of IP packet.
   // IP_Dst_IP:     Destination address of IP packet.
   //
   // UDP_len:       Length of the UDP packet taken from UDP header.
   // UDP_src_port:  Source port of UDP packet.
   // UDP_dst_port:  Destination port of UDP packet.
   //
   // SPI:           SPI number from ESP packet.
   //
   // Protocol:      Actual protocol number of the protocol inside
   //                ESP-NULL packet.
   // Protocol_off:  Calculated offset to the protocol payload data
   //                inside ESP-NULL packet.
        
   ////////////////////////////////////////////////////////////
   // This pseudocode uses following variables:
   //
   // SPI_offset:    Number of bytes between start of protocol
   //                data and SPI.  This is 0 for ESP and
   //                8 for UDP-encapsulated ESP (i.e, skipping
   //                UDP header).
   //
   // IV_len:        Length of the IV of the ESP-NULL packet.
   //
   // ICV_len:       Length of the ICV of the ESP-NULL packet.
   //
   // State:         State of the packet, i.e., ESP-NULL, ESP, or
   //                unsure.
   //
   // Also following data is taken from the packet:
   //
   // IP_total_len:  Total IP packet length.
   // IP_hdr_len:    Header length of IP packet in bytes.
   // IP_Src_IP:     Source address of IP packet.
   // IP_Dst_IP:     Destination address of IP packet.
   //
   // UDP_len:       Length of the UDP packet taken from UDP header.
   // UDP_src_port:  Source port of UDP packet.
   // UDP_dst_port:  Destination port of UDP packet.
   //
   // SPI:           SPI number from ESP packet.
   //
   // Protocol:      Actual protocol number of the protocol inside
   //                ESP-NULL packet.
   // Protocol_off:  Calculated offset to the protocol payload data
   //                inside ESP-NULL packet.
        
   ////////////////////////////////////////////////////////////
   // This is the main processing code for the packet
   // This will check if the packet requires ESP processing,
   //
   Process packet:
     * If IP protocol is ESP
          * Set SPI_offset to 0 bytes
          * Goto Process ESP
     * If IP protocol is UDP
          * Goto Process UDP
     * If IP protocol is WESP
          // For information about WESP processing, see WESP
          // specification.
          * Continue WESP processing
     * Continue Non-ESP processing
        
   ////////////////////////////////////////////////////////////
   // This is the main processing code for the packet
   // This will check if the packet requires ESP processing,
   //
   Process packet:
     * If IP protocol is ESP
          * Set SPI_offset to 0 bytes
          * Goto Process ESP
     * If IP protocol is UDP
          * Goto Process UDP
     * If IP protocol is WESP
          // For information about WESP processing, see WESP
          // specification.
          * Continue WESP processing
     * Continue Non-ESP processing
        
   ////////////////////////////////////////////////////////////
   // This code is run for UDP packets, and it checks if the
   // packet is UDP encapsulated UDP packet, or UDP
   // encapsulated IKE packet, or keepalive packet.
   //
   Process UDP:
     // Reassembly is not mandatory here, we could
     // do reassembly also only after detecting the
     // packet being UDP encapsulated ESP packet, but
     // that would complicate the pseudocode here
     // a lot, as then we would need to add code
     // for checking whether or not the UDP header is in this
     // packet.
     // Reassembly is to simplify things
     * If packet is fragment
          * Do full reassembly before processing
     * If UDP_src_port != 4500 and UDP_dst_port != 4500
          * Continue Non-ESP processing
     * Set SPI_offset to 8 bytes
     * If UDP_len > 4 and first 4 bytes of UDP packet are 0x000000
          * Continue Non-ESP processing (pass IKE-packet)
     * If UDP_len > 4 and first 4 bytes of UDP packet are 0x000002
          * Continue WESP processing
     * If UDP_len == 1 and first byte is 0xff
          * Continue Non-ESP processing (pass NAT-Keepalive Packet)
     * Goto Process ESP
        
   ////////////////////////////////////////////////////////////
   // This code is run for UDP packets, and it checks if the
   // packet is UDP encapsulated UDP packet, or UDP
   // encapsulated IKE packet, or keepalive packet.
   //
   Process UDP:
     // Reassembly is not mandatory here, we could
     // do reassembly also only after detecting the
     // packet being UDP encapsulated ESP packet, but
     // that would complicate the pseudocode here
     // a lot, as then we would need to add code
     // for checking whether or not the UDP header is in this
     // packet.
     // Reassembly is to simplify things
     * If packet is fragment
          * Do full reassembly before processing
     * If UDP_src_port != 4500 and UDP_dst_port != 4500
          * Continue Non-ESP processing
     * Set SPI_offset to 8 bytes
     * If UDP_len > 4 and first 4 bytes of UDP packet are 0x000000
          * Continue Non-ESP processing (pass IKE-packet)
     * If UDP_len > 4 and first 4 bytes of UDP packet are 0x000002
          * Continue WESP processing
     * If UDP_len == 1 and first byte is 0xff
          * Continue Non-ESP processing (pass NAT-Keepalive Packet)
     * Goto Process ESP
        
   ////////////////////////////////////////////////////////////
   // This code is run for ESP packets (or UDP-encapsulated ESP
   // packets).  This checks if IPsec flow is known, and
   // if not calls heuristics.  If the IPsec flow is known
   // then it continues processing based on the policy.
   //
   Process ESP:
     * If packet is fragment
          * Do full reassembly before processing
     * If IP_total_len < IP_hdr_len + SPI_offset + 4
          // If this packet was UDP encapsulated ESP packet then
          // this might be valid UDP packet that might
          // be passed or dropped depending on policy.
          * Continue normal packet processing
     * Load SPI from IP_hdr_len + SPI_offset
     * Initialize State to ESP
     // In case this was UDP encapsulated ESP, use UDP_src_port and
     // UDP_dst_port also when finding data from SPI cache.
     * Find IP_Src_IP + IP_Dst_IP + SPI from SPI cache
     * If SPI found
          * Load State, IV_len, ICV_len from cache
     * If SPI not found or State is unsure
          * Call Autodetect ESP parameters (drop to slowpath)
     * If State is ESP
          * Continue Non-ESP-NULL processing
     * Goto Check ESP-NULL packet
        
   ////////////////////////////////////////////////////////////
   // This code is run for ESP packets (or UDP-encapsulated ESP
   // packets).  This checks if IPsec flow is known, and
   // if not calls heuristics.  If the IPsec flow is known
   // then it continues processing based on the policy.
   //
   Process ESP:
     * If packet is fragment
          * Do full reassembly before processing
     * If IP_total_len < IP_hdr_len + SPI_offset + 4
          // If this packet was UDP encapsulated ESP packet then
          // this might be valid UDP packet that might
          // be passed or dropped depending on policy.
          * Continue normal packet processing
     * Load SPI from IP_hdr_len + SPI_offset
     * Initialize State to ESP
     // In case this was UDP encapsulated ESP, use UDP_src_port and
     // UDP_dst_port also when finding data from SPI cache.
     * Find IP_Src_IP + IP_Dst_IP + SPI from SPI cache
     * If SPI found
          * Load State, IV_len, ICV_len from cache
     * If SPI not found or State is unsure
          * Call Autodetect ESP parameters (drop to slowpath)
     * If State is ESP
          * Continue Non-ESP-NULL processing
     * Goto Check ESP-NULL packet
        
   ////////////////////////////////////////////////////////////
   // This code is run for ESP-NULL packets, and this
   // finds out the data required for deep-inspection
   // engine (protocol number, and offset to data)
   // and calls the deep-inspection engine.
   //
   Check ESP-NULL packet:
     * If IP_total_len < IP_hdr_len + SPI_offset + IV_len + ICV_len
                    + 4 (spi) + 4 (seq no) + 4 (protocol + padding)
          // This packet was detected earlier as being part of
          // ESP-NULL flow, so this means that either ESP-NULL
          // was replaced with other flow or this is an invalid packet.
          // Either drop or pass the packet, or restart
          // heuristics based on the policy
          * Continue packet processing
     * Load Protocol from IP_total_len - ICV_len - 1
     * Set Protocol_off to
           IP_hdr_len + SPI_offset + IV_len + 4 (spi) + 4 (seq no)
     * Do normal deep inspection on packet.
        
   ////////////////////////////////////////////////////////////
   // This code is run for ESP-NULL packets, and this
   // finds out the data required for deep-inspection
   // engine (protocol number, and offset to data)
   // and calls the deep-inspection engine.
   //
   Check ESP-NULL packet:
     * If IP_total_len < IP_hdr_len + SPI_offset + IV_len + ICV_len
                    + 4 (spi) + 4 (seq no) + 4 (protocol + padding)
          // This packet was detected earlier as being part of
          // ESP-NULL flow, so this means that either ESP-NULL
          // was replaced with other flow or this is an invalid packet.
          // Either drop or pass the packet, or restart
          // heuristics based on the policy
          * Continue packet processing
     * Load Protocol from IP_total_len - ICV_len - 1
     * Set Protocol_off to
           IP_hdr_len + SPI_offset + IV_len + 4 (spi) + 4 (seq no)
     * Do normal deep inspection on packet.
        

Figure 3

图3

A.2. Slowpath
A.2. 慢行道路

The following example pseudocode shows the actual heuristics part of the packet processing engine. This part is usually implemented in software.

下面的示例伪代码显示了数据包处理引擎的实际启发式部分。这一部分通常用软件实现。

  ////////////////////////////////////////////////////////////
  // This pseudocode uses following variables:
  //
  // SPI_offset, IV_len, ICV_len, State, SPI,
  // IP_total_len, IP_hdr_len, IP_Src_IP, IP_Dst_IP
  // as defined in fastpath pseudocode.
  //
  // Stored_Check_Bits:Number of bits we have successfully
  //                   checked to contain acceptable values
  //                   in the actual payload data.  This value
  //                   is stored/retrieved from SPI cache.
  //
  // Check_Bits:       Number of bits we have successfully
  //                   checked to contain acceptable values
  //                   in the actual payload data.  This value
  //                   is updated during the packet
  //                   verification.
  //
  // Last_Packet_Data: Contains selected pieces from the
  //                   last packet.  This is used to compare
  //                   certain fields of this packet to
  //                   same fields in previous packet.
  //
  // Packet_Data:      Selected pieces of this packet, same
  //                   fields as Last_Packet_Data, and this
  //                   is stored as new Last_Packet_Data to
  //                   SPI cache after this packet is processed.
  //
  // Test_ICV_len:     Temporary ICV length used during tests.
  //                   This is stored to ICV_len when
  //                   padding checks for the packet succeed
  //                   and the packet didn't yet have unsure
  //                   status.
  //
  // Test_IV_len:      Temporary IV length used during tests.
  //
  // Pad_len:          Padding length from the ESP packet.
  //
        
  ////////////////////////////////////////////////////////////
  // This pseudocode uses following variables:
  //
  // SPI_offset, IV_len, ICV_len, State, SPI,
  // IP_total_len, IP_hdr_len, IP_Src_IP, IP_Dst_IP
  // as defined in fastpath pseudocode.
  //
  // Stored_Check_Bits:Number of bits we have successfully
  //                   checked to contain acceptable values
  //                   in the actual payload data.  This value
  //                   is stored/retrieved from SPI cache.
  //
  // Check_Bits:       Number of bits we have successfully
  //                   checked to contain acceptable values
  //                   in the actual payload data.  This value
  //                   is updated during the packet
  //                   verification.
  //
  // Last_Packet_Data: Contains selected pieces from the
  //                   last packet.  This is used to compare
  //                   certain fields of this packet to
  //                   same fields in previous packet.
  //
  // Packet_Data:      Selected pieces of this packet, same
  //                   fields as Last_Packet_Data, and this
  //                   is stored as new Last_Packet_Data to
  //                   SPI cache after this packet is processed.
  //
  // Test_ICV_len:     Temporary ICV length used during tests.
  //                   This is stored to ICV_len when
  //                   padding checks for the packet succeed
  //                   and the packet didn't yet have unsure
  //                   status.
  //
  // Test_IV_len:      Temporary IV length used during tests.
  //
  // Pad_len:          Padding length from the ESP packet.
  //
        
  // Protocol:         Protocol number of the packet inside ESP
  //                   packet.
  //
  // TCP.*:            Fields from TCP header (from inside ESP)
  // UDP.*:            Fields from UDP header (from inside ESP)
        
  // Protocol:         Protocol number of the packet inside ESP
  //                   packet.
  //
  // TCP.*:            Fields from TCP header (from inside ESP)
  // UDP.*:            Fields from UDP header (from inside ESP)
        
  ////////////////////////////////////////////////////////////
  // This code starts the actual heuristics.
  // During this the fastpath has already loaded
  // State, ICV_len, and IV_len in case they were
  // found from the SPI cache (i.e., in case the flow
  // had unsure status).
  //
  Autodetect ESP parameters:
    // First, we check if this is unsure flow, and
    // if so, we check next packet against the
    // already set IV/ICV_len combination.
    * If State is unsure
         * Call Verify next packet
         * If State is ESP-NULL
              * Goto Store ESP-NULL SPI cache info
         * If State is unsure
              * Goto Verify unsure
         // If we failed the test, i.e., State
         // was changed to ESP, we check other
         // ICV/IV_len values, i.e., fall through
    // ICV lengths are tested in order of ICV lengths,
    // from shortest to longest.
    * Call Try standard algorithms
    * If State is ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    * Call Try 128bit algorithms
    * If State is ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    * Call Try 192bit algorithms
    * If State is ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    * Call Try 256bit algorithms
    * If State is ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    // AUTH_DES_MAC and AUTH_KPDK_MD5 are left out from
    // this document.
    // If any of those test above set state to unsure
    // we mark IPsec flow as unsure.
    * If State is unsure
         * Goto Store unsure SPI cache info
        
  ////////////////////////////////////////////////////////////
  // This code starts the actual heuristics.
  // During this the fastpath has already loaded
  // State, ICV_len, and IV_len in case they were
  // found from the SPI cache (i.e., in case the flow
  // had unsure status).
  //
  Autodetect ESP parameters:
    // First, we check if this is unsure flow, and
    // if so, we check next packet against the
    // already set IV/ICV_len combination.
    * If State is unsure
         * Call Verify next packet
         * If State is ESP-NULL
              * Goto Store ESP-NULL SPI cache info
         * If State is unsure
              * Goto Verify unsure
         // If we failed the test, i.e., State
         // was changed to ESP, we check other
         // ICV/IV_len values, i.e., fall through
    // ICV lengths are tested in order of ICV lengths,
    // from shortest to longest.
    * Call Try standard algorithms
    * If State is ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    * Call Try 128bit algorithms
    * If State is ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    * Call Try 192bit algorithms
    * If State is ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    * Call Try 256bit algorithms
    * If State is ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    // AUTH_DES_MAC and AUTH_KPDK_MD5 are left out from
    // this document.
    // If any of those test above set state to unsure
    // we mark IPsec flow as unsure.
    * If State is unsure
         * Goto Store unsure SPI cache info
        
    // All of the test failed, meaning the packet cannot
    // be ESP-NULL packet, thus we mark IPsec flow as ESP
    * Goto Store ESP SPI cache info
  ////////////////////////////////////////////////////////////
  // Store ESP-NULL status to the IPsec flow cache.
  //
  Store ESP-NULL SPI cache info:
    * Store State, IV_len, ICV_len to SPI cache
            using IP_Src_IP + IP_Dst_IP + SPI as key
    * Continue Check ESP-NULL packet
        
    // All of the test failed, meaning the packet cannot
    // be ESP-NULL packet, thus we mark IPsec flow as ESP
    * Goto Store ESP SPI cache info
  ////////////////////////////////////////////////////////////
  // Store ESP-NULL status to the IPsec flow cache.
  //
  Store ESP-NULL SPI cache info:
    * Store State, IV_len, ICV_len to SPI cache
            using IP_Src_IP + IP_Dst_IP + SPI as key
    * Continue Check ESP-NULL packet
        
  ////////////////////////////////////////////////////////////
  // Store encrypted ESP status to the IPsec flow cache.
  //
  Store ESP SPI cache info:
    * Store State, IV_len, ICV_len to SPI cache
            using IP_Src_IP + IP_Dst_IP + SPI as key
    * Continue Check non-ESP-NULL packet
        
  ////////////////////////////////////////////////////////////
  // Store encrypted ESP status to the IPsec flow cache.
  //
  Store ESP SPI cache info:
    * Store State, IV_len, ICV_len to SPI cache
            using IP_Src_IP + IP_Dst_IP + SPI as key
    * Continue Check non-ESP-NULL packet
        
  ////////////////////////////////////////////////////////////
  // Store unsure flow status to IPsec flow cache.
  // Here we also store the Check_Bits.
  //
  Store unsure SPI cache info:
    * Store State, IV_len, ICV_len,
            Stored_Check_Bits to SPI cache
            using IP_Src_IP + IP_Dst_IP + SPI as key
    * Continue Check unknown packet
        
  ////////////////////////////////////////////////////////////
  // Store unsure flow status to IPsec flow cache.
  // Here we also store the Check_Bits.
  //
  Store unsure SPI cache info:
    * Store State, IV_len, ICV_len,
            Stored_Check_Bits to SPI cache
            using IP_Src_IP + IP_Dst_IP + SPI as key
    * Continue Check unknown packet
        
  ////////////////////////////////////////////////////////////
  // Verify this packet against the previously selected
  // ICV_len and IV_len values.  This will either
  // fail (and set state to ESP to mark we do not yet
  // know what type of flow this is) or will
  // increment Check_Bits.
  //
  Verify next packet:
    // We already have IV_len, ICV_len, and State loaded
    * Load Stored_Check_Bits, Last_Packet_Data from SPI Cache
    * Set Test_ICV_len to ICV_len, Test_IV_len to IV_len
    * Initialize Check_Bits to 0
    * Call Verify padding
    * If verify padding returned Failure
         // Initial guess was wrong, restart
         * Set State to ESP
         * Clear IV_len, ICV_len, State,
                 Stored_Check_Bits, Last_Packet_Data
                 from SPI Cache
        
  ////////////////////////////////////////////////////////////
  // Verify this packet against the previously selected
  // ICV_len and IV_len values.  This will either
  // fail (and set state to ESP to mark we do not yet
  // know what type of flow this is) or will
  // increment Check_Bits.
  //
  Verify next packet:
    // We already have IV_len, ICV_len, and State loaded
    * Load Stored_Check_Bits, Last_Packet_Data from SPI Cache
    * Set Test_ICV_len to ICV_len, Test_IV_len to IV_len
    * Initialize Check_Bits to 0
    * Call Verify padding
    * If verify padding returned Failure
         // Initial guess was wrong, restart
         * Set State to ESP
         * Clear IV_len, ICV_len, State,
                 Stored_Check_Bits, Last_Packet_Data
                 from SPI Cache
        
         * Return
    // Ok, padding check succeeded again
    * Call Verify packet
    * If verify packet returned Failure
         // Guess was wrong, restart
         * Set State to ESP
         * Clear IV_len, ICV_len, State,
                 Stored_Check_Bits, Last_Packet_Data
                 from SPI Cache
         * Return
    // It succeeded and updated Check_Bits and Last_Packet_Data store
    // them to SPI cache.
    * Increment Stored_Check_Bits by Check_Bits
    * Store Stored_Check_Bits to SPI Cache
    * Store Packet_Data as Last_Packet_Data to SPI cache
    * Return
        
         * Return
    // Ok, padding check succeeded again
    * Call Verify packet
    * If verify packet returned Failure
         // Guess was wrong, restart
         * Set State to ESP
         * Clear IV_len, ICV_len, State,
                 Stored_Check_Bits, Last_Packet_Data
                 from SPI Cache
         * Return
    // It succeeded and updated Check_Bits and Last_Packet_Data store
    // them to SPI cache.
    * Increment Stored_Check_Bits by Check_Bits
    * Store Stored_Check_Bits to SPI Cache
    * Store Packet_Data as Last_Packet_Data to SPI cache
    * Return
        
  ////////////////////////////////////////////////////////////
  // This will check if we have already seen enough bits
  // acceptable from the payload data, so we can decide
  // that this IPsec flow is ESP-NULL flow.
  //
  Verify unsure:
    // Check if we have enough check bits.
    * If Stored_Check_Bits > configured limit
         // We have checked enough bits, return ESP-NULL
         * Set State ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    // Not yet enough bits, continue
    * Continue Check unknown packet
        
  ////////////////////////////////////////////////////////////
  // This will check if we have already seen enough bits
  // acceptable from the payload data, so we can decide
  // that this IPsec flow is ESP-NULL flow.
  //
  Verify unsure:
    // Check if we have enough check bits.
    * If Stored_Check_Bits > configured limit
         // We have checked enough bits, return ESP-NULL
         * Set State ESP-NULL
         * Goto Store ESP-NULL SPI cache info
    // Not yet enough bits, continue
    * Continue Check unknown packet
        
  ////////////////////////////////////////////////////////////
  // Check for standard 96-bit algorithms.
  //
  Try standard algorithms:
    // AUTH_HMAC_MD5_96, AUTH_HMAC_SHA1_96, AUTH_AES_XCBC_96,
    // AUTH_AES_CMAC_96
    * Set Test_ICV_len to 12, Test_IV_len to 0
    * Goto Check packet
        
  ////////////////////////////////////////////////////////////
  // Check for standard 96-bit algorithms.
  //
  Try standard algorithms:
    // AUTH_HMAC_MD5_96, AUTH_HMAC_SHA1_96, AUTH_AES_XCBC_96,
    // AUTH_AES_CMAC_96
    * Set Test_ICV_len to 12, Test_IV_len to 0
    * Goto Check packet
        
  ////////////////////////////////////////////////////////////
  // Check for 128-bit algorithms, this is only one that
  // can have IV, so we need to check different IV_len values
  // here too.
  //
  Try 128bit algorithms:
    // AUTH_HMAC_SHA2_256_128, ENCR_NULL_AUTH_AES_GMAC
    * Set Test_ICV_len to 16, Test_IV_len to 0
        
  ////////////////////////////////////////////////////////////
  // Check for 128-bit algorithms, this is only one that
  // can have IV, so we need to check different IV_len values
  // here too.
  //
  Try 128bit algorithms:
    // AUTH_HMAC_SHA2_256_128, ENCR_NULL_AUTH_AES_GMAC
    * Set Test_ICV_len to 16, Test_IV_len to 0
        

* If IP_total_len < IP_hdr_len + SPI_offset + Test_IV_len + Test_ICV_len + 4 (spi) + 4 (seq no) + 4 (protocol + padding) * Return * Call Verify padding * If verify padding returned Failure * Return * Initialize Check_Bits to 0 * Call Verify packet * If verify packet returned Failure * Goto Try GMAC // Ok, packet seemed ok, but go now and check if we have enough // data bits so we can assume it is ESP-NULL * Goto Check if done for unsure

* 如果IP_total_len<IP_hdr_len+SPI_offset+Test_IV_len+Test_ICV_len+4(SPI)+4(序号)+4(协议+填充)*返回*调用验证填充*如果验证填充返回失败*返回*初始化检查位为0*调用验证数据包*如果验证数据包返回失败*转到GMAC//确定,数据包似乎正常,但是现在去检查一下我们是否有足够的//数据位,这样我们就可以假设它是ESP-NULL*去检查一下是否有足够的数据位

  ////////////////////////////////////////////////////////////
  // Check for GMAC MACs, i.e., MACs that have an 8-byte IV.
  //
  Try GMAC:
    // ENCR_NULL_AUTH_AES_GMAC
    * Set Test_IV_len to 8
    * If IP_total_len < IP_hdr_len + SPI_offset
         + Test_IV_len + Test_ICV_len
         + 4 (spi) + 4 (seq no) + 4 (protocol + padding)
         * Return
    * Initialize Check_Bits to 0
    * Call Verify packet
    * If verify packet returned Failure
         // Guess was wrong, continue
         * Return
    // Ok, packet seemed ok, but go now and check if we have enough
    // data bits so we can assume it is ESP-NULL
    * Goto Check if done for unsure
        
  ////////////////////////////////////////////////////////////
  // Check for GMAC MACs, i.e., MACs that have an 8-byte IV.
  //
  Try GMAC:
    // ENCR_NULL_AUTH_AES_GMAC
    * Set Test_IV_len to 8
    * If IP_total_len < IP_hdr_len + SPI_offset
         + Test_IV_len + Test_ICV_len
         + 4 (spi) + 4 (seq no) + 4 (protocol + padding)
         * Return
    * Initialize Check_Bits to 0
    * Call Verify packet
    * If verify packet returned Failure
         // Guess was wrong, continue
         * Return
    // Ok, packet seemed ok, but go now and check if we have enough
    // data bits so we can assume it is ESP-NULL
    * Goto Check if done for unsure
        
  ////////////////////////////////////////////////////////////
  // Check for 192-bit algorithms.
  //
  Try 192bit algorithms:
    // AUTH_HMAC_SHA2_384_192
    * Set Test_ICV_len to 24, Test_IV_len to 0
    * Goto Check packet
        
  ////////////////////////////////////////////////////////////
  // Check for 192-bit algorithms.
  //
  Try 192bit algorithms:
    // AUTH_HMAC_SHA2_384_192
    * Set Test_ICV_len to 24, Test_IV_len to 0
    * Goto Check packet
        
  ////////////////////////////////////////////////////////////
  // Check for 256-bit algorithms.
  //
  Try 256bit algorithms:
    // AUTH_HMAC_SHA2_512_256
    * Set Test_ICV_len to 32, Test_IV_len to 0
        
  ////////////////////////////////////////////////////////////
  // Check for 256-bit algorithms.
  //
  Try 256bit algorithms:
    // AUTH_HMAC_SHA2_512_256
    * Set Test_ICV_len to 32, Test_IV_len to 0
        

* Goto Check packet

* 转到检查包

  ////////////////////////////////////////////////////////////
  // This actually does the checking for the packet, by
  // first verifying the length, and then self describing
  // padding, and if that succeeds, then checks the actual
  // payload content.
  //
  Check packet:
    * If IP_total_len < IP_hdr_len + SPI_offset
         + Test_IV_len + Test_ICV_len
         + 4 (spi) + 4 (seq no) + 4 (protocol + padding)
         * Return
    * Call Verify padding
    * If verify padding returned Failure
         * Return
    * Initialize Check_Bits to 0
    * Call Verify packet
    * If verify packet returned Failure
         // Guess was wrong, continue
         * Return
    // Ok, packet seemed ok, but go now and check if we have enough
    // data bits so we can assume it is ESP-NULL
    * Goto Check if done for unsure
        
  ////////////////////////////////////////////////////////////
  // This actually does the checking for the packet, by
  // first verifying the length, and then self describing
  // padding, and if that succeeds, then checks the actual
  // payload content.
  //
  Check packet:
    * If IP_total_len < IP_hdr_len + SPI_offset
         + Test_IV_len + Test_ICV_len
         + 4 (spi) + 4 (seq no) + 4 (protocol + padding)
         * Return
    * Call Verify padding
    * If verify padding returned Failure
         * Return
    * Initialize Check_Bits to 0
    * Call Verify packet
    * If verify packet returned Failure
         // Guess was wrong, continue
         * Return
    // Ok, packet seemed ok, but go now and check if we have enough
    // data bits so we can assume it is ESP-NULL
    * Goto Check if done for unsure
        
  ////////////////////////////////////////////////////////////
  // This code checks if we have seen enough acceptable
  // values in the payload data, so we can decide that this
  // IPsec flow is ESP-NULL flow.
  //
  Check if done for unsure:
    * If Stored_Check_Bits > configured limit
         // We have checked enough bits, return ESP-NULL
         * Set State ESP-NULL
         * Set IV_len to Test_IV_len, ICV_len to Test_ICV_len
         * Clear Stored_Check_Bits, Last_Packet_Data from SPI Cache
         * Return
    // Not yet enough bits, check if this is first unsure, if so
    // store information.  In case there are multiple
    // tests succeeding, we always assume the first one
    // (the one using shortest MAC) is the one we want to
    // check in the future.
    * If State is not unsure
         * Set State unsure
        
  ////////////////////////////////////////////////////////////
  // This code checks if we have seen enough acceptable
  // values in the payload data, so we can decide that this
  // IPsec flow is ESP-NULL flow.
  //
  Check if done for unsure:
    * If Stored_Check_Bits > configured limit
         // We have checked enough bits, return ESP-NULL
         * Set State ESP-NULL
         * Set IV_len to Test_IV_len, ICV_len to Test_ICV_len
         * Clear Stored_Check_Bits, Last_Packet_Data from SPI Cache
         * Return
    // Not yet enough bits, check if this is first unsure, if so
    // store information.  In case there are multiple
    // tests succeeding, we always assume the first one
    // (the one using shortest MAC) is the one we want to
    // check in the future.
    * If State is not unsure
         * Set State unsure
        
         // These values will be stored to SPI cache if
         // the final state will be unsure
         * Set IV_len to Test_IV_len, ICV_len to Test_ICV_len
         * Set Stored_Check_Bits as Check_Bits
    * Return
        
         // These values will be stored to SPI cache if
         // the final state will be unsure
         * Set IV_len to Test_IV_len, ICV_len to Test_ICV_len
         * Set Stored_Check_Bits as Check_Bits
    * Return
        
  ////////////////////////////////////////////////////////////
  // Verify self describing padding
  //
  Verify padding:
    * Load Pad_len from IP_total_len - Test_ICV_len - 2
    * Verify padding bytes at
                 IP_total_len - Test_ICV_len - 1 - Pad_len ..
                 IP_total_len - Test_ICV_len - 2 are
                 1, 2, ..., Pad_len
    * If Verify of padding bytes succeeded
         * Return Success
    * Return Failure
        
  ////////////////////////////////////////////////////////////
  // Verify self describing padding
  //
  Verify padding:
    * Load Pad_len from IP_total_len - Test_ICV_len - 2
    * Verify padding bytes at
                 IP_total_len - Test_ICV_len - 1 - Pad_len ..
                 IP_total_len - Test_ICV_len - 2 are
                 1, 2, ..., Pad_len
    * If Verify of padding bytes succeeded
         * Return Success
    * Return Failure
        
  ////////////////////////////////////////////////////////////
  // This will verify the actual protocol content inside ESP
  // packet.
  //
  Verify packet:
    // We need to first check things that cannot be set, i.e., if any of
    // those are incorrect, then we return Failure.  For any
    / fields that might be correct, we increment the Check_Bits
    // for a suitable amount of bits.  If all checks pass, then
    // we just return Success, and the upper layer will then
    // later check if we have enough bits checked already.
    * Load Protocol From IP_total_len - Test_ICV_len - 1
    * If Protocol TCP
         * Goto Verify TCP
    * If Protocol UDP
         * Goto Verify UDP
    // Other protocols can be added here as needed, most likely same
    // protocols as deep inspection does.
    // Tunnel mode checks (protocol 4 for IPv4 and protocol 41 for
    // IPv6) is also left out from here to make the document shorter.
    * Return Failure
        
  ////////////////////////////////////////////////////////////
  // This will verify the actual protocol content inside ESP
  // packet.
  //
  Verify packet:
    // We need to first check things that cannot be set, i.e., if any of
    // those are incorrect, then we return Failure.  For any
    / fields that might be correct, we increment the Check_Bits
    // for a suitable amount of bits.  If all checks pass, then
    // we just return Success, and the upper layer will then
    // later check if we have enough bits checked already.
    * Load Protocol From IP_total_len - Test_ICV_len - 1
    * If Protocol TCP
         * Goto Verify TCP
    * If Protocol UDP
         * Goto Verify UDP
    // Other protocols can be added here as needed, most likely same
    // protocols as deep inspection does.
    // Tunnel mode checks (protocol 4 for IPv4 and protocol 41 for
    // IPv6) is also left out from here to make the document shorter.
    * Return Failure
        
  ////////////////////////////////////////////////////////////
  // Verify TCP protocol headers
  //
  Verify TCP:
    // First we check things that must be set correctly.
    * If TCP.Data_Offset field < 5
        // TCP head length too small
        
  ////////////////////////////////////////////////////////////
  // Verify TCP protocol headers
  //
  Verify TCP:
    // First we check things that must be set correctly.
    * If TCP.Data_Offset field < 5
        // TCP head length too small
        
        * Return Failure
    // After that, we start to check things that do not
    // have one definitive value, but can have multiple possible
    // valid values.
    * If TCP.ACK bit is not set, then check
         that TCP.Acknowledgment_number field contains 0
         // If the ACK bit is not set, then the acknowledgment
         // field usually contains 0, but I do not think
         // RFCs mandate it being zero, so we cannot make
         // this a failure if it is not so.
         * Increment Check_Bits by 32
    * If TCP.URG bit is not set, then check
         that TCP.Urgent_Pointer field contains 0
         // If the URG bit is not set, then urgent pointer
         // field usually contains 0, but I do not think
         // RFCs mandate it being zero, so we cannot make
         // this failure if it is not so.
         * Increment Check_Bits by 16
    * If TCP.Data_Offset field == 5
        * Increment Check_Bits by 4
    * If TCP.Data_Offset field > 5
        * If TCP options format is valid and it is padded correctly
             * Increment Check_Bits accordingly
        * If TCP options format was garbage
             * Return Failure
    * If TCP.checksum is correct
        // This might be wrong because packet passed NAT, so
        // we cannot make this failure case.
        * Increment Check_Bits by 16
    // We can also do normal deeper TCP inspection here, i.e.,
    // check that the SYN/ACK/FIN/RST bits are correct and state
    // matches the state of existing flow if this is packet
    // to existing flow, etc.
    // If there is anything clearly wrong in the packet (i.e.,
    // some data is set to something that it cannot be), then
    // this can return Failure; otherwise, it should just
    // increment Check_Bits matching the number of bits checked.
    //
    // We can also check things here compared to the last packet
    * If Last_Packet_Data.TCP.source port =
         Packet_Data.TCP.source_port and
         Last_Packet_Data.TCP.destination port =
         Packet_Data.TCP.destination port
         * Increment Check_Bits by 32
    * If Last_Packet_Data.TCP.Acknowledgement_number =
         Packet_Data.TCP.Acknowledgement_number
         * Increment Check_Bits by 32
    * If Last_Packet_Data.TCP.sequence_number =
        
        * Return Failure
    // After that, we start to check things that do not
    // have one definitive value, but can have multiple possible
    // valid values.
    * If TCP.ACK bit is not set, then check
         that TCP.Acknowledgment_number field contains 0
         // If the ACK bit is not set, then the acknowledgment
         // field usually contains 0, but I do not think
         // RFCs mandate it being zero, so we cannot make
         // this a failure if it is not so.
         * Increment Check_Bits by 32
    * If TCP.URG bit is not set, then check
         that TCP.Urgent_Pointer field contains 0
         // If the URG bit is not set, then urgent pointer
         // field usually contains 0, but I do not think
         // RFCs mandate it being zero, so we cannot make
         // this failure if it is not so.
         * Increment Check_Bits by 16
    * If TCP.Data_Offset field == 5
        * Increment Check_Bits by 4
    * If TCP.Data_Offset field > 5
        * If TCP options format is valid and it is padded correctly
             * Increment Check_Bits accordingly
        * If TCP options format was garbage
             * Return Failure
    * If TCP.checksum is correct
        // This might be wrong because packet passed NAT, so
        // we cannot make this failure case.
        * Increment Check_Bits by 16
    // We can also do normal deeper TCP inspection here, i.e.,
    // check that the SYN/ACK/FIN/RST bits are correct and state
    // matches the state of existing flow if this is packet
    // to existing flow, etc.
    // If there is anything clearly wrong in the packet (i.e.,
    // some data is set to something that it cannot be), then
    // this can return Failure; otherwise, it should just
    // increment Check_Bits matching the number of bits checked.
    //
    // We can also check things here compared to the last packet
    * If Last_Packet_Data.TCP.source port =
         Packet_Data.TCP.source_port and
         Last_Packet_Data.TCP.destination port =
         Packet_Data.TCP.destination port
         * Increment Check_Bits by 32
    * If Last_Packet_Data.TCP.Acknowledgement_number =
         Packet_Data.TCP.Acknowledgement_number
         * Increment Check_Bits by 32
    * If Last_Packet_Data.TCP.sequence_number =
        

Packet_Data.TCP.sequence_number * Increment Check_Bits by 32 // We can do other similar checks here * Return Success

Packet\u Data.TCP.sequence\u number*增量检查\u位32//我们可以在此处执行其他类似检查*返回成功

  ////////////////////////////////////////////////////////////
  // Verify UDP protocol headers
  //
  Verify UDP:
    // First we check things that must be set correctly.
    * If UDP.UDP_length > IP_total_len - IP_hdr_len - SPI_offset
        - Test_IV_len - Test_ICV_len - 4 (spi)
        - 4 (seq no) - 1 (protocol)
        - Pad_len - 1 (Pad_len)
        * Return Failure
    * If UDP.UDP_length < 8
        * Return Failure
    // After that, we start to check things that do not
    // have one definitive value, but can have multiple possible
    // valid values.
    * If UDP.UDP_checksum is correct
        // This might be wrong because packet passed NAT, so
        // we cannot make this failure case.
        * Increment Check_Bits by 16
    * If UDP.UDP_length = IP_total_len - IP_hdr_len - SPI_offset
         - Test_IV_len - Test_ICV_len - 4 (spi)
         - 4 (seq no) - 1 (protocol)
         - Pad_len - 1 (Pad_len)
         // If there is no TFC padding then UDP_length
         // will be matching the full packet length
         * Increment Check_Bits by 16
    // We can also do normal deeper UDP inspection here.
    // If there is anything clearly wrong in the packet (i.e.,
    // some data is set to something that it cannot be), then
    // this can return Failure; otherwise, it should just
    // increment Check_Bits matching the number of bits checked.
    //
    // We can also check things here compared to the last packet
    * If Last_Packet_Data.UDP.source_port =
         Packet_Data.UDP.source_port and
         Last_Packet_Data.destination_port =
         Packet_Data.UDP.destination_port
         * Increment Check_Bits by 32
    * Return Success
        
  ////////////////////////////////////////////////////////////
  // Verify UDP protocol headers
  //
  Verify UDP:
    // First we check things that must be set correctly.
    * If UDP.UDP_length > IP_total_len - IP_hdr_len - SPI_offset
        - Test_IV_len - Test_ICV_len - 4 (spi)
        - 4 (seq no) - 1 (protocol)
        - Pad_len - 1 (Pad_len)
        * Return Failure
    * If UDP.UDP_length < 8
        * Return Failure
    // After that, we start to check things that do not
    // have one definitive value, but can have multiple possible
    // valid values.
    * If UDP.UDP_checksum is correct
        // This might be wrong because packet passed NAT, so
        // we cannot make this failure case.
        * Increment Check_Bits by 16
    * If UDP.UDP_length = IP_total_len - IP_hdr_len - SPI_offset
         - Test_IV_len - Test_ICV_len - 4 (spi)
         - 4 (seq no) - 1 (protocol)
         - Pad_len - 1 (Pad_len)
         // If there is no TFC padding then UDP_length
         // will be matching the full packet length
         * Increment Check_Bits by 16
    // We can also do normal deeper UDP inspection here.
    // If there is anything clearly wrong in the packet (i.e.,
    // some data is set to something that it cannot be), then
    // this can return Failure; otherwise, it should just
    // increment Check_Bits matching the number of bits checked.
    //
    // We can also check things here compared to the last packet
    * If Last_Packet_Data.UDP.source_port =
         Packet_Data.UDP.source_port and
         Last_Packet_Data.destination_port =
         Packet_Data.UDP.destination_port
         * Increment Check_Bits by 32
    * Return Success
        

Figure 4

图4

Authors' Addresses

作者地址

Tero Kivinen AuthenTec, Inc. Fredrikinkatu 47 Helsinki FIN-00100 FI

Tero Kivinen AuthenTec,Inc.Fredrikinkatu 47赫尔辛基FIN-00100 FI

   EMail: kivinen@iki.fi
        
   EMail: kivinen@iki.fi
        

Daniel L. McDonald Oracle Corporation 35 Network Drive MS UBUR02-212 Burlington, MA 01803 USA

Daniel L.McDonald Oracle Corporation美国马萨诸塞州伯灵顿市网络大道35号UBUR02-212邮编01803

   EMail: danmcd@opensolaris.org
        
   EMail: danmcd@opensolaris.org