RFC 4301
Security Architecture for the Internet Protocol
RFC 4301: Security Architecture for the Internet Protocol 🎀
Okay bestie, this is RFC 4301, the Security Architecture for IP doc, aka the big-brain blueprint for IPsec 🔐✨. The title block tea ☕: it's from the Network Working Group, written by S. Kent and K. Seo at BBN Technologies 💅. It's a Standards Track doc, dated December 2005 🦋. It obsoletes RFC 2401 (the November 1998 one), and the title block doesn't list any updates.
Status of This Memo
Okay so this section is the official vibe check 🫶. It's an Internet standards track protocol for the Internet community, and it's asking for discussion and suggestions for improvements 💭. If you want the current standardization state and status of this protocol, check the "Internet Official Protocol Standards" (STD 1) doc 📋. And yes, distribution is unlimited, so share it with the whole squad 🌈.
Copyright Notice
Copyright (C) The Internet Society (2005) 🎀
Abstract
This doc is an updated version of the "Security Architecture for IP," which is designed to provide security services for traffic at the IP layer 🔒. It obsoletes RFC 2401 (November 1998) 🦋.
Dedication
This document is dedicated to the memory of Charlie Lynn 🌸, a long-time senior colleague at BBN who made very significant contributions to the IPsec documents 💜. Rest easy, legend 🫶.
Table of Contents
1. Introduction ....................................................4
1.1. Summary of Contents of Document ............................4
1.2. Audience ...................................................4
1.3. Related Documents ..........................................5
2. Design Objectives ...............................................5
2.1. Goals/Objectives/Requirements/Problem Description ..........5
2.2. Caveats and Assumptions ....................................6
3. System Overview .................................................7
3.1. What IPsec Does ............................................7
3.2. How IPsec Works ............................................9
3.3. Where IPsec Can Be Implemented ............................10
4. Security Associations ..........................................11
4.1. Definition and Scope ......................................12
4.2. SA Functionality ..........................................16
4.3. Combining SAs .............................................17
4.4. Major IPsec Databases .....................................18
4.4.1. The Security Policy Database (SPD) .................19
4.4.1.1. Selectors .................................26
4.4.1.2. Structure of an SPD Entry .................30
4.4.1.3. More Regarding Fields Associated
with Next Layer Protocols .................32
4.4.2. Security Association Database (SAD) ................34
4.4.2.1. Data Items in the SAD .....................36
4.4.2.2. Relationship between SPD, PFP
flag, packet, and SAD .....................38
4.4.3. Peer Authorization Database (PAD) ..................43
4.4.3.1. PAD Entry IDs and Matching Rules ..........44
4.4.3.2. IKE Peer Authentication Data ..............45
4.4.3.3. Child SA Authorization Data ...............46
4.4.3.4. How the PAD Is Used .......................46
4.5. SA and Key Management .....................................47
4.5.1. Manual Techniques ..................................48
4.5.2. Automated SA and Key Management ....................48
4.5.3. Locating a Security Gateway ........................49
4.6. SAs and Multicast .........................................50
5. IP Traffic Processing ..........................................50
5.1. Outbound IP Traffic Processing
(protected-to-unprotected) ................................52
5.1.1. Handling an Outbound Packet That Must Be
Discarded ..........................................54
5.1.2. Header Construction for Tunnel Mode ................55
5.1.2.1. IPv4: Header Construction for
Tunnel Mode ...............................57
5.1.2.2. IPv6: Header Construction for
Tunnel Mode ...............................59
5.2. Processing Inbound IP Traffic (unprotected-to-protected) ..59
6. ICMP Processing ................................................63
6.1. Processing ICMP Error Messages Directed to an
IPsec Implementation ......................................63
6.1.1. ICMP Error Messages Received on the
Unprotected Side of the Boundary ...................63
6.1.2. ICMP Error Messages Received on the
Protected Side of the Boundary .....................64
6.2. Processing Protected, Transit ICMP Error Messages .........64
7. Handling Fragments (on the protected side of the IPsec
boundary) ......................................................66
7.1. Tunnel Mode SAs that Carry Initial and Non-Initial
Fragments .................................................67
7.2. Separate Tunnel Mode SAs for Non-Initial Fragments ........67
7.3. Stateful Fragment Checking ................................68
7.4. BYPASS/DISCARD Traffic ....................................69
8. Path MTU/DF Processing .........................................69
8.1. DF Bit ....................................................69
8.2. Path MTU (PMTU) Discovery .................................70
8.2.1. Propagation of PMTU ................................70
8.2.2. PMTU Aging .........................................71
9. Auditing .......................................................71
10. Conformance Requirements ......................................71
11. Security Considerations .......................................72
12. IANA Considerations ...........................................72
13. Differences from RFC 2401 .....................................72
14. Acknowledgements ..............................................75
Appendix A: Glossary ..............................................76
Appendix B: Decorrelation .........................................79
B.1. Decorrelation Algorithm ...................................79
Appendix C: ASN.1 for an SPD Entry ................................82
Appendix D: Fragment Handling Rationale ...........................88
D.1. Transport Mode and Fragments ..............................88
D.2. Tunnel Mode and Fragments .................................89
D.3. The Problem of Non-Initial Fragments ......................90
D.4. BYPASS/DISCARD Traffic ....................................93
D.5. Just say no to ports? .....................................94
D.6. Other Suggested Solutions..................................94
D.7. Consistency................................................95
D.8. Conclusions................................................95
Appendix E: Example of Supporting Nested SAs via SPD and
Forwarding Table Entries...............................96
References.........................................................98
Normative References............................................98
Informative References..........................................99
1. Introduction ✨
1.1. Summary of Contents of Document
Okay so this doc is the base architecture for IPsec-compliant systems 🔐. It explains how to provide a set of security services for traffic at the IP layer, for both IPv4 [Pos81a] and IPv6 [DH98] 🌐. It covers the requirements for systems that implement IPsec, the core pieces of those systems, and how everything fits together and fits into the IP environment 🧩. It also talks about the security services IPsec protocols offer, and how you can use them in the IP world 💅.
Now, this doc does not cover every single aspect of IPsec architecture 🙈. Other docs dig into the specialized stuff, like using IPsec in Network Address Translation (NAT) environments and more comprehensive support for IP multicast 🦋. The core pieces are explained in terms of the functionality they basically need to have 💖. Other RFCs (see Section 1.3 for pointers to other documents) define the protocols in (a), (c), and (d) 📚:
- a. Security Protocols -- Authentication Header (AH) and Encapsulating Security Payload (ESP)
- b. Security Associations -- what they are and how they work, how they are managed, associated processing
- c. Key Management -- manual and automated (The Internet Key Exchange (IKE))
- d. Cryptographic algorithms for authentication and encryption
Also, this is not a Security Architecture for the Internet 🙅♀️. It only handles security at the IP layer, using a combo of cryptographic and protocol security mechanisms 🔒.
Quick spelling tea ☕: "IPsec" is the preferred spelling, and it's used throughout this doc and all related IPsec standards 💅. Every other capitalization (like IPSEC, IPSec, or ipsec) is deprecated 💀. But any capitalization of the letters "IPsec" should be understood to refer to the IPsec protocols 🫶.
The keywords MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL, when they appear in this document, are to be interpreted as described in RFC 2119 [Bra97] 👑.
1.2. Audience
The main crowd for this doc is people who implement this IP security tech, or who architect systems that will use it 🧑💻. Technically adept users (end users or system admins) are part of the audience too 🌸. There's a glossary in Appendix A to fill in any vocab gaps 📖. This doc assumes you already know the Internet Protocol (IP), related networking tech, and general info security terms and concepts 🧠.
1.3. Related Documents
As I mentioned earlier, other docs go deep on some of IPsec's components and how they relate to each other 🦋. They include RFCs on these topics 📚:
- a. security protocols -- RFCs describing the Authentication Header (AH) [Ken05b] and Encapsulating Security Payload (ESP) [Ken05a] protocols.
- b. cryptographic algorithms for integrity and encryption -- one RFC that defines the mandatory, default algorithms for use with AH and ESP [Eas05], a similar RFC that defines the mandatory algorithms for use with IKEv2 [Sch05] plus a separate RFC for each cryptographic algorithm.
- c. automatic key management -- RFCs on "The Internet Key Exchange (IKEv2) Protocol" [Kau05] and "Cryptographic Algorithms for Use in the Internet Key Exchange Version 2 (IKEv2)" [Sch05].
2. Design Objectives ✨
2.1. Goals/Objectives/Requirements/Problem Description 💖
okay so IPsec is designed to be interoperable (so everyone's gear can actually talk to each other 🫶), high quality, and cryptographically-based security for IPv4 and IPv6 🔐. The security services on the menu are access control, connectionless integrity, data origin authentication, detection and rejection of replays (a form of partial sequence integrity), confidentiality (via encryption), and limited traffic flow confidentiality. It all happens at the IP layer, so it protects, in a standard way, every protocol that can ride over IP (including IP itself) 🦋
IPsec also includes a spec for minimal firewall functionality, bc access control at the IP layer is essential ✨. Implementations are free to offer fancier firewall stuff, and to carry out the IPsec-mandated functionality using those fancier mechanisms. (Heads up: interoperability may suffer if an IPsec implementation adds extra firewall constraints on traffic flows that can't be negotiated based on the traffic selector features defined in this document and negotiated via IKEv2 💅.) The IPsec firewall function leans on the cryptographically-enforced authentication and integrity provided for all IPsec traffic, so it gives better access control than a firewall that doesn't know IPsec internal parameters plus separate crypto protection would 👑.
Most of the security services come from two traffic security protocols, the Authentication Header (AH) and the Encapsulating Security Payload (ESP), plus cryptographic key management procedures and protocols 🔑. Which IPsec protocols get used in a context, and how, is decided by the users/administrators in that context. The whole goal of the IPsec architecture is to make sure compliant implementations include the services and management interfaces needed to meet the security requirements of a broad user population 🌈.
When IPsec is correctly implemented and deployed, it ought not adversely affect users, hosts, and other Internet components that don't use IPsec for traffic protection 🌸. IPsec security protocols (AH and ESP, and to a lesser extent, IKE) are designed to be cryptographic algorithm independent. This modularity lets you pick different sets of cryptographic algorithms as appropriate, without affecting the other parts of the implementation 🧚. Different user communities may pick different sets (creating cryptographically-enforced cliques) if they need to 🍓.
To help interoperability across the global Internet, a set of default cryptographic algorithms for use with AH and ESP is specified in [Eas05], and a set of mandatory-to-implement algorithms for IKEv2 is specified in [Sch05]. [Eas05] and [Sch05] will be updated periodically to keep up with computational and cryptologic advances. Because these algorithms live in documents separate from the AH, ESP, and IKEv2 specs, they can be updated or replaced without holding up the standardization progress of the rest of the IPsec document suite 🎀. The idea is that using these algorithms with IPsec traffic protection and key management protocols lets system and application developers deploy high quality, Internet-layer, cryptographic security tech 💜.
2.2. Caveats and Assumptions ⭐
ok real talk 🙈: the IPsec protocols and their default crypto algorithms are designed to provide high quality security for Internet traffic. But the security you actually get depends on the quality of the implementation, which is outside the scope of this set of standards. Also, the security of a computer system or network depends on lots of stuff: personnel, physical, procedural, compromising emanations, and computer security practices. So IPsec is only one part of an overall system security architecture 🫶.
Finally, IPsec's security is super dependent on many aspects of the operating environment it runs in. For example, defects in OS security, poor quality random number sources, sloppy system management protocols and practices, etc., can all degrade the security IPsec provides 💀. Same as above, none of these environmental attributes are within the scope of this or other IPsec standards.
3. System Overview 🧚
This section gives a high level description of how IPsec works, the components of the system, and how they fit together to provide the security services noted above. The goal is to help you "picture" the overall process/system, see how it fits into the IP environment, and get context for the later sections, which describe each component in more detail 🔍.
An IPsec implementation operates in a host, as a security gateway (SG), or as an independent device, affording protection to IP traffic. (A security gateway is an intermediate system implementing IPsec, e.g., a firewall or router that has been IPsec-enabled.) More detail on these classes of implementations comes later, in Section 3.3. The protection IPsec offers is based on requirements defined by a Security Policy Database (SPD) established and maintained by a user or system administrator, or by an application operating within constraints set by either of the above. Generally, packets get selected for one of three processing actions based on IP and next layer header information ("Selectors", Section 4.4.1.1) matched against entries in the SPD. Each packet is either PROTECTed using IPsec security services, DISCARDed, or allowed to BYPASS IPsec protection, based on the applicable SPD policies identified by the Selectors 🌟.
3.1. What IPsec Does 🍓
IPsec creates a boundary between unprotected and protected interfaces, for a host or a network (see Figure 1 below). Traffic crossing the boundary is subject to access controls specified by the user or administrator responsible for the IPsec configuration. These controls say whether packets cross the boundary unimpeded, get security services via AH or ESP, or are discarded 🚧.
IPsec security services are offered at the IP layer through selection of appropriate security protocols, cryptographic algorithms, and cryptographic keys. IPsec can protect one or more "paths" (a) between a pair of hosts, (b) between a pair of security gateways, or (c) between a security gateway and a host. A compliant host implementation MUST support (a) and (c) and a compliant security gateway must support all three of these forms of connectivity, since under certain circumstances a security gateway acts as a host 🦋.
Unprotected
^ ^
| |
+-------------|-------|-------+
| +-------+ | | |
| |Discard|<--| V |
| +-------+ |B +--------+ |
................|y..| AH/ESP |..... IPsec Boundary
| +---+ |p +--------+ |
| |IKE|<----|a ^ |
| +---+ |s | |
| +-------+ |s | |
| |Discard|<--| | |
| +-------+ | | |
+-------------|-------|-------+
| |
V V
Protected
Figure 1. Top Level IPsec Processing Model
In this diagram, "unprotected" is an interface that might also be called "black" or "ciphertext". "Protected" is an interface that might also be called "red" or "plaintext". The protected interface noted above may be internal; e.g., in a host implementation of IPsec, the protected interface may link to a socket layer interface presented by the OS. In this document, "inbound" means traffic entering an IPsec implementation via the unprotected interface, or emitted by the implementation on the unprotected side of the boundary and directed towards the protected interface. "Outbound" means traffic entering the implementation via the protected interface, or emitted by the implementation on the protected side of the boundary and directed toward the unprotected interface. An IPsec implementation may support more than one interface on either or both sides of the boundary 🎀.
Note the facilities for discarding traffic on either side of the IPsec boundary, the BYPASS facility that lets traffic transit the boundary without cryptographic protection, and the reference to IKE as a protected-side key and security management function 👑.
IPsec optionally supports negotiation of IP compression [SMPT01], motivated in part by the observation that when encryption is employed within IPsec, it prevents effective compression by lower protocol layers 💜.
3.2. How IPsec Works
okay so IPsec runs on two protocols to do its traffic security magic 🪄: Authentication Header (AH) and Encapsulating Security Payload (ESP). Each one gets a full write-up in its own RFC [Ken05b, Ken05a]. IPsec implementations MUST support ESP and MAY support AH. (AH got bumped down to MAY because experience has shown there are very few situations where ESP can't deliver the security services you need. ESP can even do integrity without confidentiality, so it's basically AH's twin in most contexts 👯♀️)
- The IP Authentication Header (AH) [Ken05b] offers integrity and data origin authentication, with optional (at the discretion of the receiver) anti-replay features. 🛡️
- The Encapsulating Security Payload (ESP) protocol [Ken05a] offers the same set of services, and also offers confidentiality. 🔐 Use of ESP to provide confidentiality without integrity is NOT RECOMMENDED, so don't even go there bestie 🙅♀️ When ESP is used with confidentiality enabled, there are provisions for limited traffic flow confidentiality, i.e., provisions for concealing packet length, and for facilitating efficient generation and discard of dummy packets. 🫣 This capability is likely to be effective primarily in virtual private network (VPN) and overlay network contexts.
- Both AH and ESP offer access control, enforced through the distribution of cryptographic keys and the management of traffic flows as dictated by the Security Policy Database (SPD, Section 4.4.1). 🚪✨
These protocols can be applied individually or in combination with each other to provide IPv4 and IPv6 security services. 🌐 However, most security requirements can be met through the use of ESP by itself, so ESP is kind of the main character here 👑 Each protocol supports two modes of use: transport mode and tunnel mode. In transport mode, AH and ESP provide protection primarily for next layer protocols. In tunnel mode, AH and ESP are applied to tunneled IP packets. The differences between the two modes are discussed in Section 4.1. 🧳
IPsec lets the user (or system administrator) control the granularity at which a security service is offered. 🎛️ For example, you can create a single encrypted tunnel to carry all the traffic between two security gateways, or a separate encrypted tunnel can be created for each TCP connection between each pair of hosts communicating across those gateways. It's giving customization 💅 IPsec, through the SPD management paradigm, incorporates facilities for specifying:
- which security protocol (AH or ESP) to employ, the mode (transport or tunnel), security service options, what cryptographic algorithms to use, and in what combinations to use the specified protocols and services, and
- the granularity at which protection should be applied.
Because most of the security services IPsec provides require cryptographic keys, IPsec relies on a separate set of mechanisms for putting those keys in place. 🔑 This document requires support for both manual and automated distribution of keys. It specifies a specific public-key based approach (IKEv2 [Kau05]) for automated key management, but other automated key distribution techniques MAY be used. 🙌
Note: This document mandates support for several features for which support is available in IKEv2 but not in IKEv1, e.g., negotiation of an SA representing ranges of local and remote ports or negotiation of multiple SAs with the same selectors. Therefore, this document assumes use of IKEv2 or a key and security association management system with comparable features. 📝
3.3. Where IPsec Can Be Implemented
there are SO many ways IPsec can show up 🧚 It can live in a host, or get paired with a router or firewall to become a security gateway, or sit there as an independent security device.
a. Native stack: IPsec may be integrated into the native IP stack. This requires access to the IP source code and is applicable to both hosts and security gateways, although native host implementations benefit the most from this strategy, as explained later (Section 4.4.1, paragraph 6; Section 4.4.1.1, last paragraph). 💻
b. Bump-in-the-stack (BITS): In a "bump-in-the-stack" (BITS) implementation, IPsec is implemented "underneath" an existing implementation of an IP protocol stack, between the native IP and the local network drivers. 🍰 Source code access for the IP stack is not required in this context, which makes this approach appropriate for use with legacy systems. This approach, when it is adopted, is usually employed in hosts.
c. Bump-in-the-wire (BITW): The use of a dedicated, inline security protocol processor is a common design feature of systems used by the military, and of some commercial systems as well. It is sometimes referred to as a "bump-in-the-wire" (BITW) implementation. Such implementations may be designed to serve either a host or a gateway. Usually, the BITW device is itself IP addressable. When supporting a single host, it may be quite analogous to a BITS implementation, but when supporting a router or firewall, it must operate like a security gateway. 🔌
This document often talks about use of IPsec by a host or a security gateway, without caring whether the implementation is native, BITS, or BITW. When the distinctions among these implementation options are significant, the document points to specific implementation approaches. 🎯
A host implementation of IPsec may show up in devices that might not be viewed as "hosts". For example, a router might employ IPsec to protect routing protocols (e.g., BGP) and management functions (e.g., Telnet), without affecting subscriber traffic traversing the router. 🛜 A security gateway might employ separate IPsec implementations to protect its management traffic and subscriber traffic. The architecture described in this document is very flexible! 🦋 For example, a computer with a full-featured, compliant, native OS IPsec implementation should be capable of being configured to protect resident (host) applications and to provide security gateway protection for traffic traversing the computer. That configuration would make use of the forwarding tables and the SPD selection function described in Sections 5.1 and 5.2. 🧩
4. Security Associations ✨
this section lays out the Security Association management requirements for all IPv6 implementations, and for those IPv4 implementations that implement AH, ESP, or both. 🧠 The concept of a "Security Association" (SA) is fundamental to IPsec. Both AH and ESP make use of SAs, and a major function of IKE is establishing and maintaining them. All implementations of AH or ESP MUST support the concept of an SA as described below. The rest of this section covers various aspects of SA management, defining required characteristics for SA policy management and SA management techniques. 📋
4.1. Definition and Scope
an SA is a simplex "connection" that affords security services to the traffic carried by it. 🛣️ Security services are afforded to an SA by the use of AH, or ESP, but not both. If both AH and ESP protection are applied to a traffic stream, then two SAs must be created and coordinated to effect protection through iterated application of the security protocols. To secure typical, bi-directional communication between two IPsec-enabled systems, a pair of SAs (one in each direction) is required. IKE explicitly creates SA pairs in recognition of this common usage requirement. 👯
For an SA used to carry unicast traffic, the Security Parameters Index (SPI) by itself suffices to specify an SA. (For information on the SPI, see Appendix A and the AH and ESP specifications [Ken05b, Ken05a].) However, as a local matter, an implementation may choose to use the SPI in conjunction with the IPsec protocol type (AH or ESP) for SA identification. 🆔 If an IPsec implementation supports multicast, then it MUST support multicast SAs using the algorithm below for mapping inbound IPsec datagrams to SAs. Implementations that support only unicast traffic need not implement this de-multiplexing algorithm. 📦
In many secure multicast architectures, e.g., [RFC3740], a central Group Controller/Key Server unilaterally assigns the Group Security Association's (GSA's) SPI. 👑 This SPI assignment is not negotiated or coordinated with the key management (e.g., IKE) subsystems that reside in the individual end systems that constitute the group. Consequently, it is possible that a GSA and a unicast SA can simultaneously use the same SPI. 😬 A multicast-capable IPsec implementation MUST correctly de-multiplex inbound traffic even in the context of SPI collisions. This is the kind of drama your code has to survive 💀
Each entry in the SA Database (SAD) (Section 4.4.2) must indicate whether the SA lookup makes use of the destination IP address, or the destination and source IP addresses, in addition to the SPI. For multicast SAs, the protocol field is not employed for SA lookups. For each inbound, IPsec-protected packet, an implementation must conduct its search of the SAD such that it finds the entry that matches the "longest" SA identifier. 🔍 In this context, if two or more SAD entries match based on the SPI value, then the entry that also matches based on destination address, or destination and source address (as indicated in the SAD entry) is the "longest" match. This implies a logical ordering of the SAD search as follows:
- Search the SAD for a match on the combination of SPI, destination address, and source address. If an SAD entry matches, then process the inbound packet with that matching SAD entry. Otherwise, proceed to step 2.
- Search the SAD for a match on both SPI and destination address. If the SAD entry matches, then process the inbound packet with that matching SAD entry. Otherwise, proceed to step 3.
- Search the SAD for a match on only SPI if the receiver has chosen to maintain a single SPI space for AH and ESP, and on both SPI and protocol, otherwise. If an SAD entry matches, then process the inbound packet with that matching SAD entry. Otherwise, discard the packet and log an auditable event. 🗑️📝
In practice, an implementation may choose any method (or none at all) to accelerate this search, although its externally visible behavior MUST be functionally equivalent to having searched the SAD in the above order. ⚡ For example, a software-based implementation could index into a hash table by the SPI. The SAD entries in each hash table bucket's linked list could be kept sorted so that the entries with the longest SA identifiers come first in that linked list. Those SAD entries having the shortest SA identifiers could be sorted so that they are the last entries in the linked list. A hardware-based implementation may be able to effect the longest match search intrinsically, using commonly available Ternary Content-Addressable Memory (TCAM) features. 🔧
The indication of whether source and destination address matching is required to map inbound IPsec traffic to SAs MUST be set either as a side effect of manual SA configuration or via negotiation using an SA management protocol, e.g., IKE or Group Domain of Interpretation (GDOI) [RFC3547]. Typically, Source-Specific Multicast (SSM) [HC03] groups use a 3-tuple SA identifier composed of an SPI, a destination multicast address, and source address. An Any-Source Multicast group SA requires only an SPI and a destination multicast address as an identifier. 🎀
Okay so DSCP bits are a whole thing 👀 ([NiBlBaBL98], [Gro02]). If different classes of traffic get sent on the same SA, and the receiver is using the optional anti-replay feature (it exists in both AH and ESP 🛡️), the windowing can end up throwing away the lower-priority packets. Not ideal, bestie 😭 So a sender SHOULD put traffic of different classes, but with the same selector values, on different SAs to support Quality of Service (QoS) appropriately 💅. To make that possible, the IPsec implementation MUST permit establishment and maintenance of multiple SAs between a given sender and receiver, with the same selectors. The sender decides locally how traffic gets split across those parallel SAs for QoS, and IKE doesn't negotiate it 🧚. The receiver MUST process the packets from the different SAs without prejudice 🫶. These requirements apply to both transport and tunnel mode SAs. In tunnel mode, the DSCP values show up in the inner IP header. In transport mode the DSCP value might change en route, but that should not cause problems for IPsec processing, since the value isn't used for SA selection and MUST NOT be checked as part of SA/packet validation. Still, if packets get significantly re-ordered inside an SA (say, because DSCP values changed en route), that may trigger discarding by the receiver because of the anti-replay mechanism 😬
DISCUSSION: Even though the DSCP [NiBlBaBL98, Gro02] and Explicit Congestion Notification (ECN) [RaFlBl01] fields aren't "selectors" in the way this architecture uses that word, the sender still needs a way to direct packets with a given set of DSCP values to the right SA. That mechanism might be called a "classifier" 🎀
As noted above, there are two types of SAs: transport mode and tunnel mode. IKE creates SAs in pairs, so to keep things simple, we require that both SAs in a pair be the same mode, either transport or tunnel 💖
A transport mode SA is typically set up between a pair of hosts to provide end-to-end security services 🌸 When you want security between two intermediate systems along a path (instead of end-to-end IPsec), transport mode MAY be used between security gateways or between a security gateway and a host. When transport mode is used this way, transport mode may also support in-IP tunneling (like IP-in-IP [Per96], Generic Routing Encapsulation (GRE) tunneling [FaLiHaMeTr00], or dynamic routing [ToEgWa04]) over transport mode SAs. To be clear, an intermediate system (like a security gateway) may only use transport mode for packets whose source address (for outbound packets) or destination address (for inbound packets) belongs to the intermediate system itself. The access control functions that make IPsec so useful are heavily limited in this setup, because they can't be applied to the end-to-end headers of packets crossing a transport mode SA used this way. So this approach should be evaluated carefully before you use it in any specific context 🧐
In IPv4, the transport mode security protocol header sits right after the IP header and any options, and before any next layer protocols (like TCP or UDP) 🧩 In IPv6, the security protocol header comes after the base IP header and selected extension headers, but it may appear before or after destination options. It MUST appear before next layer protocols (like TCP, UDP, or Stream Control Transmission Protocol (SCTP)). With ESP, a transport mode SA only protects those next layer protocols, not the IP header or any extension headers before the ESP header. With AH, protection also extends to selected parts of the IP header that come before it, selected parts of extension headers, and selected options (in the IPv4 header, the IPv6 Hop-by-Hop extension header, or the IPv6 Destination extension headers). For more on what AH covers, check the AH specification [Ken05b] 📖
A tunnel mode SA is basically an SA applied to an IP tunnel, with the access controls applied to the headers of the traffic inside the tunnel 🚇 Two hosts MAY set up a tunnel mode SA between themselves. Apart from the two exceptions below, whenever either end of a security association is a security gateway, the SA MUST be tunnel mode. So an SA between two security gateways is usually tunnel mode, and so is an SA between a host and a security gateway 💅 There are two exceptions:
- a) Where traffic is destined for a security gateway (like Simple Network Management Protocol (SNMP) commands), the security gateway is acting as a host, so transport mode is allowed. Here the SA terminates at a host (management) function inside the security gateway, so it deserves different treatment 🙈
- b) As noted above, security gateways MAY support a transport mode SA to protect IP traffic between two intermediate systems along a path, like between a host and a security gateway, or between two security gateways 🌈
There are a bunch of reasons to use tunnel mode for an SA involving a security gateway, and honestly they're all valid 🫠 For example, if there are multiple paths to the same destination behind a security gateway (like via different security gateways), it's important that an IPsec packet gets sent to the security gateway the SA was negotiated with. Also, a packet that might get fragmented en route must have all its fragments delivered to the same IPsec instance for reassembly before cryptographic processing. And when a fragment is processed by IPsec and sent, then fragmented en route, it's critical to have inner and outer headers so the fragmentation state data for the pre- and post-IPsec packet formats is retained. So there are several reasons to use tunnel mode whenever either end of an SA is a security gateway. (Using an IP-in-IP tunnel together with transport mode can also deal with these fragmentation issues, but that setup limits how well IPsec can enforce access control policies on traffic.)
Note: AH and ESP can't be applied in transport mode to IPv4 packets that are fragments. In those cases only tunnel mode can be used. For IPv6, it would be possible to carry a plaintext fragment on a transport mode SA, but for simplicity this restriction also applies to IPv6 packets. See Section 7 for more details on handling plaintext fragments on the protected side of the IPsec barrier 🧚
For a tunnel mode SA, there's an "outer" IP header that specifies the IPsec processing source and destination, plus an "inner" IP header that specifies the (apparently) ultimate source and destination for the packet 🎁 The security protocol header goes after the outer IP header and before the inner IP header. With AH in tunnel mode, parts of the outer IP header get protection (as above), and so does the entire tunneled IP packet (all of the inner IP header is protected, along with the next layer protocols). With ESP, only the tunneled packet is protected, not the outer header 🔐
In summary:
- a) A host implementation of IPsec MUST support both transport and tunnel mode. This is true for native, BITS, and BITW implementations for hosts 💜
- b) A security gateway MUST support tunnel mode and MAY support transport mode. If it supports transport mode, that should be used only when the security gateway is acting as a host (like for network management), or to provide security between two intermediate systems along a path 🦋
4.2. SA Functionality ✨
The set of security services an SA offers depends on the security protocol selected, the SA mode, the endpoints of the SA, and which optional services are elected within the protocol 💅
For example, both AH and ESP offer integrity and authentication services, but the coverage differs between the two protocols and between transport and tunnel mode 👀 If the integrity of an IPv4 option or an IPv6 extension header has to be protected en route between sender and receiver, AH can provide that, except for IP or extension headers that may change in ways the sender can't predict. However, in some contexts the same security can be achieved by applying ESP to a tunnel carrying the packet 🫶
The granularity of access control depends on the choice of selectors that define each SA. Also, the authentication means IPsec peers use (for example, while creating an IKE SA as opposed to a child SA) affects the granularity of the access control afforded 🔥
If confidentiality is selected, an ESP (tunnel mode) SA between two security gateways can offer partial traffic flow confidentiality 🌸 Tunnel mode lets the inner IP headers be encrypted, hiding the identities of the (ultimate) traffic source and destination. ESP payload padding can also be invoked to hide packet sizes, which further conceals the external characteristics of the traffic 🙈 Similar traffic flow confidentiality can be offered when a mobile user is given a dynamic IP address in a dialup context and sets up a (tunnel mode) ESP SA to a corporate firewall acting as a security gateway 💼 Just note that fine-granularity SAs are generally more vulnerable to traffic analysis than coarse-granularity ones carrying traffic from many subscribers 🕵️
Note: A compliant implementation MUST NOT allow instantiation of an ESP SA that employs both NULL encryption and no integrity algorithm. An attempt to negotiate such an SA is an auditable event for both initiator and responder. The audit log entry for this event SHOULD include the current date/time, the local IKE IP address, and the remote IKE IP address. The initiator SHOULD record the relevant SPD entry 🚨
4.3. Combining SAs 🎀
This document doesn't require support for nested security associations or for what RFC 2401 [RFC2401] called "SA bundles" 🧩 You can still get these features by configuring both the SPD and the local forwarding functions (for inbound and outbound traffic) appropriately, but that capability sits outside the IPsec module and is therefore outside the scope of this specification. As a result, managing nested/bundled SAs can be more complex and less assured than under the model implied by RFC 2401 [RFC2401] 😅 An implementation that supports nested SAs SHOULD provide a management interface that lets a user or administrator express the nesting requirement, and then create the appropriate SPD entries and forwarding table entries to make the required processing happen. (See Appendix E for an example of how to configure nested SAs 💖)
4.4. Major IPsec Databases ✨
okay so this is where we talk about the databases 🗄️💖 A lot of how an IPsec implementation handles IP traffic is just a local vibe, so it isn't standardized. BUT some of the outside stuff has to be standardized so everyone can actually talk to each other 🫶 and so there's a minimum management capability that makes IPsec usable at all. This section gives a general model for processing IP traffic with IPsec to support those goals. The model is nominal, so implementations don't need to match its details exactly. Their external behavior MUST correspond to the externally observable characteristics of this model to be compliant 🎀
There are three nominal databases in this model: the Security Policy Database (SPD), the Security Association Database (SAD), and the Peer Authorization Database (PAD). The SPD holds the policies that decide the fate of all IP traffic coming in or going out of a host or security gateway (Section 4.4.1). The SAD holds the parameters tied to each established (keyed) SA (Section 4.4.2). The PAD is the link between an SA management protocol (such as IKE) and the SPD (Section 4.4.3). 🧚
Multiple Separate IPsec Contexts
If an IPsec implementation acts as a security gateway for multiple subscribers, it MAY implement multiple separate IPsec contexts. Each context MAY have and MAY use completely independent identities, policies, key management SAs, and/or IPsec SAs. This is mostly a local implementation matter 💅 BUT a way to associate inbound (SA) proposals with local contexts is required. So if the key management protocol in use supports it, context identifiers MAY be conveyed from initiator to responder in the signaling messages, and the result is that IPsec SAs get created with a binding to a particular context. For example, a security gateway that provides VPN service to multiple customers can associate each customer's traffic with the correct VPN. Iconic routing 🌸
Forwarding vs Security Decisions
The IPsec model here has a clear separation between forwarding (routing) and security decisions, so it fits a wide range of contexts where IPsec might be used 🦋 Forwarding can be trivial, like when there are only two interfaces, or it can be complex, e.g., if the context employs a sophisticated forwarding function. IPsec only assumes that outbound and inbound traffic that has gone through IPsec processing is forwarded in a way that's consistent with the context IPsec is running in. Support for nested SAs is optional. If it's required, it takes coordination between forwarding tables and SPD entries so a packet can cross the IPsec boundary more than once 🔥
"Local" vs "Remote"
In this document, the terms "Local" and "Remote" are used for policy rules when talking about IP addresses and ports. "Local" means the entity being protected by an IPsec implementation, so the "source" address/port of outbound packets or the "destination" address/port of inbound packets. "Remote" means a peer entity or peer entities. The terms "source" and "destination" are reserved for packet header fields 👑
"Non-initial" vs "Initial" Fragments
Throughout this document, "non-initial fragments" means fragments that don't contain all of the selector values that might be needed for access control (e.g., they might not contain Next Layer Protocol, source and destination ports, ICMP message type/code, Mobility Header type). "Initial fragment" means a fragment that contains all the selector values needed for access control. Heads up though: for IPv6, which fragment contains the Next Layer Protocol and ports (or ICMP message type/code or Mobility Header type [Mobip]) depends on the kind and number of extension headers present. In this context, the "initial fragment" might not be the first fragment 🙈
4.4.1. The Security Policy Database (SPD)
okay this one's a big deal 😭 An SA is a management construct used to enforce security policy for traffic crossing the IPsec boundary. So a key piece of SA processing is an underlying Security Policy Database (SPD) that says what services get offered to IP datagrams and how. The form of the database and its interface are out of scope for this spec. BUT this section does spell out the minimum management functionality that has to exist, so a user or system administrator can control whether and how IPsec gets applied to traffic sent or received by a host or passing through a security gateway. The SPD, or the relevant caches, must be consulted while processing all traffic (inbound and outbound), including traffic that IPsec doesn't protect, as long as it crosses the IPsec boundary. That includes IPsec management traffic like IKE. An IPsec implementation MUST have at least one SPD, and it MAY support multiple SPDs if that makes sense for the context it runs in. There's no requirement to keep SPDs on a per-interface basis, the way RFC 2401 [RFC2401] specified. BUT if an implementation supports multiple SPDs, then it MUST include an explicit SPD selection function that gets invoked to pick the right SPD for outbound traffic processing. The inputs to this function are the outbound packet and any local metadata (e.g., the interface the packet arrived on) needed to make the selection. The output is an SPD identifier (SPD-ID) 🎀
The SPD is an ordered database, like the Access Control Lists (ACLs) or packet filters you'd find in firewalls, routers, and so on 💅 The ordering matters because entries often overlap, thanks to (non-trivial) ranges as selector values. So a user or administrator MUST be able to order the entries to express the access control policy they want. There's no way to impose a general, canonical order on SPD entries, because wildcards are allowed for selector values and the different selector types aren't hierarchically related. Literally no shortcut here 🙃
Processing Choices: DISCARD, BYPASS, PROTECT
An SPD must tell apart the traffic that gets IPsec protection from the traffic that's allowed to bypass IPsec. This applies to the IPsec protection a sender applies and to the IPsec protection that must be present at the receiver. For any outbound or inbound datagram, there are three possible processing choices: DISCARD, BYPASS IPsec, or PROTECT using IPsec. DISCARD is for traffic that isn't allowed to cross the IPsec boundary (in the specified direction). BYPASS is for traffic that's allowed to cross the boundary without IPsec protection. PROTECT is for traffic that gets IPsec protection, and for that traffic the SPD must specify the security protocols to use, their mode, the security service options, and the cryptographic algorithms to use ✨
SPD-S, SPD-I, SPD-O
An SPD is logically split into three pieces 🍓 The SPD-S (secure traffic) has entries for all traffic subject to IPsec protection. SPD-O (outbound) has entries for all outbound traffic that's to be bypassed or discarded. SPD-I (inbound) is applied to inbound traffic that will be bypassed or discarded. All three can be decorrelated (with the exception noted above for native host implementations) to make caching easier. If an IPsec implementation supports only one SPD, then that SPD consists of all three parts. If multiple SPDs are supported, some of them may be partial, e.g., some SPDs might contain only SPD-I entries, to control inbound bypassed traffic on a per-interface basis. The split lets SPD-I get consulted without having to consult SPD-S for that traffic. Since SPD-I is just a part of the SPD, if a packet looked up in SPD-I can't be matched to an entry there, then the packet MUST be discarded. For outbound traffic, if no match is found in SPD-S, then SPD-O must be checked to see if the traffic should be bypassed. Similarly, if SPD-O is checked first and no match is found, then SPD-S must be checked. In an ordered, non-decorrelated SPD, the entries for SPD-S, SPD-I, and SPD-O are interleaved, so there's just one lookup in the SPD 🌈
SPD Entries
Each SPD entry specifies packet disposition as BYPASS, DISCARD, or PROTECT. The entry is keyed by a list of one or more selectors, and the SPD holds an ordered list of these entries 🧚 The required selector types are defined in Section 4.4.1.1. These selectors define the granularity of the SAs that get created in response to an outbound packet or in response to a proposal from a peer. The detailed structure of an SPD entry is described in Section 4.4.1.2. Every SPD SHOULD have a nominal, final entry that matches anything otherwise unmatched and discards it 💜
The SPD MUST let a user or administrator specify policy entries as follows:
- SPD-I: For inbound traffic that is to be bypassed or discarded, the entry consists of the values of the selectors that apply to the traffic to be bypassed or discarded.
- SPD-O: For outbound traffic that is to be bypassed or discarded, the entry consists of the values of the selectors that apply to the traffic to be bypassed or discarded.
- SPD-S: For traffic that is to be protected using IPsec, the entry consists of the values of the selectors that apply to the traffic to be protected via AH or ESP, controls on how to create SAs based on these selectors, and the parameters needed to effect this protection (e.g., algorithms, modes, etc.). Note that an SPD-S entry also contains information such as the "populate from packet" (PFP) flag (see paragraphs below on "How To Derive the Values for an SAD entry") and bits indicating whether the SA lookup makes use of the local and remote IP addresses in addition to the SPI (see AH [Ken05b] or ESP [Ken05a] specifications). 🦋
Representing Directionality in an SPD Entry
For traffic protected by IPsec, the Local and Remote addresses and ports in an SPD entry get swapped to show which way the traffic is going 🔄, matching IKE conventions. The protocols IPsec deals with usually need symmetric SAs with the Local/Remote IP addresses flipped. ICMP is the exception 🙈 because there's often no two-way authorization requirement. Still, for uniformity and simplicity, ICMP SPD entries are written the same way as everything else ✨. Also, ICMP, Mobility Header, and non-initial fragments don't have port fields. ICMP has message type and code, and Mobility Header has a mobility header type, so SPD entries have their own ways to express access controls for those protocols instead of the usual port controls 💅. For bypassed or discarded traffic, separate inbound and outbound entries are supported, e.g., to permit unidirectional flows if required 🦋.
OPAQUE and ANY
Every selector in an SPD entry has two special values on top of the literal values that define a match: ANY and OPAQUE 👑. ANY is the wildcard. It matches any value in the matching field of the packet, or packets where that field isn't present or is obscured 🫶. OPAQUE means the selector field can't be examined, because it may not be in a fragment, it doesn't exist for the given Next Layer Protocol, or earlier IPsec processing may have encrypted the value 🔐. ANY also covers OPAQUE. So you only need OPAQUE when you have to tell apart "any allowed value" from "the field is missing or unavailable (e.g., due to encryption)" 🧠.
How to Derive the Values for an SAD Entry
For each selector in an SPD entry, the entry says how to work out the matching values for a new SA Database (SAD, see Section 4.4.2) entry, using the SPD and the packet 🧩. The goal is to let an SAD entry and an SPD cache entry get created from specific selector values in the packet, or from the matching SPD entry. Outbound traffic has SPD-S cache entries and SPD-O cache entries 📤. Inbound traffic that isn't protected by IPsec has SPD-I cache entries, and the SAD is the cache for inbound IPsec-protected traffic (see Section 4.4.2) 📥. If IPsec processing is specified for an entry, a "populate from packet" (PFP) flag may be asserted for one or more of the selectors in the SPD entry (Local IP address; Remote IP address; Next Layer Protocol; and, depending on Next Layer Protocol, Local port and Remote port, or ICMP type/code, or Mobility Header type) 🎀. If the flag is asserted for a given selector X, the SA to be created should take its value for X from the packet. Otherwise, the SA should take its value(s) for X from the SPD entry 🎯. Note: In the non-PFP case, the selector values negotiated by the SA management protocol (e.g., IKEv2) may be a subset of those in the SPD entry, depending on the SPD policy of the peer 🤝. Also, whether one flag covers source port, ICMP type/code, and Mobility Header (MH) type, or a separate flag is used for each, is a local matter 🏠.
The example below shows the PFP flag in action on a security gateway or a BITS/BITW implementation 🌸. Say an SPD entry allows a Remote address that's a range of IPv4 addresses: 192.0.2.1 to 192.0.2.10. Now an outbound packet shows up with a destination address of 192.0.2.3, and no existing SA can carry it. The new SA's value could be either of the two below, depending on what the SPD entry says the source of that selector value is 👀:
PFP flag value example of new
for the Remote SAD dest. address
addr. selector selector value
--------------- ------------
a. PFP TRUE 192.0.2.3 (one host)
b. PFP FALSE 192.0.2.1 to 192.0.2.10 (range of hosts)
If the SPD entry above had a value of ANY for the Remote address, then the SAD selector value would have to be ANY for case (b), but it would still look like the example for case (a). So the PFP flag can be used to stop an SA from being shared, even among packets that match the same SPD entry 🚫.
Management Interface
For every IPsec implementation, there MUST be a management interface that lets a user or system administrator manage the SPD 🛠️. The interface must let the user (or administrator) specify the security processing applied to every packet that crosses the IPsec boundary. (In a native host IPsec implementation that uses a socket interface, the SPD may not need to be checked on a per-packet basis, as noted at the end of Section 4.4.1.1 and in Section 5 💭.) The management interface for the SPD MUST allow creation of entries that match the selectors defined in Section 4.4.1.1, and MUST support (total) ordering of these entries, as seen through this interface 📋. The SPD entries' selectors are basically the ACLs or packet filters you'd find in a stateless firewall or packet filtering router, which are managed that way too 🔥.
On hosts, applications MAY be allowed to create SPD entries. (How such requests get signaled to the IPsec implementation is outside the scope of this standard 🙃.) However, the system administrator MUST be able to specify whether or not a user or application can override (default) system policies 👑. The form of the management interface isn't specified by this document, and it may be different for hosts vs. security gateways. Within hosts, the interface may also differ between socket-based and BITS implementations 🧩. Still, this document does specify a standard set of SPD elements that all IPsec implementations MUST support 💜.
Decorrelation
The processing model in this document assumes you can decorrelate overlapping SPD entries so they can be cached, which makes outbound traffic processing more efficient in security gateways and BITS/BITW implementations ⚡. Decorrelation [CoSa04] is only a way to improve performance and simplify the processing description 🧹. This RFC does not require a compliant implementation to use decorrelation. For example, native host implementations usually cache implicitly, because they bind SAs to socket interfaces, so there's no need to be able to decorrelate SPD entries in those implementations 🦋.
Note: Unless otherwise qualified, "SPD" refers to the body of policy information in either its ordered or its decorrelated (unordered) state 📚. Appendix B gives an algorithm you can use to decorrelate SPD entries, but any algorithm that produces equivalent output is fine 🧮. When an SPD entry is decorrelated, all the resulting entries MUST be linked together, so that every member of the group derived from one SPD entry (before decorrelation) can be placed into caches and into the SAD at the same time 🔗. For example, suppose you start with entry A (from an ordered SPD), and decorrelating it gives you entries A1, A2, and A3. When a packet comes along that matches, say, A2, and triggers the creation of an SA, the SA management protocol (e.g., IKEv2) negotiates A. Then all three decorrelated entries, A1, A2, and A3, get placed in the appropriate SPD-S cache and linked to the SA 💖. The point is that using a decorrelated SPD shouldn't create more SAs than you'd get from a not-decorrelated SPD 🙌.
If you use a decorrelated SPD, there are three options for what an initiator sends to a peer via an SA management protocol (e.g., IKE) 🎁. Sending the complete set of linked, decorrelated entries that were selected from the SPD gives the peer the best possible information for picking the right SPD entry on its end, especially if the peer has also decorrelated its SPD 🥰. But if a lot of decorrelated entries are linked, that can create large packets for SA negotiation, and so fragmentation problems for the SA management protocol 😬.
Another option is to keep the original entry from the (correlated) SPD and pass that to the SA management protocol. Passing the correlated SPD entry keeps the use of a decorrelated SPD a local matter that peers can't see, and it avoids possible fragmentation concerns 🙂. The tradeoff is that it gives a responder less precise information to match against its own SPD 🤷♀️.
There's also a middle ground: send a subset of the complete set of linked, decorrelated SPD entries ⚖️. This can avoid the fragmentation problems mentioned above and still give better information than the original correlated entry. The major downside is that it may cause additional SAs to be created later, since only a subset of the linked, decorrelated entries went to the peer 🌀. Implementers are free to use any of the approaches above ✨.
A responder uses the traffic selector proposals it gets via an SA management protocol to pick an appropriate entry in its SPD 🎯. The goal of the matching is to select an SPD entry and create an SA that closely matches the initiator's intent, so that traffic going over the resulting SA gets accepted at both ends 🫶. If the responder uses a decorrelated SPD, it SHOULD use the decorrelated SPD entries for matching, because that generally results in SAs that are more likely to match the intent of both peers 💅. If the responder has a correlated SPD, it SHOULD match the proposals against the correlated entries 📑. For IKEv2, a decorrelated SPD gives a responder the best chance to generate a "narrowed" response 🦋.
In every case, when a decorrelated SPD is available, the decorrelated entries are used to populate the SPD-S cache 🧁. If the SPD isn't decorrelated, caching isn't allowed, and an ordered search of SPD MUST be performed to verify that inbound traffic arriving on an SA is consistent with the access control policy expressed in the SPD 🔍.
Handling Changes to the SPD While the System Is Running
If a change is made to the SPD while the system is running, a check SHOULD be made of how that change affects extant SAs 👀. An implementation SHOULD check the impact of an SPD change on extant SAs, and SHOULD provide a user/administrator with a mechanism for configuring what actions to take, e.g., delete an affected SA, allow an affected SA to continue unchanged, etc. ⚙️✨
4.4.1.1. Selectors 🎀
Okay so an SA can be super fine-grained or super coarse-grained 💅, depending on the selectors that decide which traffic it covers ✨. All traffic between two hosts could ride on one SA and get one uniform set of security services, which is clean and simple 🎀. Or that same host pair could split its traffic across multiple SAs based on the app being used (the Next Layer Protocol and related fields, like ports 🦋), with different SAs offering different security services 🌈. Same energy for gateways: all traffic between a pair of security gateways could sit on a single SA, or each communicating host pair could get its own SA 🫶. The following selector parameters MUST be supported by all IPsec implementations so you can actually control SA granularity 👑. Also, Local and Remote addresses should either both be IPv4 or both be IPv6, but never a mix 🙈. And the Local/Remote port selectors (plus ICMP message type and code, and Mobility Header type) may be labeled as OPAQUE 🫣, which helps when those fields are inaccessible because of packet fragmentation 💀.
- Remote IP Address(es) (IPv4 or IPv6) 🌸: This is a list of ranges of IP addresses (unicast, broadcast (IPv4 only)). It lets you express a single IP address (as a trivial range), a list of addresses (each one a trivial range), a range of addresses (low and high values, inclusive), and the most generic form, a list of ranges 🧚. Address ranges exist so more than one remote system can share the same SA, like systems sitting behind a security gateway 💖.
- Local IP Address(es) (IPv4 or IPv6) 🍓: This is a list of ranges of IP addresses (unicast, broadcast (IPv4 only)). Same deal: a single address, a list, a range, or a list of ranges 🎀. Address ranges let more than one source system share the same SA, like systems behind a security gateway 💜. Local means the address(es) being protected by this implementation (or policy entry) 🛡️.
Note: The SPD does not include support for multicast address entries. To support multicast SAs, an implementation should make use of a Group SPD (GSPD) as defined in [RFC3740]. GSPD entries require a different structure, i.e., one cannot use the symmetric relationship associated with local and remote address values for unicast SAs in a multicast context. Specifically, outbound traffic directed to a multicast address on an SA would not be received on a companion, inbound SA with the multicast address as the source. ⚠️ Multicast is a whole different vibe, bestie 😭.
- Next Layer Protocol 🦋: Obtained from the IPv4 "Protocol" or the IPv6 "Next Header" fields. This is an individual protocol number, ANY, or for IPv6 only, OPAQUE. The Next Layer Protocol is whatever comes after any IP extension headers that are present. To make locating it easier, there SHOULD be a mechanism for configuring which IPv6 extension headers to skip. The default configuration for which protocols to skip SHOULD include the following protocols: 0 (Hop-by-hop options), 43 (Routing Header), 44 (Fragmentation Header), and 60 (Destination Options). Note: The default list does NOT include 51 (AH) or 50 (ESP). From a selector lookup point of view, IPsec treats AH and ESP as Next Layer Protocols 🧠.
Several additional selectors depend on the Next Layer Protocol value 👀:
- If the Next Layer Protocol uses two ports (as do TCP, UDP, SCTP, and others), then there are selectors for Local and Remote Ports. Each of these selectors has a list of ranges of values. Note that the Local and Remote ports may not be available in the case of receipt of a fragmented packet or if the port fields have been protected by IPsec (encrypted); thus, a value of OPAQUE also MUST be supported. Note: In a non-initial fragment, port values will not be available. If a port selector specifies a value other than ANY or OPAQUE, it cannot match packets that are non-initial fragments. If the SA requires a port value other than ANY or OPAQUE, an arriving fragment without ports MUST be discarded. (See Section 7, "Handling Fragments".) 🔥
- If the Next Layer Protocol is a Mobility Header, then there is a selector for IPv6 Mobility Header message type (MH type) [Mobip]. This is an 8-bit value that identifies a particular mobility message. Note that the MH type may not be available in the case of receipt of a fragmented packet. (See Section 7, "Handling Fragments".) For IKE, the IPv6 Mobility Header message type (MH type) is placed in the most significant eight bits of the 16-bit local "port" selector. 🦋
- If the Next Layer Protocol value is ICMP, then there is a 16-bit selector for the ICMP message type and code. The message type is a single 8-bit value, which defines the type of an ICMP message, or ANY. The ICMP code is a single 8-bit value that defines a specific subtype for an ICMP message. For IKE, the message type is placed in the most significant 8 bits of the 16-bit selector and the code is placed in the least significant 8 bits. This 16-bit selector can contain a single type and a range of codes, a single type and ANY code, and ANY type and ANY code. Given a policy entry with a range of Types (T-start to T-end) and a range of Codes (C-start to C-end), and an ICMP packet with Type t and Code c, an implementation MUST test for a match using:
(T-start*256) + C-start <= (t*256) + c <= (T-end*256) +
C-end
Note that the ICMP message type and code may not be available in the case of receipt of a fragmented packet. (See Section 7, "Handling Fragments".) 🏓
- Name 🏷️: This is not a selector like the others above. It is not acquired from a packet. A name may be used as a symbolic identifier for an IPsec Local or Remote address. Named SPD entries are used in two ways, bestie 👑:
- A named SPD entry is used by a responder (not an initiator) in support of access control when an IP address would not be appropriate for the Remote IP address selector, e.g., for "road warriors". The name used to match this field is communicated during the IKE negotiation in the ID payload. In this context, the initiator's Source IP address (inner IP header in tunnel mode) is bound to the Remote IP address in the SAD entry created by the IKE negotiation. This address overrides the Remote IP address value in the SPD, when the SPD entry is selected in this fashion. All IPsec implementations MUST support this use of names. 💖
- A named SPD entry may be used by an initiator to identify a user for whom an IPsec SA will be created (or for whom traffic may be bypassed). The initiator's IP source address (from inner IP header in tunnel mode) is used to replace the following if and when they are created:
- local address in the SPD cache entry
- local address in the outbound SAD entry
- remote address in the inbound SAD entry
Support for this use is optional for multi-user, native host implementations and not applicable to other implementations. Note that this name is used only locally; it is not communicated by the key management protocol. Also, name forms other than those used for case 1 above (responder) are applicable in the initiator context (see below). ✨
An SPD entry can contain both a name (or a list of names) and also values for the Local or Remote IP address.
For case 1, responder, the identifiers employed in named SPD entries are one of the following four types:
- a. a fully qualified user name string (email), e.g.,
mozart@foo.example.com(this corresponds to ID_RFC822_ADDR in IKEv2) 📧 - b. a fully qualified DNS name, e.g.,
foo.example.com(this corresponds to ID_FQDN in IKEv2) 🌐 - c. X.500 distinguished name, e.g., [WaKiHo97],
CN = Stephen T. Kent, O = BBN Technologies, SP = MA, C = US(this corresponds to ID_DER_ASN1_DN in IKEv2, after decoding) 🗂️ - d. a byte string (this corresponds to Key_ID in IKEv2) 🔑
For case 2, initiator, the identifiers employed in named SPD entries are of type byte string. They are likely to be Unix UIDs, Windows security IDs, or something similar, but could also be a user name or account name. In all cases, this identifier is only of local concern and is not transmitted. 🤫
The IPsec implementation context determines how selectors are used 🧩. For example, a native host implementation typically makes use of a socket interface. When a new connection is established, the SPD can be consulted and an SA bound to the socket. Thus, traffic sent via that socket need not result in additional lookups to the SPD (SPD-O and SPD-S) cache 🦋. In contrast, a BITS, BITW, or security gateway implementation needs to look at each packet and perform an SPD-O/SPD-S cache lookup based on the selectors 🔥.
4.4.1.2. Structure of an SPD Entry ✨
okay so this section is the prose tour of what a single SPD entry looks like 💅 there's also an ASN.1 example in Appendix C if you're into that 🧚
this part is written so it maps straight onto IKE payloads, so the policy in an SPD entry can get negotiated through IKE 🫶 the tea is that the version of IKEv2 published alongside this document [Kau05] doesn't line up perfectly with the SPD semantics 😭 IKEv2 doesn't let you negotiate one SA that binds multiple pairs of local and remote addresses and ports together. instead, when you negotiate several local and remote addresses and ports for one SA, IKEv2 treats them as unordered sets that can be mixed and matched in any way 🙈 so until IKE gives us a way to express SPD selector sets properly, users MUST NOT put multiple selector sets in a single SPD entry unless their access control intent actually fits that IKE "mix and match" behavior 🚫 an implementation MAY warn users when they build an SPD entry with multiple selector sets whose syntax hints at a possible conflict with current IKE semantics. it's a little heads up so nobody gets caught off guard 🎀
the management GUI can get fancy too. it might offer address prefixes as well as ranges, plus symbolic names for protocols, ports, and so on 🌸 (don't mix up symbolic names in a management interface with the SPD selector "Name" 🙅♀️) also, Remote/Local only apply to IP addresses and ports, not to ICMP message type/code or Mobility Header type ✨ and if the reserved, symbolic selector value OPAQUE or ANY is used for a selector type, that value is the only one allowed in the list for that selector, and it must appear only once in that list 👑 ANY and OPAQUE are just local syntax conventions though. IKEv2 negotiates them using these ranges:
ANY: start = 0 end = <max>
OPAQUE: start = <max> end = 0
an SPD is an ordered list of entries, and each entry has the following fields 🦋
- Name -- a list of IDs. this quasi-selector is optional 💜 the forms that MUST be supported are described above in Section 4.4.1.1 under "Name".
- PFP flags -- one per traffic selector. a given flag, e.g., for Next Layer Protocol, applies to that selector across all "selector sets" (see below) in an SPD entry. when an SA gets created, each flag says whether the corresponding traffic selector should be instantiated from the matching field in the packet that triggered the SA creation, or from the value(s) in the corresponding SPD entry (see Section 4.4.1, "How to Derive the Values for an SAD Entry") 🔥 whether one flag covers things like source port, ICMP type/code, and MH type, or whether each gets its own flag, is a local matter 🤷♀️ the PFP flags exist for:
- Local Address
- Remote Address
- Next Layer Protocol
- Local Port, or ICMP message type/code or Mobility Header type (depending on the next layer protocol)
- Remote Port, or ICMP message type/code or Mobility Header type (depending on the next layer protocol)
- One to N selector sets that correspond to the "condition" for applying a particular IPsec action. each selector set contains:
- Local Address
- Remote Address
- Next Layer Protocol
- Local Port, or ICMP message type/code or Mobility Header type (depending on the next layer protocol)
- Remote Port, or ICMP message type/code or Mobility Header type (depending on the next layer protocol)
Note: the "next protocol" selector is a single individual value in a selector set entry (unlike the local and remote IP addresses) 💅 this matches how IKEv2 negotiates the Traffic Selector (TS) values for an SA, and it makes sense because you may need to tie different port fields to different protocols 🧚 you can associate multiple protocols (and ports) with a single SA by listing multiple selector sets for that SA ✨
- Processing info -- which action is required: PROTECT, BYPASS, or DISCARD 🍓 there's just one action that goes with all the selector sets, not a separate action for each set. if the required processing is PROTECT, the entry also contains the following info:
- IPsec mode -- tunnel or transport
- (if tunnel mode) local tunnel address -- for a non-mobile host with just one interface, this is straightforward; with multiple interfaces, it MUST be statically configured 🙈 hmm, wait, careful: that word isn't here. The original says "this must be statically configured." So keep lowercase "must".
- (if tunnel mode) remote tunnel address -- there's no standard way to determine this. see 4.5.3, "Locating a Security Gateway" 🫠
- Extended Sequence Number -- is this SA using extended sequence numbers?
- stateful fragment checking -- is this SA using stateful fragment checking? (see Section 7 for more details) 🔍
- Bypass DF bit (T/F) -- applicable to tunnel mode SAs
- Bypass DSCP (T/F) or map to unprotected DSCP values (array) if needed to restrict bypass of DSCP values -- applicable to tunnel mode SAs
- IPsec protocol -- AH or ESP
- algorithms -- which ones to use for AH, which ones to use for ESP, which ones to use for combined mode, ordered by decreasing priority 🎀
it's a local matter what info gets kept about handling existing SAs when the SPD changes 🦋
4.4.1.3. More Regarding Fields Associated with Next Layer Protocols 🌈
okay this part is about the extra selectors that tag along with fields in the Next Layer Protocol header 💖 a particular Next Layer Protocol can have zero, one, or two selectors. sometimes there won't be both local and remote selectors for the fields that depend on the Next Layer Protocol 😭 the IPv6 Mobility Header only has a Mobility Header message type. AH and ESP have no further selector fields. a system might be willing to send an ICMP message type and code that it doesn't want to receive 👀 in the descriptions below, "port" means a field that depends on the Next Layer Protocol 🫶
A. if a Next Layer Protocol has no "port" selectors, then the Local and Remote "port" selectors are set to OPAQUE in the relevant SPD entry, e.g.,
Local's
next layer protocol = AH
"port" selector = OPAQUE
Remote's
next layer protocol = AH
"port" selector = OPAQUE
B. even if a Next Layer Protocol has only one selector, e.g., Mobility Header type, the Local and Remote "port" selectors are used to show whether a system is willing to send and/or receive traffic with the specified "port" values 🦋 for example, if Mobility Headers of a specified type are allowed to be sent and received via an SA, the relevant SPD entry gets set like this:
Local's
next layer protocol = Mobility Header
"port" selector = Mobility Header message type
Remote's
next layer protocol = Mobility Header
"port" selector = Mobility Header message type
if Mobility Headers of a specified type are allowed to be sent but NOT received via an SA, the relevant SPD entry is set like this:
Local's
next layer protocol = Mobility Header
"port" selector = Mobility Header message type
Remote's
next layer protocol = Mobility Header
"port" selector = OPAQUE
and if Mobility Headers of a specified type are allowed to be received but NOT sent via an SA, the relevant SPD entry is set like this:
Local's
next layer protocol = Mobility Header
"port" selector = OPAQUE
Remote's
next layer protocol = Mobility Header
"port" selector = Mobility Header message type
C. if a system is willing to send traffic with a particular "port" value but NOT receive traffic with that kind of port value, its traffic selectors get set like this in the relevant SPD entry 🌸
Local's
next layer protocol = ICMP
"port" selector = <specific ICMP type & code>
Remote's
next layer protocol = ICMP
"port" selector = OPAQUE
D. to show that a system is willing to receive traffic with a particular "port" value but NOT send that kind of traffic, its traffic selectors get set like this in the relevant SPD entry 🧚
Local's
next layer protocol = ICMP
"port" selector = OPAQUE
Remote's
next layer protocol = ICMP
"port" selector = <specific ICMP type & code>
for example, say a security gateway is happy to let the systems behind it send ICMP traceroutes, but doesn't want outside systems running ICMP traceroutes against the systems behind it 💀 then the security gateway's traffic selectors get set like this in the relevant SPD entry:
Local's
next layer protocol = 1 (ICMPv4)
"port" selector = 30 (traceroute)
Remote's
next layer protocol = 1 (ICMPv4)
"port" selector = OPAQUE
4.4.2. Security Association Database (SAD) 💖
okay so every IPsec implementation has a nominal Security Association Database (SAD) 🎀 and each entry in it defines the parameters for one SA. every SA gets its own SAD entry, no exceptions 💅 for outbound processing, SAD entries get pointed to by entries in the SPD-S part of the SPD cache. for inbound processing, unicast SAs are looked up by the SPI alone, or by the SPI together with the IPsec protocol type. if an implementation supports multicast, the lookup uses the SPI plus the destination address, or the SPI plus the destination and source addresses 👀 (the algorithm that MUST be used for mapping inbound IPsec datagrams to SAs is in Section 4.1, so go check it 🧚). each SAD entry has the parameters below. they should all be present except where otherwise noted, e.g., AH Authentication algorithm. and this isn't a MIB, it's just the minimal list of data items you need to support an SA in an IPsec implementation ✨
For each of the selectors defined in Section 4.4.1.1, the entry for an inbound SA in the SAD MUST be initially populated with the value or values negotiated when the SA was created 🫶 (the paragraph in Section 4.4.1 under "Handling Changes to the SPD while the System is Running" has the guidance on how SPD changes affect extant SAs, so read that too). for a receiver, these values get used to check that the header fields of an inbound packet (after IPsec processing) match the selector values negotiated for the SA. so the SAD basically acts as a cache for checking the selectors of inbound traffic arriving on SAs 🌸 for the receiver, this is part of verifying that a packet arriving on an SA is consistent with the policy for that SA. (see Section 6 for the rules for ICMP messages.) these fields can be specific values, ranges, ANY, or OPAQUE, as described in Section 4.4.1.1, "Selectors".
also, there are a couple of situations where the SAD can have entries for SAs that don't have matching entries in the SPD 🙈 since this document doesn't mandate that the SAD be selectively cleared when the SPD changes, SAD entries can stick around after the SPD entries that created them get changed or deleted. and if a manually keyed SA gets created, there could be an SAD entry for it that doesn't correspond to any SPD entry at all 🦋
Note: The SAD can support multicast SAs, if manually configured. An outbound multicast SA has the same structure as a unicast SA. The source address is that of the sender, and the destination address is the multicast group address. An inbound, multicast SA must be configured with the source addresses of each peer authorized to transmit to the multicast SA in question. The SPI value for a multicast SA is provided by a multicast group controller, not by the receiver, as for a unicast SA. Because an SAD entry may be required to accommodate multiple, individual IP source addresses that were part of an SPD entry (for unicast SAs), the required facility for inbound, multicast SAs is a feature already present in an IPsec implementation. However, because the SPD has no provisions for accommodating multicast entries, this document does not specify an automated way to create an SAD entry for a multicast, inbound SA. Only manually configured SAD entries can be created to accommodate inbound, multicast traffic.
Implementation Guidance: this document doesn't specify how an SPD-S entry refers to its corresponding SAD entry, since that's an implementation-specific detail 🍓 but some implementations (based on experience from RFC 2401) are known to have problems here, and that's the tea ☕. the big issue is that just storing the (remote tunnel header IP address, remote SPI) pair in the SPD cache is NOT enough, because that pair doesn't always uniquely identify a single SAD entry. for instance, two hosts behind the same NAT could pick the same SPI value 😭 it can also happen if a host gets an IP address (e.g., via DHCP) that some other host used before, and the SAs tied to the old host haven't been deleted yet via dead peer detection mechanisms. that can make packets go out over the wrong SA or, if key management guarantees the pair is unique, it can block the creation of otherwise valid SAs 💀 so implementors should link the SPD cache and the SAD in a way that doesn't cause these problems, periodt 💅
4.4.2.1. Data Items in the SAD 🌈
The following data items MUST be in the SAD:
- Security Parameter Index (SPI): a 32-bit value selected by the receiving end of an SA to uniquely identify the SA. in an SAD entry for an outbound SA, the SPI is used to construct the packet's AH or ESP header. in an SAD entry for an inbound SA, the SPI is used to map traffic to the appropriate SA (see the text on unicast/multicast in Section 4.1).
- Sequence Number Counter: a 64-bit counter used to generate the Sequence Number field in AH or ESP headers. 64-bit sequence numbers are the default, but 32-bit sequence numbers are also supported if negotiated 🔥
- Sequence Counter Overflow: a flag that says whether overflow of the sequence number counter should generate an auditable event and prevent transmission of additional packets on the SA, or whether rollover is permitted. the audit log entry for this event SHOULD include the SPI value, current date/time, Local Address, Remote Address, and the selectors from the relevant SAD entry 📝
- Anti-Replay Window: a 64-bit counter and a bit-map (or equivalent) used to determine whether an inbound AH or ESP packet is a replay 🛡️
Note: If anti-replay has been disabled by the receiver for an SA, e.g., in the case of a manually keyed SA, then the Anti-Replay Window is ignored for that SA. 64-bit sequence numbers are the default, but this counter size accommodates 32-bit sequence numbers as well.
- AH Authentication algorithm, key, etc. this is required only if AH is supported 🔐
- ESP Encryption algorithm, key, mode, IV, etc. if a combined mode algorithm is used, these fields will not be applicable 🎀
- ESP integrity algorithm, keys, etc. if the integrity service is not selected, these fields will not be applicable. if a combined mode algorithm is used, these fields will not be applicable either 🦋
- ESP combined mode algorithms, key(s), etc. this data is used when a combined mode (encryption and integrity) algorithm is used with ESP. if a combined mode algorithm is not used, these fields are not applicable 🌸
- Lifetime of this SA: a time interval after which an SA must be replaced with a new SA (and new SPI) or terminated, plus an indication of which of those actions should occur. this can be expressed as a time or a byte count, or as simultaneous use of both, with whichever lifetime expires first taking precedence ⏳ a compliant implementation MUST support both types of lifetimes, and MUST support simultaneous use of both. if time is used, and IKE uses X.509 certificates for SA establishment, the SA lifetime must be constrained by the validity intervals of the certificates, and by the NextIssueDate of the Certificate Revocation Lists (CRLs) used in the IKE exchange for the SA. both the initiator and the responder are responsible for constraining the SA lifetime this way 🫶
Note: how to refresh keys when SAs expire is a local matter. however, one reasonable approach is:
- (a) if a byte count is used, the implementation SHOULD count the number of bytes to which the IPsec cryptographic algorithm is applied. for ESP, this is the encryption algorithm (including Null encryption), and for AH, it's the authentication algorithm. this includes pad bytes, etc. note that implementations MUST be able to handle the counters at the ends of an SA getting out of synch, e.g., because of packet loss or because the implementations at each end of the SA aren't doing things the same way 😅
- (b) there SHOULD be two kinds of lifetime: a soft lifetime that warns the implementation to start an action, like setting up a replacement SA, and a hard lifetime when the current SA ends and is destroyed 🌟
- (c) if the entire packet doesn't get delivered during the SA's lifetime, the packet SHOULD be discarded 🗑️
- IPsec protocol mode: tunnel or transport. indicates which mode of AH or ESP is applied to traffic on this SA 🧚
- Stateful fragment checking flag. indicates whether or not stateful fragment checking applies to this SA 🍓
- Bypass DF bit (T/F): applicable to tunnel mode SAs where both inner and outer headers are IPv4 🌈
- DSCP values: the set of DSCP values allowed for packets carried over this SA. if no values are specified, no DSCP-specific filtering is applied. if one or more values are specified, they're used to select one SA among several that match the traffic selectors for an outbound packet. note that these values are NOT checked against inbound traffic arriving on the SA 💅
- Bypass DSCP (T/F), or map to unprotected DSCP values (array) if needed to restrict bypass of DSCP values: applicable to tunnel mode SAs. this feature maps DSCP values from an inner header to values in an outer header, e.g., to address covert channel signaling concerns 🕵️♀️
- Path MTU: any observed path MTU and aging variables 🌊
- Tunnel header IP source and destination address: both addresses must be either IPv4 or IPv6 addresses. the version implies the type of IP header to be used. only used when the IPsec protocol mode is tunnel 🎀
4.4.2.2. Relationship between SPD, PFP flag, packet, and SAD
okay so this part is where the SPD, the PFP flag, the triggering packet, and the SAD all get in a group chat together 🫶 for each selector, the tables below show how the SPD value, the PFP flag, and the value in the triggering packet turn into the resulting SAD entry 🦋 heads up that the IPsec admin interface can use different syntax to make rules easier to type. like, IKEv2 sends a list of ranges, but it's way less messy for a human to just type one IP address or prefix 💅
Value in
Triggering Resulting SAD
Selector SPD Entry PFP Packet Entry
-------- ---------------- --- ------------ --------------
loc addr list of ranges 0 IP addr "S" list of ranges
ANY 0 IP addr "S" ANY
list of ranges 1 IP addr "S" "S"
ANY 1 IP addr "S" "S"
rem addr list of ranges 0 IP addr "D" list of ranges
ANY 0 IP addr "D" ANY
list of ranges 1 IP addr "D" "D"
ANY 1 IP addr "D" "D"
protocol list of prot's* 0 prot. "P" list of prot's*
ANY** 0 prot. "P" ANY
OPAQUE**** 0 prot. "P" OPAQUE
list of prot's* 0 not avail. discard packet
ANY** 0 not avail. ANY
OPAQUE**** 0 not avail. OPAQUE
list of prot's* 1 prot. "P" "P"
ANY** 1 prot. "P" "P"
OPAQUE**** 1 prot. "P" ***
list of prot's* 1 not avail. discard packet
ANY** 1 not avail. discard packet
OPAQUE**** 1 not avail. ***
if the protocol has two ports, you get selectors for both Local and Remote ports 🌸
Value in
Triggering Resulting SAD
Selector SPD Entry PFP Packet Entry
-------- ---------------- --- ------------ --------------
loc port list of ranges 0 src port "s" list of ranges
ANY 0 src port "s" ANY
OPAQUE 0 src port "s" OPAQUE
list of ranges 0 not avail. discard packet
ANY 0 not avail. ANY
OPAQUE 0 not avail. OPAQUE
list of ranges 1 src port "s" "s"
ANY 1 src port "s" "s"
OPAQUE 1 src port "s" ***
list of ranges 1 not avail. discard packet
ANY 1 not avail. discard packet
OPAQUE 1 not avail. ***
rem port list of ranges 0 dst port "d" list of ranges
ANY 0 dst port "d" ANY
OPAQUE 0 dst port "d" OPAQUE
list of ranges 0 not avail. discard packet
ANY 0 not avail. ANY
OPAQUE 0 not avail. OPAQUE
list of ranges 1 dst port "d" "d"
ANY 1 dst port "d" "d"
OPAQUE 1 dst port "d" ***
list of ranges 1 not avail. discard packet
ANY 1 not avail. discard packet
OPAQUE 1 not avail. ***
if the protocol is mobility header, there's a selector for mh type 💜
Value in
Triggering Resulting SAD
Selector SPD Entry PFP Packet Entry
-------- ---------------- --- ------------ --------------
mh type list of ranges 0 mh type "T" list of ranges
ANY 0 mh type "T" ANY
OPAQUE 0 mh type "T" OPAQUE
list of ranges 0 not avail. discard packet
ANY 0 not avail. ANY
OPAQUE 0 not avail. OPAQUE
list of ranges 1 mh type "T" "T"
ANY 1 mh type "T" "T"
OPAQUE 1 mh type "T" ***
list of ranges 1 not avail. discard packet
ANY 1 not avail. discard packet
OPAQUE 1 not avail. ***
if the protocol is ICMP, you get a 16-bit selector for ICMP type and ICMP code 🎀 the type and code are bound together, so the codes apply to that particular type, no cap. this 16-bit selector can hold a single type with a range of codes, a single type with ANY code, and ANY type with ANY code ✨
Value in
Triggering Resulting SAD
Selector SPD Entry PFP Packet Entry
--------- ---------------- --- ------------ --------------
ICMP type a single type & 0 type "t" & single type &
and code range of codes code "c" range of codes
a single type & 0 type "t" & single type &
ANY code code "c" ANY code
ANY type & ANY 0 type "t" & ANY type &
code code "c" ANY code
OPAQUE 0 type "t" & OPAQUE
code "c"
a single type & 0 not avail. discard packet
range of codes
a single type & 0 not avail. discard packet
ANY code
ANY type & 0 not avail. ANY type &
ANY code ANY code
OPAQUE 0 not avail. OPAQUE
a single type & 1 type "t" & "t" and "c"
range of codes code "c"
a single type & 1 type "t" & "t" and "c"
ANY code code "c"
ANY type & 1 type "t" & "t" and "c"
ANY code code "c"
OPAQUE 1 type "t" & ***
code "c"
a single type & 1 not avail. discard packet
range of codes
a single type & 1 not avail. discard packet
ANY code
ANY type & 1 not avail. discard packet
ANY code
OPAQUE 1 not avail. ***
and if the name selector is used 🌈
Value in
Triggering Resulting SAD
Selector SPD Entry PFP Packet Entry
--------- ---------------- --- ------------ --------------
name list of user or N/A N/A N/A
system names
here's the footnote key for those tables, copied exactly so nothing gets lost 🧚
* "List of protocols" is the information, not the way
that the SPD or SAD or IKEv2 have to represent this
information.
** 0 (zero) is used by IKE to indicate ANY for
protocol.
*** Use of PFP=1 with an OPAQUE value is an error and
SHOULD be prohibited by an IPsec implementation.
**** The protocol field cannot be OPAQUE in IPv4. This
table entry applies only to IPv6.
4.4.3. Peer Authorization Database (PAD)
okay the Peer Authorization Database (PAD) is the bridge between the SPD and a security association management protocol like IKE 🌉 it has a few critical jobs, bestie:
- it identifies the peers or groups of peers that are authorized to communicate with this IPsec entity
- it specifies the protocol and method used to authenticate each peer
- it provides the authentication data for each peer
- it constrains the types and values of IDs that a peer can assert with regard to child SA creation, so that the peer can't assert identities for SPD lookup that it isn't authorized to represent, when child SAs are created 🔒
- peer gateway location info, e.g., IP address(es) or DNS names, MAY be included for peers that are known to be "behind" a security gateway 🏠
the PAD does all of this for an IKE peer whether that peer is the initiator or the responder, no cap 👑
to pull this off, the PAD has an entry for each peer or group of peers the IPsec entity talks to 💖 an entry can name one individual peer (a user, end system, or security gateway) or specify a group of peers using the ID matching rules defined below. the entry specifies the authentication protocol (e.g., IKEv1, IKEv2, KINK) and the method used (e.g., certificates or pre-shared secrets), plus the authentication data (e.g., the pre-shared secret or the trust anchor the peer's certificate gets validated against) ✨ for certificate-based auth, the entry can also include info to help check the peer's revocation status, e.g., a pointer to a CRL repository or the name of an Online Certificate Status Protocol (OCSP) server tied to the peer or to its trust anchor 🦋
each entry also says whether the IKE ID payload gets used as a symbolic name for SPD lookup, or whether the remote IP address from the traffic selector payloads gets used for SPD lookups when child SAs are created 🌸
and last but not least, the PAD information MAY be used to support creating more than one tunnel mode SA at a time between two peers, e.g., two tunnels protecting the same addresses/hosts but with different tunnel endpoints 🍓
4.4.3.1. PAD Entry IDs and Matching Rules ✨
okay so the PAD is an ordered database 📋, and an administrator sets the order (or a user, if it's a single-user end system) 🫶. Usually the same admin handles both the PAD and the SPD, bc the two databases have to stay coordinated 💅. The ordering matters for the exact same reason as the SPD: "star name" entries let overlaps happen in the set of IKE IDs that could match a specific entry 🙈.
There are six ID types for PAD entries, which line up with the symbolic name types and IP addresses used for SPD entries 🎀. The ID of each entry is the index for the PAD, so it's the value you use to pick an entry 🔥. All six types can match IKE ID payload types 💖. The six are:
- DNS name (specific or partial)
- Distinguished Name (complete or sub-tree constrained)
- RFC 822 email address (complete or partially qualified)
- IPv4 address (range)
- IPv6 address (range)
- Key ID (exact match only)
The first three name types can do sub-tree matching as well as exact matches 🌸. A DNS name can be fully qualified so it matches exactly one name, e.g., foo.example.com. Or it can be partial, so it covers a whole group of peers, e.g., .example.com could match any DNS name ending in those two domain name components 🧚.
A Distinguished Name works the same way. You can give a complete DN to match exactly one entry, e.g., CN = Stephen, O = BBN Technologies, SP = MA, C = US. Or you can make an entry cover a sub-tree, e.g., C = US, SP = MA might match all DNs that have those two attributes as the top two Relative Distinguished Names (RDNs) 🦋.
RFC 822 email addresses have the same options 💌. A complete address like foo@example.com matches one entity, but a sub-tree name like @example.com could match all the entities whose names end in those two domain names to the right of the @ 💜.
How an implementation does sub-tree matching for distinguished names, domain names, or RFC 822 e-mail addresses is a local matter 🤷♀️. But at a minimum, sub-tree matching of the sort described above MUST be supported. (Substring matching within a DN, DNS name, or RFC 822 address MAY be supported, but it is not required.)
For IPv4 and IPv6 addresses, the same address range syntax used for SPD entries MUST be supported 🌈. That gives you an individual address (via a trivial range), an address prefix (by picking a range that follows CIDR-style prefixes), or an arbitrary address range ⭐.
The Key ID field is defined as an OCTET string in IKE 🍓. For this name type, only exact-match syntax MUST be supported, since there's no explicit structure for this ID type. Additional matching functions MAY be supported for this ID type 🫶.
4.4.3.2. IKE Peer Authentication Data 🔐
Once an entry is found by searching the PAD in order based on ID field matching, you have to verify the asserted identity, i.e., authenticate the asserted ID 🕵️♀️. For each PAD entry, there's an indication of the authentication type to use. This document requires support for two required authentication data types:
- X.509 certificate
- pre-shared secret
For X.509 certificate authentication, the PAD entry holds a trust anchor 👑. The end entity (EE) certificate for the peer must be verifiable through that trust anchor, either directly or via a certificate path. See RFC 3280 for the definition of a trust anchor 📜. An entry used with certificate-based authentication MAY include extra data to help with certificate revocation status, e.g., a list of appropriate OCSP responders or CRL repositories, plus associated authentication data 🎀. For pre-shared secret authentication, the PAD holds the pre-shared secret that IKE will use 🤫.
This document does not require that the IKE ID a peer asserts be syntactically related to a specific field in the end entity certificate used to authenticate that peer. But it often will make sense to require it, e.g., when one entry represents a set of peers who each might have a distinct SPD entry 😭. So implementations MUST provide a means for an administrator to require a match between an asserted IKE ID and the subject name or subject alt name in a certificate. The former applies to IKE IDs expressed as distinguished names, and the latter fits DNS names, RFC 822 e-mail addresses, and IP addresses 💅. Since KEY ID is meant for identifying a peer authenticated via a pre-shared secret, there's no requirement to match this ID type to a certificate field 🙈.
See IKEv1 [HarCar98] and IKEv2 [Kau05] for the details on how IKE does peer authentication using certificates or pre-shared secrets 📚.
This document does not mandate support for any other authentication methods, although such methods MAY be employed 🦋.
4.4.3.3. Child SA Authorization Data 🧚
Once an IKE peer is authenticated, child SAs may be created ✨. Each PAD entry has data that constrains the set of IDs a peer can assert, for matching against the SPD. Each entry also indicates whether the IKE ID is used as a symbolic name for SPD matching, or whether an IP address asserted in a traffic selector payload is used instead 🎀.
If the entry says the IKE ID is used, then the PAD entry ID field defines the authorized set of IDs 🫶. If the entry says the child SA traffic selectors are used, then an additional data element is required, in the form of IPv4 and/or IPv6 address ranges 🌸. (A peer may be authorized for both address types, so there MUST be provision for both a v4 and a v6 address range 💖.)
4.4.3.4. How the PAD Is Used 🌈
During the initial IKE exchange, the initiator and responder each assert their identity via the IKE ID payload and send an AUTH payload to verify the asserted identity 🪪. One or more CERT payloads may be transmitted to help verify each asserted identity 📨.
When an IKE entity receives an IKE ID payload, it uses the asserted ID to find an entry in the PAD, using the matching rules described above 🔍. The PAD entry specifies the authentication method to use for the identified peer. This makes sure the right method is used for each peer, and that different methods can be used for different peers 💅. The entry also specifies the authentication data used to verify the asserted identity. That data is used together with the specified method to authenticate the peer, before any CHILD SAs are created 🔐.
Child SAs are created based on the exchange of traffic selector payloads, either at the end of the initial IKE exchange or in later CREATE_CHILD_SA exchanges 🦋. The PAD entry for the (now authenticated) IKE peer is used to constrain creation of child SAs. Specifically, the PAD entry specifies how the SPD is searched using a traffic selector proposal from a peer 👑. There are two choices. Either the IKE ID asserted by the peer is used to find an SPD entry via its symbolic name, or the peer IP addresses asserted in traffic selector payloads are used for SPD lookups based on the remote IP address field portion of an SPD entry 🌟. These constraints on creating child SAs are needed to stop an authenticated peer from spoofing IDs that belong to other, legitimate peers 🚫.
Note that because the PAD is checked before searching for an SPD entry, this safeguard protects an initiator against spoofing attacks 🛡️. For example, say IKE A receives an outbound packet destined for IP address X, a host served by a security gateway. RFC 2401 [RFC2401] and this document don't specify how A determines the address of the IKE peer serving X 🤔. However, any peer contacted by A as the presumed representative for X must be registered in the PAD so the IKE exchange can be authenticated. Moreover, when the authenticated peer asserts that it represents X in its traffic selector exchange, the PAD will be consulted to see if that peer is authorized to represent X 🙅♀️. So the PAD provides a binding of address ranges (or name sub-spaces) to peers, to counter attacks like this 💀.
4.5. SA and Key Management 🗝️
All IPsec implementations MUST support both manual and automated SA and cryptographic key management 💖. The IPsec protocols, AH and ESP, are largely independent of the associated SA management techniques, although those techniques do affect some of the security services the protocols offer 🌸. For example, the optional anti-replay service available for AH and ESP requires automated SA management 🔄. Moreover, the granularity of key distribution used with IPsec determines the granularity of authentication provided 🎯. In general, data origin authentication in AH and ESP is limited by how far the secrets used with the integrity algorithm (or with a key management protocol that creates such secrets) are shared among multiple possible sources 🫣.
The following text describes the minimum requirements for both types of SA management 📝.
4.5.1. Manual Techniques 🛠️
The simplest form of management is manual management, where a person manually configures each system with keying material and SA management data relevant to secure communication with other systems 👩💻. Manual techniques are practical in small, static environments, but they do not scale well 😅. For example, a company could create a virtual private network (VPN) using IPsec in security gateways at several sites. If the number of sites is small, and since all the sites come under the purview of a single administrative domain, this might be a feasible context for manual management techniques 🏢. In this case, the security gateway might selectively protect traffic to and from other sites within the organization using a manually configured key, while not protecting traffic for other destinations 🔐. It also might be appropriate when only selected communications need to be secured. A similar argument might apply to using IPsec entirely within an organization for a small number of hosts and/or gateways 💜. Manual management techniques often employ statically configured, symmetric keys, though other options also exist ✨.
4.5.2. Automated SA and Key Management ✨
okay so if IPsec is going to be everywhere 🌍, it needs an Internet-standard, scalable, automated SA management protocol, no cap. That support is required to make the anti-replay features of AH and ESP actually usable, and to let SAs get created on demand, like for user- and session-oriented keying 🔐. (Btw, "rekeying" an SA really means creating a brand-new SA with a new SPI 🤓. That process usually needs an automated SA/key management protocol.)
The default pick for the automated key management protocol is IKEv2 [Kau05] 👑. This doc assumes the key management protocol can do certain things that IKEv1 can't do 🙅. Other automated SA management protocols MAY be employed 🦋.
When you use an automated SA/key management protocol, its output gets used to make multiple keys for one single SA 🔑. That also happens because IKE creates two SAs, and each one gets its own distinct keys. If you're doing both integrity and confidentiality, you need a minimum of four keys, bestie 💜. Some crypto algorithms need multiple keys on their own too, like 3DES 🎀.
The Key Management System might hand over a separate string of bits for each key, or it might give you one big string that all the keys get pulled out of 🧩. If it's one string, you have to be careful that the parts of the system mapping those bits to keys do it the same way at both ends of the SA 👀. So that both IPsec implementations use the same bits for the same keys, no matter which part of the system does the splitting, the encryption keys MUST be taken from the first (left-most, high-order) bits, and the integrity keys MUST be taken from the remaining bits 💅. The number of bits for each key is defined in the relevant cryptographic algorithm specification RFC 📜. If there are multiple encryption keys or multiple integrity keys, the cryptographic algorithm's specification must spell out the order they get selected from that single string of bits 🫶.
4.5.3. Locating a Security Gateway 🗺️
this section is about how a host finds out that relevant security gateways exist, and once it's talked to them, how it knows they're the right ones 🕵️♀️. Where that info gets stored is a local decision, but the Peer Authorization Database (PAD) described in Section 4.4 is the most likely spot 🗂️. (Note: S* means a system running IPsec, like SH1 and SG2 below.)
Picture this: a remote host (SH1) is using the Internet to reach a server or some other machine (H2), and there's a security gateway (SG2), like a firewall, that H1's traffic has to go through 🔥. An example is a mobile host crossing the Internet to reach its home organization's firewall (SG2) 🧳. This raises a few issues:
- How does SH1 know/learn about the existence of the security gateway SG2?
- How does it authenticate SG2, and once it has authenticated SG2, how does it confirm that SG2 has been authorized to represent H2?
- How does SG2 authenticate SH1 and verify that SH1 is authorized to contact H2?
- How does SH1 know/learn about any additional gateways that provide alternate paths to H2?
To deal with all of this, an IPsec-supporting host or security gateway MUST have an administrative interface 🛠️. That interface lets the user or administrator configure the address of one or more security gateways for ranges of destination addresses that need them. It also covers configuring the info for locating and authenticating those gateways, and verifying they're authorized to represent the destination host ✅. (The authorization part is implied in the PAD.) This document doesn't cover how to automate discovery or verification of security gateways 🙈.
4.6. SAs and Multicast 📣
The receiver-orientation of the SA means that, for unicast traffic, the destination system picks the SPI value 🎯. Since the destination picks it, manually configured SAs can't clash with automatically configured ones (like the ones a key management protocol makes), and SAs from multiple sources can't clash with each other either 🙌. Multicast is different, though: a single SA is shared by multiple destination systems 👯. So some system or person has to coordinate across all multicast groups, pick an SPI or SPIs for each group, and then pass that group's IPsec info to every legit member of the group through mechanisms this doc doesn't define 📬.
Multiple senders to a multicast group SHOULD use a single Security Association (and therefore one SPI) for all traffic to that group when a symmetric key encryption or integrity algorithm is in use 🤝. In that case, the receiver only knows the message came from something holding the group's key 🔑. Usually the receiver can't authenticate which system actually sent the multicast traffic 🫣. Specs for other, more general multicast approaches are being handled by the IETF Multicast Security Working Group 🌈.
5. IP Traffic Processing 🚦
Like we said in Section 4.4.1, "The Security Policy Database (SPD)", the SPD (or its associated caches) MUST be consulted while processing all traffic that crosses the IPsec protection boundary, including IPsec management traffic 👀. If there's no policy in the SPD that matches a packet (for inbound or outbound traffic), the packet MUST be discarded 🗑️. To keep things simple and make SA lookups super fast (for SG/BITS/BITW), this doc introduces an SPD cache for all outbound traffic (SPD-O plus SPD-S), and a cache for inbound, non-IPsec-protected traffic (SPD-I) ⚡. (Like we mentioned earlier, the SAD acts as a cache for checking the selectors of inbound IPsec-protected traffic arriving on SAs 📦.) There's basically one cache per SPD 💖. For this spec, each cached entry is assumed to map to exactly one SA. Exceptions show up when you use multiple SAs to carry traffic of different priorities (like with distinct DSCP values) but the same selectors 🎀.
There are also a couple of situations where the SAD can have entries for SAs that don't have matching entries in the SPD 👻. This doc doesn't require the SAD to be selectively cleared when the SPD changes, so SAD entries can stick around after the SPD entries that created them get changed or deleted 🧹. Also, if a manually keyed SA gets created, there could be a SAD entry for it that doesn't match any SPD entry 🤷♀️.
SPD entries can overlap, so you generally can't cache them safely 😬. A simple cache might match an entry that an ordered search of the SPD wouldn't have matched 🙃. But if you decorrelate the SPD entries first, the resulting entries can be cached safely 🧠. Each cached entry says whether matching traffic should be bypassed or discarded, as appropriate ✨. (Note: the original SPD entry might result in multiple SAs, e.g., because of PFP 🧩.) Unless noted otherwise, any mention below of the "SPD", "SPD cache", or "cache" means a decorrelated SPD (SPD-I, SPD-O, SPD-S) or the SPD cache holding entries from that decorrelated SPD 💜.
Note: in a host IPsec implementation based on sockets, the SPD gets consulted whenever a new socket is created, to decide what IPsec processing (if any) applies to traffic flowing on that socket 🧦. That gives you an implicit caching mechanism, so the caching parts of the discussion above can be skipped in those implementations 🦋.
Note: it's assumed you start with a correlated SPD, because that's how users and admins are used to managing this kind of access control list or firewall filter rule 📋. Then the decorrelation algorithm builds a list of cache-able SPD entries from it 🔄. The decorrelation is invisible at the management interface 👻.
For inbound IPsec traffic, the SAD entry selected by the SPI is the cache for the selectors to match against arriving IPsec packets, after AH or ESP processing has been done 🎯.
5.1. Outbound IP Traffic Processing (protected-to-unprotected) ✨
okay so first up is traffic coming in through a protected interface and heading out an unprotected one 🦋 here's the whole flow as a diagram:
Unprotected Interface
^
|
(nested SAs) +----------+
-------------------|Forwarding|<-----+
| +----------+ |
| ^ |
| | BYPASS |
V +-----+ |
+-------+ | SPD | +--------+
...| SPD-I |.................|Cache|.....|PROCESS |...IPsec
| (*) | | (*) |---->|(AH/ESP)| boundary
+-------+ +-----+ +--------+
| +-------+ / ^
| |DISCARD| <--/ |
| +-------+ |
| |
| +-------------+
|---------------->|SPD Selection|
+-------------+
^
| +------+
| -->| ICMP |
| / +------+
|/
|
|
Protected Interface
Figure 2. Processing Model for Outbound Traffic
(*) = The SPD caches are shown here. If there
is a cache miss, then the SPD is checked.
There is no requirement that an
implementation buffer the packet if
there is a cache miss.
so the rules here are that IPsec MUST perform the following steps when it's processing outbound packets, and honestly these steps are the whole vibe 💅
1. when a packet shows up from the subscriber (protected) interface, you invoke the SPD selection function to get the SPD-ID you need to pick the right SPD. (if the implementation only uses one SPD, this step is a no-op, so nothing to stress about 🌸)
2. match the packet headers against the cache for the SPD named by the SPD-ID from step 1. quick note: this cache holds entries from SPD-O and SPD-S ✨
3a. if there's a match, process the packet the way the matching cache entry says, so BYPASS, DISCARD, or PROTECT using AH or ESP. if IPsec processing applies, there's a link from the SPD cache entry to the relevant SAD entry, which tells you the mode, cryptographic algorithms, keys, SPI, PMTU, and so on. IPsec processing works the way we already defined it, for tunnel or transport modes and for AH or ESP, as spelled out in their own RFCs [Ken05b, Ken05a]. also, the SA PMTU value, plus the value of the stateful fragment checking flag (and the DF bit in the IP header of the outbound packet), decides whether the packet can (must) be fragmented before or after IPsec processing, or whether it has to be discarded and an ICMP PMTU message gets sent 🎀
3b. if there's no match in the cache, search the SPD (SPD-S and SPD-O parts) named by SPD-ID. if the SPD entry calls for BYPASS or DISCARD, create one or more new outbound SPD cache entries, and if it's BYPASS, create one or more new inbound SPD cache entries too. (you can end up with more than one cache entry because a decorrelated SPD entry might be linked to other entries that got created as a side effect of the decorrelation process, so it's giving layers 🧚) if the SPD entry calls for PROTECT, which means creating an SA, the key management mechanism (for example IKEv2) gets invoked to create the SA. if SA creation works, a new outbound (SPD-S) cache entry gets made, along with outbound and inbound SAD entries. otherwise the packet is discarded. (a packet that triggers an SPD lookup MAY be discarded by the implementation, or it MAY be processed against the newly created cache entry, if one was created.) also, since SAs come in pairs, an SAD entry for the matching inbound SA gets created too, and it holds the selector values derived from the SPD entry (and from the packet, if any PFP flags were "true") that were used to create the inbound SA, so it can check inbound traffic delivered through that SA 🔥
4. the packet gets passed to the outbound forwarding function (which runs outside the IPsec implementation) so it can pick the interface the packet goes out on. this function may cause the packet to be passed back across the IPsec boundary for more IPsec processing, like for nested SAs. if that happens, there MUST be an entry in the SPD-I database that permits inbound bypassing of the packet, otherwise the packet gets discarded. if it's necessary (like if there's more than one SPD-I), the looped-back traffic MAY be tagged as coming from this internal interface. that lets you use a different SPD-I for "real" external traffic versus looped traffic, if you need that 🫶
Note: With the exception of IPv4 and IPv6 transport mode, an SG, BITS, or BITW implementation MAY fragment packets before applying IPsec. (This applies only to IPv4. For IPv6 packets, only the originator is allowed to fragment them.) The device SHOULD have a configuration setting to disable this. The resulting fragments are evaluated against the SPD in the normal manner. Thus, fragments not containing port numbers (or ICMP message type and code, or Mobility Header type) will only match rules having port (or ICMP message type and code, or MH type) selectors of OPAQUE or ANY. (See Section 7 for more details.)
Wait, the fragmentation part: an SG, BITS, or BITW implementation MAY fragment packets before applying IPsec, and the device SHOULD have a setting to turn that off. fragments without port numbers only match rules with OPAQUE or ANY selectors, so that's a fun little gotcha to remember 💀 (see Section 7 for more details).
Note: With regard to determining and enforcing the PMTU of an SA, the IPsec system MUST follow the steps described in Section 8.2. no skipping that one, bestie 😭
5.1.1. Handling an Outbound Packet That Must Be Discarded
okay so if an IPsec system gets an outbound packet it has to discard, it SHOULD be able to generate and send an ICMP message telling the sender that the packet got tossed 🙈 the type and code depend on why it was discarded, like we spell out below. the reason SHOULD be recorded in the audit log, and that audit log entry SHOULD include the reason, the current date/time, and the selector values from the packet 📝
a. the selectors of the packet matched an SPD entry that requires the packet to be discarded:
IPv4 Type = 3 (destination unreachable) Code = 13
(Communication Administratively Prohibited)
IPv6 Type = 1 (destination unreachable) Code = 1
(Communication with destination administratively
prohibited)
b1. the IPsec system reached the remote peer just fine, but it couldn't negotiate the SA that the matching SPD entry needs. this can happen because, for example, the remote peer is administratively prohibited from talking to the initiator, the initiating peer couldn't authenticate itself to the remote peer, the remote peer couldn't authenticate itself to the initiating peer, or the SPD at the remote peer didn't have a suitable entry 😬
IPv4 Type = 3 (destination unreachable) Code = 13
(Communication Administratively Prohibited)
IPv6 Type = 1 (destination unreachable) Code = 1
(Communication with destination administratively
prohibited)
b2. the IPsec system couldn't set up the SA the matching SPD entry needs, because the IPsec peer on the other end of the exchange couldn't be contacted 📵
IPv4 Type = 3 (destination unreachable) Code = 1 (host
unreachable)
IPv6 Type = 1 (destination unreachable) Code = 3 (address
unreachable)
Heads up, this one is serious 🚨 an attacker behind a security gateway could send packets with a spoofed source address, W.X.Y.Z, to an IPsec entity, which would make it send ICMP messages to W.X.Y.Z. that opens the door to a denial of service (DoS) attack among hosts behind a security gateway. to address this, a security gateway SHOULD include a management control that lets an administrator configure the IPsec implementation to send or not send those ICMP messages in these situations. and if that facility is selected, it should also rate limit how often those ICMP responses go out. the whole point is not letting the bad guys use your ICMP as a weapon 🛡️👑
5.1.2. Header Construction for Tunnel Mode ✨
Okay bestie, this section is all about the inner and outer IP headers, extension headers, and options for AH and ESP tunnels when traffic is going out 🚀. It covers how to build the encapsulating (outer) IP header, what happens to fields in the inner IP header, and what else you need to do for outbound tunnel mode traffic. The whole vibe is modeled after RFC 2003, "IP Encapsulation within IP" [Per96]:
- The outer IP header Source Address and Destination Address are the "endpoints" of the tunnel (the encapsulator and decapsulator) 💖. The inner IP header Source and Destination Addresses are the original sender and recipient of the datagram, from the tunnel's point of view.
(Peep footnote 3 after the table in 5.1.2.1 for the deets on the encapsulating source IP address 👀.)
- The inner IP header doesn't change, except for TTL (or Hop Limit) and the DS/ECN Fields 🎀. Otherwise it stays the same while it travels to the tunnel exit point.
- No changes happen to IP options or extension headers in the inner header while the encapsulated datagram moves through the tunnel 🧚.
Note: IPsec tunnel mode is different from IP-in-IP tunneling (RFC 2003 [Per96]) in a few ways, and honestly these are so iconic 💅:
- IPsec gives a security admin controls to manage covert channels (which usually aren't a concern for tunneling) and to make sure the receiver checks the right parts of the received packet when applying access controls. An IPsec implementation MAY be configurable for how it processes the outer DS field for tunnel mode for transmitted packets. For outbound traffic, one configuration setting for the outer DS field works as described in the following sections on IPv4 and IPv6 header processing for IPsec tunnels. Another setting lets the outer DS field be mapped to a fixed value, which MAY be configured on a per-SA basis. (The value might really be fixed for all traffic outbound from a device, but per-SA granularity allows that too.) This lets a local admin decide whether the covert channel created by copying these bits is worth the benefits of copying 🔥.
- IPsec describes how to handle ECN and DS, and it lets you control how changes in these fields spread between unprotected and protected domains. Generally, propagation from a protected to an unprotected domain is a covert channel, so controls exist to manage its bandwidth. Propagation of ECN values in the other direction is controlled so that only legitimate ECN changes (indicating congestion between the tunnel endpoints) get propagated. By default, DS propagation from an unprotected domain to a protected domain is not permitted. However, if the sender and receiver don't share the same DS code space, and the receiver has no way of learning how to map between the two spaces, then it may be appropriate to deviate from the default. Specifically, an IPsec implementation MAY be configurable in terms of how it processes the outer DS field for tunnel mode for received packets. It may be configured to either discard the outer DS value (the default) OR to overwrite the inner DS field with the outer DS field. If offered, the discard vs. overwrite behavior MAY be configured on a per-SA basis. This config lets a local admin decide whether the vulnerabilities created by copying these bits outweigh the benefits 😭. See [RFC2983] for more on when each of these behaviors may be useful, and also for the possible need for diffserv traffic conditioning before or after IPsec processing (including tunnel decapsulation).
- IPsec allows the IP version of the encapsulating header to be different from the inner header 🦋.
The tables in the following sub-sections show how each header and option field is handled. "Constructed" means the outer field's value is built independently of the inner one 🍓.
5.1.2.1. IPv4: Header Construction for Tunnel Mode
<-- How Outer Hdr Relates to Inner Hdr -->
Outer Hdr at Inner Hdr at
IPv4 Encapsulator Decapsulator
Header fields: -------------------- ------------
version 4 (1) no change
header length constructed no change
DS Field copied from inner hdr (5) no change
ECN Field copied from inner hdr constructed (6)
total length constructed no change
ID constructed no change
flags (DF,MF) constructed, DF (4) no change
fragment offset constructed no change
TTL constructed (2) decrement (2)
protocol AH, ESP no change
checksum constructed constructed (2)(6)
src address constructed (3) no change
dest address constructed (3) no change
Options never copied no change
Notes:
(1) The IP version in the encapsulating header can be different from the value in the inner header 🌸.
(2) The encapsulator decrements the TTL in the inner header before forwarding, and the decapsulator does the same if it forwards the packet. (The IPv4 checksum changes when the TTL changes.) Note: Decrementing the TTL is a normal part of forwarding a packet. So a packet that starts on the same node as the encapsulator doesn't get its TTL decremented, since that node is originating the packet rather than forwarding it. This applies to BITS and native IPsec implementations in hosts and routers. The IPsec processing model also includes an external forwarding capability, and TTL processing can be used to prevent packets from looping (for example, because of configuration errors) within the context of this processing model 🔄.
(3) The Local and Remote addresses depend on the SA. The SA is used to determine the Remote address, and that in turn determines which Local address (net interface) is used to forward the packet 🗺️.
Note: For multicast traffic, the destination address, or the source and destination addresses, may be required for demuxing. In that case, it's important to keep things consistent over the lifetime of the SA by making sure the source address in the encapsulating tunnel header is the same one that was negotiated during SA establishment 🤝. There's one exception to this general rule: a mobile IPsec implementation will update its source address as it moves 🚗.
(4) Configuration determines whether the DF is copied from the inner header (IPv4 only), cleared, or set 🎛️.
(5) If the packet will immediately enter a domain where the DSCP value in the outer header isn't appropriate, that value MUST be mapped to an appropriate value for that domain [NiBlBaBL98]. See RFC 2475 [BBCDWW98] for further information 📚.
(6) If the ECN field in the inner header is set to ECT(0) or ECT(1) (where ECT is ECN-Capable Transport), and the ECN field in the outer header is set to Congestion Experienced (CE), then set the ECN field in the inner header to CE. Otherwise, make no change to the ECN field in the inner header. (The IPv4 checksum changes when the ECN changes.) ⚡
Note: IPsec doesn't copy the options from the inner header into the outer header, and it doesn't construct options in the outer header either. However, post-IPsec code MAY insert or construct options for the outer header 🌈.
5.1.2.2. IPv6: Header Construction for Tunnel Mode
<-- How Outer Hdr Relates Inner Hdr --->
Outer Hdr at Inner Hdr at
IPv6 Encapsulator Decapsulator
Header fields: -------------------- ------------
version 6 (1) no change
DS Field copied from inner hdr (5) no change (9)
ECN Field copied from inner hdr constructed (6)
flow label copied or configured (8) no change
payload length constructed no change
next header AH,ESP,routing hdr no change
hop limit constructed (2) decrement (2)
src address constructed (3) no change
dest address constructed (3) no change
Extension headers never copied (7) no change
Notes:
(1) - (6) See Section 5.1.2.1 💫.
(7) IPsec doesn't copy extension headers from the inner packet into outer headers, and it doesn't construct extension headers in the outer header either. However, post-IPsec code MAY insert or construct extension headers for the outer header 🧩.
(8) See [RaCoCaDe04]. Copying is acceptable only for end systems, not SGs. If an SG copied flow labels from the inner header to the outer header, collisions might result 🙈.
(9) An implementation MAY choose to provide a facility to pass the DS value from the outer header to the inner header, on a per-SA basis, for received tunnel mode packets. The reason for this feature is to accommodate situations where the DS code space at the receiver is different from the sender's and the receiver has no way of knowing how to translate from the sender's space. Copying this value from the outer header to the inner header is risky, though, because it lets an attacker modify the outer DSCP value in a way that may adversely affect other traffic at the receiver 🚨. That's why the default behavior for IPsec implementations is NOT to permit such copying 🛡️.
5.2. Processing Inbound IP Traffic (unprotected-to-protected) ✨
okay so inbound is lowkey a different vibe from outbound 💅 because we use the SPIs to match IPsec-protected packets up to their SAs 🦋. The inbound SPD cache (SPD-I) only gets used for bypassed or discarded traffic 🎀. If a packet that arrives on the unprotected interface looks like an IPsec fragment, it gets reassembled before any IPsec processing happens 🧩. For any SPD cache, the idea is that a packet which doesn't match an entry gets referred to the matching SPD, periodt. Every SPD SHOULD have a nominal, final entry that catches anything unmatched and discards it 🙈. That way, non-IPsec traffic that shows up and misses every SPD-I entry gets tossed, no cap 💀.
Unprotected Interface
|
V
+-----+ IPsec protected
------------------->|Demux|-------------------+
| +-----+ |
| | |
| Not IPsec | |
| | |
| V |
| +-------+ +---------+ |
| |DISCARD|<---|SPD-I (*)| |
| +-------+ +---------+ |
| | |
| |-----+ |
| | | |
| | V |
| | +------+ |
| | | ICMP | |
| | +------+ |
| | V
+---------+ | +-----------+
...|SPD-O (*)|............|...................|PROCESS(**)|...IPsec
+---------+ | | (AH/ESP) | Boundary
^ | +-----------+
| | +---+ |
| BYPASS | +-->|IKE| |
| | | +---+ |
| V | V
| +----------+ +---------+ +----+
|--------<------|Forwarding|<---------|SAD Check|-->|ICMP|
nested SAs +----------+ | (***) | +----+
| +---------+
V
Protected Interface
Figure 3. Processing Model for Inbound Traffic
(*) = The caches are shown here. If there is
a cache miss, then the SPD is checked.
There is no requirement that an
implementation buffer the packet if
there is a cache miss.
(**) = This processing includes using the
packet's SPI, etc., to look up the SA
in the SAD, which forms a cache of the
SPD for inbound packets (except for
cases noted in Sections 4.4.2 and 5).
See step 3a below.
(***) = This SAD check refers to step 4 below.
Prior to doing AH or ESP processing, any IP fragments that arrive via the unprotected interface get reassembled (by IP) 🧵. Each inbound IP datagram that IPsec processing will apply to is spotted by the AH or ESP values showing up in the IP Next Protocol field (or AH or ESP as a next layer protocol in the IPv6 context) 👀.
IPsec MUST perform the following steps: 👑
1. When a packet arrives, it may be tagged with the ID of the interface (physical or virtual) it came in on, if needed, so multiple SPDs and their SPD-I caches can be supported 🏷️. (The interface ID gets mapped to a matching SPD-ID.)
2. The packet gets examined and demuxed into one of two categories:
- If the packet appears to be IPsec protected and it is addressed to this device, we try to map it to an active SA via the SAD 🔐. Note that the device may have several IP addresses that can be used in the SAD lookup, e.g., with protocols like SCTP.
- Traffic not addressed to this device, or addressed to this device but not AH or ESP, goes to the SPD-I lookup. (This means IKE traffic MUST have an explicit BYPASS entry in the SPD 🫶.) If multiple SPDs are in use, the tag from step 1 picks which SPD-I (and cache) to search. The SPD-I lookup decides whether the action is DISCARD or BYPASS.
3a. If the packet is addressed to the IPsec device and AH or ESP is the specified protocol, the packet gets looked up in the SAD. For unicast traffic, use only the SPI (or SPI plus protocol). For multicast traffic, use the SPI plus the destination, or the SPI plus destination and source addresses, as specified in Section 4.1. In either case (unicast or multicast), if there is no match, discard the traffic 🗑️. This is an auditable event. The audit log entry for this event SHOULD include the current date/time, SPI, source and destination of the packet, IPsec protocol, and any other selector values of the packet that are available. If the packet is found in the SAD, process it accordingly (see step 4) ✨.
3b. If the packet is not addressed to the device, or it is addressed to this device and is not AH or ESP, look up the packet header in the (appropriate) SPD-I cache. If there's a match and the packet is to be discarded or bypassed, do that 🙌. If there is no cache match, look up the packet in the corresponding SPD-I and create a cache entry as appropriate. (No SAs get created just because a packet that needs IPsec protection showed up; only BYPASS or DISCARD cache entries can be created this way 🚫.) If there is no match, discard the traffic. This is an auditable event. The audit log entry for this event SHOULD include the current date/time, SPI if available, IPsec protocol if available, source and destination of the packet, and any other selector values of the packet that are available 📝.
3c. Processing of ICMP messages is assumed to happen on the unprotected side of the IPsec boundary 🧚. Unprotected ICMP messages get examined, and local policy decides whether to accept or reject them and, if accepted, what action to take as a result. For example, if an ICMP unreachable message is received, the implementation must decide whether to act on it, reject it, or act on it with constraints. (See Section 6.)
4. Apply AH or ESP processing as specified, using the SAD entry selected in step 3a above. Then match the packet against the inbound selectors identified by the SAD entry, to verify that the received packet is appropriate for the SA it came in on 🔍.
5. If an IPsec system receives an inbound packet on an SA and the packet's header fields are not consistent with the selectors for the SA, it MUST discard the packet 🚨. This is an auditable event. The audit log entry for this event SHOULD include the current date/time, SPI, IPsec protocol(s), source and destination of the packet, any other selector values of the packet that are available, and the selector values from the relevant SAD entry. The system SHOULD also be capable of generating and sending an IKE notification of INVALID_SELECTORS to the sender (IPsec peer), indicating that the received packet was discarded because it failed the selector checks 📣.
To minimize the impact of a DoS attack, or a mis-configured peer, the IPsec system SHOULD include a management control 🛡️ that lets an administrator configure the IPsec implementation to send or not send this IKE notification. If this facility is selected, the system should also rate limit the transmission of such notifications. This is the kind of safety net that keeps things from getting spammy 💀.
After traffic is bypassed or processed through IPsec, it gets handed to the inbound forwarding function for disposition 🚀. This function may cause the packet to be sent (outbound) across the IPsec boundary for additional inbound IPsec processing, e.g., to support nested SAs 🪆. If that happens, then just like ALL outbound traffic that is to be bypassed, the packet MUST be matched against an SPD-O entry 🎯. Ultimately, the packet should be forwarded to the destination host or process for disposition 🏁.
6. ICMP Processing 🌸
This section describes IPsec handling of ICMP traffic 🧸. There are two categories of ICMP traffic: error messages (e.g., type = destination unreachable) and non-error messages (e.g., type = echo). This section applies exclusively to error messages 🎯. Disposition of non-error ICMP messages (that are not addressed to the IPsec implementation itself) MUST be explicitly accounted for using SPD entries 📋.
The discussion in this section applies to ICMPv6 as well as to ICMPv4 🦋. Also, a mechanism SHOULD be provided so an administrator can cause ICMP error messages (selected, all, or none) to be logged, which helps with problem diagnosis 🔎.
6.1. Processing ICMP Error Messages Directed to an IPsec Implementation 💜
6.1.1. ICMP Error Messages Received on the Unprotected Side of the Boundary ✨
Okay so, Figure 3 in Section 5.2 shows a separate ICMP processing module on the unprotected side of the IPsec boundary 🛡️. Its job is handling ICMP messages (errors or otherwise) that are addressed to the IPsec device and aren't protected with AH or ESP. Here's the tea: these ICMP messages aren't authenticated, so processing them can lead to denial or degradation of service 💀. So, in general, ignoring them sounds like the move.
BUT. Lowkey, a ton of ICMP messages will come to hosts or security gateways from unauthenticated sources, like routers out on the public Internet 🌐. If you ignore those, service can get worse, for example because PMTU messages and redirection messages don't get processed. So there's a real reason to accept and act on unauthenticated ICMP messages too 🥺.
To cover both sides of this, a compliant IPsec implementation MUST let a local administrator configure it to accept or reject unauthenticated ICMP traffic 🎀. That control MUST work at the granularity of ICMP type and MAY work at the granularity of ICMP type and code 💅. On top of that, an implementation SHOULD include mechanisms and parameters for handling this traffic 🫶. For example, it could let you set a minimum PMTU for traffic (per destination), so an unauthenticated ICMP can't drag the PMTU down to something ridiculously tiny 🙈.
If an ICMP PMTU message gets through the checks above and the system is set up to accept it, there are two possibilities 🦋. If the implementation does fragmentation on the ciphertext side of the boundary, the accepted PMTU info gets passed to the forwarding module (which sits outside the IPsec implementation), and that module uses it to manage outbound packet fragmentation. If the implementation is set up to do plaintext side fragmentation instead, the PMTU info goes to the plaintext side and gets processed as described in Section 8.2 🧚.
6.1.2. ICMP Error Messages Received on the Protected Side of the Boundary 🏰
These ICMP messages aren't authenticated either, BUT they come from sources on the protected side of the IPsec boundary, so they're generally seen as more "trustworthy" than the ones from the unprotected side 🤝. The big worry is that a compromised host or router could send out bogus ICMP error messages that mess up service for other devices "behind" the security gateway, or even lead to confidentiality violations 😱. For example, if a fake ICMP redirect got consumed by a security gateway, it could change the forwarding table on the protected side so traffic goes to some inappropriate destination "behind" the gateway. Yikes, no thank you 🙅♀️. So implementers MUST provide controls that let local administrators constrain how ICMP error messages received on the protected side (and directed to the IPsec implementation) get processed 🔒. These controls are the same type as the ones used on the unprotected side, described above in Section 6.1.1 💜.
6.2. Processing Protected, Transit ICMP Error Messages 🚇
When an ICMP error message gets sent via an SA to a device "behind" an IPsec implementation, both its payload and its header need checking from an access control perspective 👀. If one of these messages gets forwarded to a host behind a security gateway, that host's IP implementation will make decisions based on the payload, meaning the header of the packet that supposedly triggered the error response 🕵️♀️. So an IPsec implementation MUST be configurable to check that this payload header info is consistent with the SA it arrived on. (In other words, the payload header, with source and destination address and port fields reversed, has to match the traffic selectors for the SA ✨.)
Why does this matter? If this check isn't done, anyone who has an active SA with the receiving IPsec system (A) could send an ICMP Destination Unreachable message referring to any host or net that A is currently talking to 😭. That's a super efficient DoS attack against A's other peers, and normal IPsec receiver processing of traffic does NOT protect against it 🚨. However, not every context needs these checks, so it's also necessary to let a local administrator configure an implementation to NOT perform them 🌸.
To support both policies, the following convention is adopted 💅. If an administrator wants ICMP error messages carried by an SA without inspecting the payload, they configure an SPD entry that explicitly allows that traffic. If an administrator wants IPsec to check the payload of ICMP error messages for consistency, they do NOT create any SPD entries that allow carrying such traffic based on the ICMP packet header. This convention motivates the processing description below 🎀.
IPsec senders and receivers MUST support the following processing for ICMP error messages sent and received via SAs 🫶.
If an SA exists that accommodates an outbound ICMP error message, the message gets mapped to that SA, and upon receipt only the IP and ICMP headers are checked, just like any other traffic 💖. If no SA matches the traffic selectors for an ICMP error message, the SPD gets searched to see if such an SA can be created. If it can, the SA gets created and the ICMP error message gets sent over it. On receipt, the usual traffic selector checks happen at the receiver 🔍. This is exactly what would happen for traffic in general, so it's not special processing for ICMP error messages at all 🧁.
If no SA exists that would carry the outbound ICMP message, AND no SPD entry would allow carrying this outbound ICMP error message, then an IPsec implementation MUST map the message to the SA that would carry the return traffic for the packet that triggered the ICMP error 🔁. This means the implementation has to detect outbound ICMP error messages that map to no existing SA or SPD entry, and handle them specially when it comes to SA creation and lookup 🧠. The implementation pulls out the header of the triggering packet (from the ICMP message payload), reverses the source and destination IP address fields, extracts the protocol field, and reverses the port fields (if accessible) 🪞. It then uses that info to find an appropriate, active outbound SA and sends the error message over it. If no such SA exists, no SA gets created, and this counts as an auditable event 📋.
If an IPsec implementation gets an inbound ICMP error message on an SA, and the IP and ICMP headers of the message don't match the traffic selectors for that SA, the receiver MUST process the message in a special way 🚨. Specifically, the receiver must pull out the header of the triggering packet from the ICMP payload and reverse fields as described above, to figure out whether the packet is consistent with the selectors for the SA the ICMP error arrived on 🕵️. If the packet fails this check, the IPsec implementation MUST NOT forwarded the ICMP message to the destination. This is an auditable event 🙅♀️📋.
7. Handling Fragments (on the protected side of the IPsec boundary) 🧩
Okay, so earlier sections of this doc covered mechanisms for (a) fragmenting an outbound packet after IPsec processing and reassembling it at the receiver before IPsec processing, and (b) handling inbound fragments from the unprotected side of the IPsec boundary 📦. This section is about how an implementation should handle outbound plaintext fragments on the protected side of the boundary 💜. (See Appendix D, "Fragment Handling Rationale", if you want the why 🧠.) Specifically, it covers:
- mapping an outbound non-initial fragment to the right SA (or finding the right SPD entry)
- verifying that a received non-initial fragment is authorized for the SA it arrived on
- mapping outbound and inbound non-initial fragments to the right SPD-O/SPD-I entry or the relevant cache entry, for BYPASS/DISCARD traffic
Note: In Section 4.1, transport mode SAs were defined to NOT carry fragments (IPv4 or IPv6) 🚫. Also, Section 4.4.1 defined two special selector values, ANY and OPAQUE, and ANY includes OPAQUE 🌈. The term "non-trivial" means the selector has a value other than OPAQUE or ANY ✨.
Note: "non-initial fragment" refers to a fragment that doesn't contain all the selector values that might be needed for access control 🙈. As Section 4.4.1 points out, depending on the Next Layer Protocol, the ICMP message type/code or Mobility Header type (in addition to Ports) could be missing from non-initial fragments. Also, for IPv6, even the first fragment might NOT contain the Next Layer Protocol or Ports (or ICMP message type/code, or Mobility Header type), depending on how many and what kind of extension headers are present 😵💫. If a non-initial fragment has the Port (or ICMP type and code, or Mobility Header type) but not the Next Layer Protocol, then unless there's an SPD entry for the relevant Local/Remote addresses with ANY for Next Layer Protocol and Port (or ICMP type and code, or Mobility Header type), the fragment wouldn't have all the selector info needed for access control 🚧.
To deal with all this, three approaches have been defined 🎀:
- Tunnel mode SAs that carry initial and non-initial fragments (See Section 7.1.)
- Separate tunnel mode SAs for non-initial fragments (See Section 7.2.)
- Stateful fragment checking (See Section 7.3.)
7.1. Tunnel Mode SAs that Carry Initial and Non-Initial Fragments 🎁
All implementations MUST support tunnel mode SAs that are configured to pass traffic without regard to port field (or ICMP type/code or Mobility Header type) values 💖. If the SA will carry traffic for specified protocols, the selector set for the SA MUST specify the port fields (or ICMP type/code or Mobility Header type) as ANY 🌟. An SA defined this way will carry all traffic, including initial and non-initial fragments, for the indicated Local/Remote addresses and specified Next Layer protocol(s) 🦋. If the SA will carry traffic without regard to a specific protocol value (meaning ANY is specified as the (Next Layer) protocol selector value), then the port field values are undefined and MUST be set to ANY as well 🫶. (As noted in 4.4.1, ANY includes OPAQUE as well as all specific values 💅.)
7.2. Separate Tunnel Mode SAs for Non-Initial Fragments ✨
okay so an implementation MAY support tunnel mode SAs that only carry non-initial fragments 🧚 Those are kept apart from non-fragmented packets and initial fragments. The OPAQUE value is what you use to set the port (or ICMP type/code or Mobility Header type) field selectors for an SA that carries these fragments 🦋 Receivers MUST do a minimum offset check on IPv4 (non-initial) fragments, which protects against overlapping fragment attacks whenever SAs of this type are in use 🛡️
BUT, and this is a big one 😭, those checks can't be done on IPv6 non-initial fragments. So users and admins are told that carrying these fragments may be dangerous 💀 Implementers may choose to NOT support such SAs for IPv6 traffic, and that's a totally valid vibe 💅
Also, an SA like this carries ALL the non-initial fragments that match one Local/Remote address pair and one protocol value. In other words, the fragments on this SA belong to packets that, if they weren't fragmented, might have gone on separate SAs with different security levels 👀 That's giving chaos energy. So users and administrators are advised to protect this traffic with ESP (with integrity) and the "strongest" integrity and encryption algorithms in use between both peers 🔐 (Figuring out which algorithm is "strongest" means putting the available algorithms in an order, and that's a local call made at the discretion of the initiator of the SA.)
Specific port (or ICMP type/code or Mobility Header type) selector values are used to define SAs that carry initial fragments and non-fragmented packets 🎀 This approach works if a user or admin wants to set up one or more tunnel mode SAs between the same Local/Remote addresses that tell traffic apart by port (or ICMP type/code or Mobility Header type) fields. These SAs MUST have non-trivial protocol selector values. Otherwise, approach #1 above MUST be used 🙅♀️
Note: In general, with the approach in this section, you only need ONE SA between two implementations to carry all the non-initial fragments 🌸 But if you want multiple SAs between the two implementations for QoS differentiation, you might also want multiple SAs to carry fragments-without-ports, one for each supported QoS class. Since QoS via distinct SAs is a local matter and this document doesn't mandate it, choosing multiple SAs for non-initial fragments should also be a local decision 🫶
7.3. Stateful Fragment Checking 🔍
An implementation MAY support some form of stateful fragment checking for a tunnel mode SA with non-trivial port (or ICMP type/code or MH type) field values (not ANY or OPAQUE) 🌈 Implementations that will transmit non-initial fragments on a tunnel mode SA using non-trivial port (or ICMP type/code or MH type) selectors MUST notify a peer with the IKE NOTIFY NON_FIRST_FRAGMENTS_ALSO payload ✨
The peer MUST reject this proposal if it won't accept non-initial fragments in this context 🙅♀️ If an implementation doesn't successfully negotiate sending non-initial fragments for such an SA, it MUST NOT send those fragments over the SA. This standard doesn't say how peers handle such fragments, like through reassembly or other means, at either the sender or the receiver 🤷♀️ However, a receiver MUST discard non-initial fragments that arrive on an SA with non-trivial port (or ICMP type/code or MH type) selector values unless this feature has been negotiated. Also, the receiver MUST discard non-initial fragments that don't comply with the security policy applied to the overall packet. Discarding these packets is an auditable event 📝
Also, if fragments of a packet might be sent or received through different security gateways or BITW implementations, stateful strategies for tracking fragments may fail 😬
7.4. BYPASS/DISCARD Traffic 🚫
All implementations MUST support DISCARDing of fragments using the normal SPD packet classification mechanisms 💖 All implementations MUST also support stateful fragment checking to accommodate BYPASS traffic for which a non-trivial port range is specified. The worry is that BYPASSing a cleartext, non-initial fragment that arrives at an IPsec implementation could undermine the security IPsec gives to protected traffic headed to the same destination 😱
Here's an example. Say an IPsec implementation has an SPD entry that calls for IPsec protection of traffic between a specific source/destination address pair, for a specific protocol and destination port, like TCP traffic on port 23 (Telnet). Now assume the implementation also allows BYPASS of traffic from that same source/destination address pair and protocol, but for a different destination port, like port 119 (NNTP). An attacker could send a non-initial fragment (with a forged source address) that, if bypassed, could overlap with the IPsec-protected traffic from the same source and break its integrity 🕵️♀️ Requiring stateful fragment checking for BYPASS entries with non-trivial port ranges stops attacks like this 🛑 As noted above, in network configurations where fragments of a packet might be sent or received through different security gateways or BITW implementations, stateful strategies for tracking fragments may fail.
8. Path MTU/DF Processing 📏
Applying AH or ESP to an outbound packet makes the packet bigger, so it might go over the PMTU for the SA it's traveling through 🥲 An IPsec implementation may also receive an unprotected ICMP PMTU message and, if it decides to act on that message, the result affects outbound traffic processing. This section explains the processing an IPsec implementation needs to handle these two PMTU issues 💜
8.1. DF Bit 🎀
All IPsec implementations MUST support the option of copying the DF bit from an outbound packet to the tunnel mode header it emits, when traffic goes through a tunnel mode SA. That means it MUST be possible to configure how the implementation treats the DF bit (set, clear, or copy from the inner header) for each SA. This applies to SAs where both the inner and outer headers are IPv4 🍓
8.2. Path MTU (PMTU) Discovery 🛤️
This section covers IPsec handling for unprotected Path MTU Discovery messages. ICMP PMTU refers to an ICMP message for:
IPv4 (RFC 792 [Pos81b]):
- Type = 3 (Destination Unreachable)
- Code = 4 (Fragmentation needed and DF set)
- Next-Hop MTU in the low-order 16 bits of the
second word of the ICMP header (labeled "unused"
in RFC 792), with high-order 16 bits set to zero)
IPv6 (RFC 2463 [CD98]):
- Type = 2 (Packet Too Big)
- Code = 0 (Fragmentation needed)
- Next-Hop MTU in the 32-bit MTU field of the ICMP6
message
8.2.1. Propagation of PMTU 📣
When an IPsec implementation receives an unauthenticated PMTU message, and it's set up to process (vs. ignore) those messages, it maps the message to the SA it belongs to 🗺️ This mapping happens by pulling the header information out of the payload of the PMTU message and applying the procedure described in Section 5.2. The PMTU that this message gives you is used to update the SAD PMTU field. That takes into account the size of the AH or ESP header that will be applied, any crypto synchronization data, and the overhead of an extra IP header if it's a tunnel mode SA ✨
In a native host implementation, you can keep PMTU data at the same granularity as unprotected communication, so there's no loss of functionality 💅 Signaling the PMTU info stays internal to the host. For all other IPsec implementation options, the PMTU data must be propagated via a synthesized ICMP PMTU. In these cases, the IPsec implementation SHOULD wait for outbound traffic to be mapped to the SAD entry. When that traffic arrives, if it would exceed the updated PMTU value, the traffic MUST be handled like this:
- Case 1: The original (cleartext) packet is IPv4 and has the DF bit set. The implementation SHOULD discard the packet and send a PMTU ICMP message 🙅♀️
- Case 2: The original (cleartext) packet is IPv4 and has the DF bit clear. The implementation SHOULD fragment it (before or after encryption, depending on its configuration) and then forward the fragments. It SHOULD NOT send a PMTU ICMP message 🧩
- Case 3: The original (cleartext) packet is IPv6. The implementation SHOULD discard the packet and send a PMTU ICMP message 💀
8.2.2. PMTU Aging ⏳
In all IPsec implementations, the PMTU associated with an SA MUST be "aged", and some mechanism is needed to update the PMTU in a timely way, especially to figure out if the PMTU is smaller than current network conditions require 👀 A given PMTU has to stick around long enough for a packet to get from the source of the SA to the peer, and to send back an ICMP error message if the current PMTU is too big 🫠
Implementations SHOULD use the approach from the Path MTU Discovery document (RFC 1191 [MD90], Section 6.3), which suggests periodically resetting the PMTU to the first-hop data-link MTU and then letting the normal PMTU Discovery processes update the PMTU as needed 🔄 The period SHOULD be configurable ⏰
9. Auditing 📝
IPsec implementations don't have to support auditing 🤷♀️ For the most part, how granular auditing is is a local matter. But several auditable events are identified in this document, and for each of them, a minimum set of information that SHOULD be included in an audit log is defined. Extra information MAY also be included in the audit log for each of these events, and additional events not explicitly called out in this spec also MAY result in audit log entries 🌷 There's no requirement for the receiver to send any message back to the purported transmitter when it detects an auditable event, because doing that could invite denial of service 🛡️
10. Conformance Requirements ✅
All IPv4 IPsec implementations MUST comply with all requirements of this document. All IPv6 implementations MUST comply with all requirements of this document 👑
11. Security Considerations 🔒✨
okay bestie, this whole doc is literally about security, so security considerations are everywhere in here 🫶 no cap
IPsec is super strict about what happens to IP header data crossing the IPsec barrier in both directions, especially when tunnel mode SAs are in play 💅 Some of these rules are absolute, and others are up to local admins, often per SA 🌸 For outbound traffic, the rules are there to limit covert channel bandwidth 👀 For inbound traffic, the goal is to stop an attacker who can mess with one data stream on the unprotected side of the IPsec barrier from breaking other data streams on the protected side 🛡️ Section 5 talks about DSCP handling for tunnel mode SAs, and it's a perfect example of this concern 💜
Now the scary part 😭 If an IPsec implementation passes ICMP error messages over SAs based on the ICMP header values and skips checking the header info inside the ICMP message payload, things can get seriously vulnerable 💀 Picture this: several sites (A, B, and C) are linked up by ESP-protected tunnels, A-B, A-C, and B-C 🌈 Each tunnel's traffic selectors say ANY for protocol and port, and the IP source/destination ranges cover the address space behind each site's security gateway 🍓 That means a host at site B could send an ICMP Destination Unreachable message to any host at site A, declaring that every host on site C's network is unreachable 😱 It's a super efficient DoS attack, and it could've been stopped if the ICMP error messages got the same IPsec checks, as long as the SPD is configured properly, like Section 6.2 describes ✨ Treat this one with respect, it's not a drill 🙈
12. IANA Considerations 🧚
IANA assigned the value (3) in the asn1-modules registry 🎀 It also assigned the object identifier 1.3.6.1.5.8.3.1 to the SPD module 💖 Check out Appendix C, "ASN.1 for an SPD Entry" for the details 🌸
13. Differences from RFC 2401 🦋
Okay so this doc is pretty different from RFC 2401 [RFC2401] in its details and how it's organized 💅 But the core ideas? Still the same, bestie 💖
- The processing model got a glow-up to handle new IPsec scenarios, run faster, and be easier to implement ⚡ It now separates forwarding (routing) from SPD selection, has several SPD changes, and adds an outbound SPD cache and an inbound SPD cache for bypassed or discarded traffic 🔥 There's also a brand new database, the Peer Authorization Database (PAD) 🫶 It links an SA management protocol (like IKE) to the SPD, so they actually talk to each other 💜
- There's no longer a requirement to support nested SAs or "SA bundles" 🙈 You can get the same functionality through SPD and forwarding table config instead 🧚 There's a config example in Appendix E 💅
- SPD entries are way more flexible now ✨ Each entry has 1 to N selector sets, and each set holds one protocol 💖 A "list of ranges" can now be used for the Local IP address, Remote IP address, and whatever fields go with the Next Layer Protocol (Local Port, Remote Port, ICMP message type and code, and Mobility Header type) 🌈 A single value is written as a trivial range, and ANY is a range that covers every value for that selector 🍓 There's an ASN.1 example in Appendix C 🎀
- TOS (IPv4) and Traffic Class (IPv6) got replaced by DSCP and ECN 🦋 The tunnel section now explains how to handle the DSCP and ECN bits 💅
- For tunnel mode SAs, an SG, BITS, or BITW implementation is now allowed to fragment packets before applying IPsec 🌸 This only applies to IPv4 😤 For IPv6 packets, only the originator is allowed to fragment them 💜
- When you want security between two intermediate systems along a path, or between an intermediate system and an end system, transport mode can now be used between security gateways and between a security gateway and a host 🔥
- This doc makes it clear that for all traffic crossing the IPsec boundary, including IPsec management traffic, the SPD or associated caches must be consulted 👀
- This doc defines how to handle a security gateway with multiple subscribers who each need their own separate IPsec contexts 🫶
- Reserved SPIs now have a definition ✨
- There's new text explaining why ALL IP packets must be checked, since IPsec includes minimal firewall functionality for access control at the IP layer 🛡️
- The tunnel section now clarifies how to handle the IP options field and IPv6 extension headers when building the outer header 🎀
- SA mapping for inbound traffic was updated to match the AH and ESP changes that support unicast and multicast SAs 🌈
- There's guidance on the covert channel created in tunnel mode by copying the DSCP value to the outer header 👀
- Support for AH in both IPv4 and IPv6 is no longer required 🙈
- PMTU handling got updated, and the appendix on PMTU/DF/Fragmentation was deleted 🍓
- Three approaches were added for handling plaintext fragments on the protected side of the IPsec boundary 🧚 Appendix D explains the reasoning behind them 💖
- There's revised text on deriving selector values for SAs, whether from the SPD entry, from the packet, and so on 💅
- A new table shows how selector values in an SPD entry, the PFP flag, and the resulting selector values in the matching SAD entry relate to each other 🌸
- Appendix B was added to cover decorrelation ✨
- There's new text on handling an outbound packet that must be discarded 😤
- There's new text on handling a DISCARDED inbound packet, meaning one that doesn't match the SA it arrived on 💜
- The IPv6 Mobility Header was added as a possible Next Layer Protocol, and its message type was added as a selector 🦋
- ICMP message type and code were added as selectors 🔥
- The selector "data sensitivity level" was removed to keep things simple 🙈
- The text on handling ICMP error messages got updated, and the appendix on "Categorization of ICMP Messages" was deleted 🫶
- The text for the selector name was updated and clarified 🌈
- The "Next Layer Protocol" got more explanation, plus a default list of protocols to skip when looking for it 🧚
- The doc now says it assumes use of IKEv2 or an SA management protocol with comparable features 💖
- There's new text clarifying the algorithm for mapping inbound IPsec datagrams to SAs when multicast SAs are involved 🎀
- The appendix "Sequence Space Window Code Example" was removed 💅
- For IP addresses and ports, the policy rules now use "Local" and "Remote" instead of source and destination 🌸 "Local" is the entity protected by the IPsec implementation, so it's the "source" address/port on outbound packets or the "destination" address/port on inbound packets 💜 "Remote" refers to a peer entity or peer entities 🦋 The terms "source" and "destination" still get used for packet header fields 🔥
14. Acknowledgements 🫶
The authors want to give a huge shoutout to Ran Atkinson 👑 He played a critical role in early IPsec work and wrote the first series of IPsec standards, RFCs 1825-1827 💖 They also thank Charlie Lynn 🌈 He made big contributions to the second series of IPsec standards (RFCs 2401, 2402, and 2406) and to the current versions, especially on IPv6 issues 🧚 Last but not least, the authors thank the members of the IPsec and MSEC working groups who helped develop this protocol spec 💜✨
Appendix A: Glossary 📖✨
Okay bestie, this is the glossary, aka the "wait, what does that word actually mean" section 🤓 Other docs have more background, like [Shi00], [VK83], and [HA94]. This one covers generic security service and mechanism terms, plus the IPsec-specific stuff 💜
Access Control 🔐
A security service that prevents unauthorized use of a resource, including the prevention of use of a resource in an unauthorized manner. In the IPsec context, the resource being controlled is often:
- for a host, computing cycles or data
- for a security gateway, a network behind the gateway or bandwidth on that network
Anti-replay 🔁
See "Integrity" below.
Authentication 🪪
Used casually to mean two services that are technically separate, data origin authentication and connectionless integrity, glued together. Check the definitions below for each one 💅
Availability 🌤️
When you look at it as a security service, it's about the security worries that come from attacks which deny or degrade service. In the IPsec context, anti-replay mechanisms in AH and ESP are what keep availability up ✨
Confidentiality 🤫
The security service that keeps data from being disclosed to people who aren't supposed to see it. The big worry is usually application-level data getting exposed, but sometimes the external characteristics of a conversation matter too 👀 Traffic flow confidentiality is the service that handles that second worry, by hiding source and destination addresses, message length, or how often you're talking. In the IPsec context, using ESP in tunnel mode, especially at a security gateway, can give you some level of traffic flow confidentiality. (See also "Traffic Analysis" below.)
Data Origin Authentication 🫡
A security service that checks that the source of the data is who it claims to be. This one usually comes bundled with connectionless integrity service 🎀
Encryption 🗝️
A security mechanism that transforms data from an intelligible form (plaintext) into an unintelligible form (ciphertext) to give you confidentiality. Going the other way is called "decryption". People often just say "encryption" to cover both processes, so don't be confused if they do 🙈
Integrity 🧩
A security service that makes sure changes to data can be detected. Integrity comes in different flavors to match what applications need. IPsec supports two forms: connectionless and a form of partial sequence integrity. Connectionless integrity detects modification of an individual IP datagram, without caring where that datagram sits in a stream of traffic. The partial sequence integrity IPsec offers is called anti-replay integrity, and it detects duplicate IP datagrams arriving (within a constrained window). Compare that with connection-oriented integrity, which is way stricter about sequencing, so it can detect lost or re-ordered messages. Authentication and integrity get cited separately a lot, but in practice they're intimately connected and almost always offered together 💖
Protected vs. Unprotected 🛡️
"Protected" refers to the systems or interfaces inside the IPsec protection boundary, and "unprotected" refers to the ones outside it. IPsec gives you a boundary that traffic passes through, and the barrier is asymmetric, which shows up in the processing model 🌈 Outbound data, if it isn't discarded or bypassed, gets protected by applying AH or ESP and adding the matching headers. Inbound data, if it isn't discarded or bypassed, gets processed by removing the AH or ESP headers. In this document, inbound traffic enters an IPsec implementation from the "unprotected" interface. Outbound traffic enters via the "protected" interface, or is generated internally by the implementation on the "protected" side of the boundary and sent toward the "unprotected" interface. An IPsec implementation can support more than one interface on either or both sides of the boundary. The protected interface can be internal, like in a host implementation of IPsec, or it can link to a socket layer interface the OS presents 🧚
Security Association (SA) 🤝
A simplex (uni-directional) logical connection created for security purposes. All traffic going through an SA gets the same security processing. In IPsec, an SA is an Internet-layer abstraction that's implemented using AH or ESP. The state data for an SA lives in the SA Database (SAD) 📚
Security Gateway 🚪
An intermediate system that acts as the communications interface between two networks. The hosts (and networks) on the external side of the security gateway are called unprotected (they're generally at least less protected than the ones "behind" the SG), while the networks and hosts on the internal side are seen as protected. The internal subnets and hosts a security gateway serves are presumed trusted, because they share a common, local, security administration. In the IPsec context, a security gateway is where AH and/or ESP gets implemented to serve a set of internal hosts, giving those hosts security services when they talk to external hosts that also use IPsec (either directly or through another security gateway) 🏰
Security Parameters Index (SPI) 🔢
An arbitrary 32-bit value that a receiver uses to identify the SA a packet that comes in should be bound to. For a unicast SA, the SPI can be used by itself to specify an SA, or it can be used together with the IPsec protocol type. Multicast SAs are identified using additional IP address information. The SPI is carried in AH and ESP so the receiving system can pick the SA a received packet gets processed under. An SPI only has local significance, as defined by whoever created the SA (usually the receiver of the packet carrying the SPI), so it's generally treated as an opaque bit string. The creator of an SA can still choose to interpret the bits in an SPI to make local processing easier 🫶
Traffic Analysis 🕵️
Analyzing network traffic flow to work out information that's useful to an adversary. Examples include how often things get sent, who the conversing parties are, packet sizes, and flow identifiers [Sch94] 👀
Appendix B: Decorrelation 🧠
This appendix is based on work done for caching policies in the IP Security Policy Working Group by Luis Sanchez, Matt Condell, and John Zao 💜
Two SPD entries are correlated if there's a non-null intersection between the values of corresponding selectors in each entry. Caching correlated SPD entries can lead to incorrect policy enforcement, which is NOT the vibe 😭 The fix that still lets you cache is to remove those ambiguities by decorrelating the entries. That means rewriting the SPD entries so that every pair of entries has at least one selector with a null intersection between the values in both entries. Once the entries are decorrelated, there's no ordering requirement on them anymore, since only one entry will ever match any lookup 🎯 The next section digs into decorrelation in more detail and presents an algorithm you can use to implement it 🔥
B.1. Decorrelation Algorithm ✨
okay so the basic decorrelation algorithm takes each entry in a correlated SPD and splits it into a bunch of smaller entries using a tree structure 🌳 the nodes of the tree are the selectors that might overlap between policies. at each node, the algorithm makes a branch for every value of that selector, plus one extra branch for the complement of the union of all the selector values 💅 then you form policies by walking the tree from the root to each leaf. the leaf policies get compared to the set of already decorrelated policy rules. each one either gets completely overridden by something in that set and is discarded, or it gets decorrelated with everything in the set and is added to it 🫶
Here's the notation we're using:
C A set of ordered, correlated entries (a correlated SPD).
Ci The ith entry in C.
U The set of decorrelated entries being built from C.
Ui The ith entry in U.
Sik The kth selection for policy Ci.
Ai The action for policy Ci.
A policy (SPD entry) P can be written as a sequence of selector values plus an action (BYPASS, DISCARD, or PROTECT):
Ci = Si1 x Si2 x ... x Sik -> Ai
- Put C1 in set U as U1.
For each policy Cj (j > 1) in C:
- If
Cjis decorrelated with every entry in U, add it to U. easy peasy 🎀 - If
Cjis correlated with one or more entries in U, create a tree rooted at the policyCjthat partitionsCjinto a set of decorrelated entries. the algorithm starts with a root node where no selectors have been chosen yet 🧚
A) Choose a selector in Cj, Sjn, that hasn't been chosen yet when you traverse the tree from the root to this node. if there are no selectors left unused, move on to the next unfinished branch until all branches are completed. once the tree is completed, go to step D.
T is the set of entries in U that are correlated with the entry at this node.
The entry at this node is the entry formed by the selector values of each branch between the root and this node. any selector values that aren't represented by branches yet assume the corresponding selector value in Cj, since the values in Cj represent the maximum value for each selector 👑
B) Add a branch to the tree for each value of the selector Sjn that appears in any of the entries in T. (if the value is a superset of the value of Sjn in Cj, use the value in Cj, since that value represents the universal set.) Also add a branch for the complement of the union of all the values of the selector Sjn in T. when taking the complement, remember that the universal set is the value of Sjn in Cj. a branch doesn't need to be created for the null set 🙈
C) Repeat A and B until the tree is completed.
D) The entry at each leaf now represents an entry that is a subset of Cj. the entries at the leaves completely partition Cj in such a way that each entry is either completely overridden by an entry in U, or is decorrelated with the entries in U. add all the decorrelated entries at the leaves of the tree to U 🦋
- Get the next
Cjand go to 2. - When all entries in C have been processed, U will contain a decorrelated version of C ✨
There are a few optimizations you can make to this algorithm. here are some of them 🍓
it's possible to improve the amount of branching by carefully choosing the order of the selectors used for the next branch. for example, if a selector Sjn can be chosen so that all the values for that selector in T are equal to or a superset of the value of Sjn in Cj, then only a single branch needs to be created (since the complement will be null) 💖
branches of the tree don't have to run the entire decorrelation algorithm. for example, if a node represents an entry that is decorrelated with all the entries in U, there's no reason to keep decorrelating that branch. and if a branch is completely overridden by an entry in U, there's no reason to keep decorrelating it either 🌸
another optimization is to check whether a branch is overridden by one of the CORRELATED entries in set C that has already been decorrelated. so if the branch is part of decorrelating Cj, check whether it was overridden by an entry Cm, where m < j. this check is valid because all the entries Cm are already expressed in U 🔥
finally, along with checking whether an entry is already decorrelated in step 2, check whether Cj is overridden by any entry in U. if it is, skip it since it isn't relevant. an entry x is overridden by another entry y if every selector in x is equal to or a subset of the corresponding selector in entry y 💜
Appendix C: ASN.1 for an SPD Entry 🎀
okay bestie, this appendix gives us another way to describe SPD entries, the ones from Section 4.4.1 ✨ It's written in ASN.1 and it actually compiles, which is kind of iconic 💅 But it's just for illustration, so you don't have to use it to be compliant. The SPD description in Section 4.4.1 is the real source of truth, so that's the one that counts 🫶
SPDModule
{iso(1) org (3) dod (6) internet (1) security (5) mechanisms (5)
ipsec (8) asn1-modules (3) spd-module (1) }
DEFINITIONS IMPLICIT TAGS ::=
BEGIN
IMPORTS
RDNSequence FROM PKIX1Explicit88
{ iso(1) identified-organization(3)
dod(6) internet(1) security(5) mechanisms(5) pkix(7)
id-mod(0) id-pkix1-explicit(18) } ;
-- An SPD is a list of policies in decreasing order of preference
SPD ::= SEQUENCE OF SPDEntry
SPDEntry ::= CHOICE {
iPsecEntry IPsecEntry, -- PROTECT traffic
bypassOrDiscard [0] BypassOrDiscardEntry } -- DISCARD/BYPASS
IPsecEntry ::= SEQUENCE { -- Each entry consists of
name NameSets OPTIONAL,
pFPs PacketFlags, -- Populate from packet flags
-- Applies to ALL of the corresponding
-- traffic selectors in the SelectorLists
condition SelectorLists, -- Policy "condition"
processing Processing -- Policy "action"
}
BypassOrDiscardEntry ::= SEQUENCE {
bypass BOOLEAN, -- TRUE BYPASS, FALSE DISCARD
condition InOutBound }
InOutBound ::= CHOICE {
outbound [0] SelectorLists,
inbound [1] SelectorLists,
bothways [2] BothWays }
BothWays ::= SEQUENCE {
inbound SelectorLists,
outbound SelectorLists }
NameSets ::= SEQUENCE {
passed SET OF Names-R, -- Matched to IKE ID by
-- responder
local SET OF Names-I } -- Used internally by IKE
-- initiator
Names-R ::= CHOICE { -- IKEv2 IDs
dName RDNSequence, -- ID_DER_ASN1_DN
fqdn FQDN, -- ID_FQDN
rfc822 [0] RFC822Name, -- ID_RFC822_ADDR
keyID OCTET STRING } -- KEY_ID
Names-I ::= OCTET STRING -- Used internally by IKE
-- initiator
FQDN ::= IA5String
RFC822Name ::= IA5String
PacketFlags ::= BIT STRING {
-- if set, take selector value from packet
-- establishing SA
-- else use value in SPD entry
localAddr (0),
remoteAddr (1),
protocol (2),
localPort (3),
remotePort (4) }
SelectorLists ::= SET OF SelectorList
SelectorList ::= SEQUENCE {
localAddr AddrList,
remoteAddr AddrList,
protocol ProtocolChoice }
Processing ::= SEQUENCE {
extSeqNum BOOLEAN, -- TRUE 64 bit counter, FALSE 32 bit
seqOverflow BOOLEAN, -- TRUE rekey, FALSE terminate & audit
fragCheck BOOLEAN, -- TRUE stateful fragment checking,
-- FALSE no stateful fragment checking
lifetime SALifetime,
spi ManualSPI,
algorithms ProcessingAlgs,
tunnel TunnelOptions OPTIONAL } -- if absent, use
-- transport mode
SALifetime ::= SEQUENCE {
seconds [0] INTEGER OPTIONAL,
bytes [1] INTEGER OPTIONAL }
ManualSPI ::= SEQUENCE {
spi INTEGER,
keys KeyIDs }
KeyIDs ::= SEQUENCE OF OCTET STRING
ProcessingAlgs ::= CHOICE {
ah [0] IntegrityAlgs, -- AH
esp [1] ESPAlgs} -- ESP
ESPAlgs ::= CHOICE {
integrity [0] IntegrityAlgs, -- integrity only
confidentiality [1] ConfidentialityAlgs, -- confidentiality
-- only
both [2] IntegrityConfidentialityAlgs,
combined [3] CombinedModeAlgs }
IntegrityConfidentialityAlgs ::= SEQUENCE {
integrity IntegrityAlgs,
confidentiality ConfidentialityAlgs }
-- Integrity Algorithms, ordered by decreasing preference
IntegrityAlgs ::= SEQUENCE OF IntegrityAlg
-- Confidentiality Algorithms, ordered by decreasing preference
ConfidentialityAlgs ::= SEQUENCE OF ConfidentialityAlg
-- Integrity Algorithms
IntegrityAlg ::= SEQUENCE {
algorithm IntegrityAlgType,
parameters ANY -- DEFINED BY algorithm -- OPTIONAL }
IntegrityAlgType ::= INTEGER {
none (0),
auth-HMAC-MD5-96 (1),
auth-HMAC-SHA1-96 (2),
auth-DES-MAC (3),
auth-KPDK-MD5 (4),
auth-AES-XCBC-96 (5)
-- tbd (6..65535)
}
-- Confidentiality Algorithms
ConfidentialityAlg ::= SEQUENCE {
algorithm ConfidentialityAlgType,
parameters ANY -- DEFINED BY algorithm -- OPTIONAL }
ConfidentialityAlgType ::= INTEGER {
encr-DES-IV64 (1),
encr-DES (2),
encr-3DES (3),
encr-RC5 (4),
encr-IDEA (5),
encr-CAST (6),
encr-BLOWFISH (7),
encr-3IDEA (8),
encr-DES-IV32 (9),
encr-RC4 (10),
encr-NULL (11),
encr-AES-CBC (12),
encr-AES-CTR (13)
-- tbd (14..65535)
}
CombinedModeAlgs ::= SEQUENCE OF CombinedModeAlg
CombinedModeAlg ::= SEQUENCE {
algorithm CombinedModeType,
parameters ANY -- DEFINED BY algorithm} -- defined outside
-- of this document for AES modes.
CombinedModeType ::= INTEGER {
comb-AES-CCM (1),
comb-AES-GCM (2)
-- tbd (3..65535)
}
TunnelOptions ::= SEQUENCE {
dscp DSCP,
ecn BOOLEAN, -- TRUE Copy CE to inner header
df DF,
addresses TunnelAddresses }
TunnelAddresses ::= CHOICE {
ipv4 IPv4Pair,
ipv6 [0] IPv6Pair }
IPv4Pair ::= SEQUENCE {
local OCTET STRING (SIZE(4)),
remote OCTET STRING (SIZE(4)) }
IPv6Pair ::= SEQUENCE {
local OCTET STRING (SIZE(16)),
remote OCTET STRING (SIZE(16)) }
DSCP ::= SEQUENCE {
copy BOOLEAN, -- TRUE copy from inner header
-- FALSE do not copy
mapping OCTET STRING OPTIONAL} -- points to table
-- if no copy
DF ::= INTEGER {
clear (0),
set (1),
copy (2) }
ProtocolChoice::= CHOICE {
anyProt AnyProtocol, -- for ANY protocol
noNext [0] NoNextLayerProtocol, -- has no next layer
-- items
oneNext [1] OneNextLayerProtocol, -- has one next layer
-- item
twoNext [2] TwoNextLayerProtocol, -- has two next layer
-- items
fragment FragmentNoNext } -- has no next layer
-- info
AnyProtocol ::= SEQUENCE {
id INTEGER (0), -- ANY protocol
nextLayer AnyNextLayers }
AnyNextLayers ::= SEQUENCE { -- with either
first AnyNextLayer, -- ANY next layer selector
second AnyNextLayer } -- ANY next layer selector
NoNextLayerProtocol ::= INTEGER (2..254)
FragmentNoNext ::= INTEGER (44) -- Fragment identifier
OneNextLayerProtocol ::= SEQUENCE {
id INTEGER (1..254), -- ICMP, MH, ICMPv6
nextLayer NextLayerChoice } -- ICMP Type*256+Code
-- MH Type*256
TwoNextLayerProtocol ::= SEQUENCE {
id INTEGER (2..254), -- Protocol
local NextLayerChoice, -- Local and
remote NextLayerChoice } -- Remote ports
NextLayerChoice ::= CHOICE {
any AnyNextLayer,
opaque [0] OpaqueNextLayer,
range [1] NextLayerRange }
-- Representation of ANY in next layer field
AnyNextLayer ::= SEQUENCE {
start INTEGER (0),
end INTEGER (65535) }
-- Representation of OPAQUE in next layer field.
-- Matches IKE convention
OpaqueNextLayer ::= SEQUENCE {
start INTEGER (65535),
end INTEGER (0) }
-- Range for a next layer field
NextLayerRange ::= SEQUENCE {
start INTEGER (0..65535),
end INTEGER (0..65535) }
-- List of IP addresses
AddrList ::= SEQUENCE {
v4List IPv4List OPTIONAL,
v6List [0] IPv6List OPTIONAL }
-- IPv4 address representations
IPv4List ::= SEQUENCE OF IPv4Range
IPv4Range ::= SEQUENCE { -- close, but not quite right ...
ipv4Start OCTET STRING (SIZE (4)),
ipv4End OCTET STRING (SIZE (4)) }
-- IPv6 address representations
IPv6List ::= SEQUENCE OF IPv6Range
IPv6Range ::= SEQUENCE { -- close, but not quite right ...
ipv6Start OCTET STRING (SIZE (16)),
ipv6End OCTET STRING (SIZE (16)) }
END
Appendix D: Fragment Handling Rationale 🧚
okay so this one is about fragments, the little pieces of a packet that get chopped up 🍓 There are three issues we need to get sorted when it comes to (plaintext) fragments in IPsec:
- mapping a non-initial, outbound fragment to the right SA (or finding the right SPD entry)
- verifying that a received, non-initial fragment is authorized for the SA via which it is received
- mapping outbound and inbound non-initial fragments to the right SPD/cache entry, for BYPASS/DISCARD traffic
the first and third issues happen because we need a deterministic algorithm for mapping traffic to SAs (and SPD/cache entries) 🔥 and honestly all three matter, because we want to make sure non-initial fragments crossing the IPsec boundary don't end up breaking the access control policies at the receiver (or transmitter) 💀 that would be such a main character moment for the wrong reasons 🙈
D.1. Transport Mode and Fragments ✨
Okay bestie, let's start with the big one 🦋 Transport mode SAs have been defined to not carry fragments. This is a carryover from RFC 2401, where transport mode SAs always terminated at endpoints. It's a fundamental requirement, because in the worst case an IPv4 fragment that IPsec was applied to could then get fragmented (as a ciphertext packet) on its way to the destination. The IP fragment reassembly procedures at the IPsec receiver wouldn't be able to tell pre-IPsec fragments apart from fragments created after IPsec processing. Chaos 💀
For IPv6, only the sender is allowed to fragment a packet. Same as IPv4, an IPsec implementation is allowed to fragment tunnel mode packets after IPsec processing, because it's the sender relative to the (outer) tunnel header. But unlike IPv4, it would be feasible to carry a plaintext fragment on a transport mode SA, because the fragment header in IPv6 appears after the AH or ESP header, so it wouldn't confuse the receiver about reassembly. The receiver wouldn't attempt reassembly for the fragment until after IPsec processing. To keep things simple, this specification prohibits carriage of fragments on transport mode SAs for IPv6 traffic. 🌸
When only end systems used transport mode SAs, the prohibition wasn't a problem, since we assumed the end system could be configured to not offer a fragment to IPsec. For a native host implementation this seems reasonable, and, as someone already noted, RFC 2401 warned that a BITS implementation might have to reassemble fragments before performing an SA lookup. (It would then apply AH or ESP and could re-fragment the packet after IPsec processing.) Because a BITS implementation is assumed to have access to all traffic emanating from its host, even if the host has multiple interfaces, this was deemed a reasonable mandate. 🎀
In this specification, it is acceptable to use transport mode where the IPsec implementation isn't the ultimate destination, e.g., between two SGs. In principle, this creates a new opportunity for outbound, plaintext fragments to get mapped to a transport mode SA for IPsec processing. However, in these new contexts where a transport mode SA is now approved, it seems likely we can keep prohibiting transmission of fragments as seen by IPsec, i.e., packets that have an "outer header" with a non-zero fragment offset field. For example, in an IP overlay network, packets sent over transport mode SAs are IP-in-IP tunneled and so have the necessary inner header to accommodate fragmentation prior to IPsec processing. When carried via a transport mode SA, IPsec wouldn't examine the inner IP header for such traffic, and so wouldn't consider the packet to be a fragment. 🧚
D.2. Tunnel Mode and Fragments 🌈
For tunnel mode SAs, it has always been the case that outbound fragments might arrive for processing at an IPsec implementation. This can be a problem, because a non-initial fragment generally won't contain the port fields associated with a next layer protocol like TCP, UDP, or SCTP. So depending on the SPD configuration for a given IPsec implementation, plaintext fragments might or might not pose a problem. 💜
For example, if the SPD requires that all traffic between two address ranges is offered IPsec protection (no BYPASS or DISCARD SPD entries apply to this address range), then it should be easy to carry non-initial fragments on the SA defined for this address range, since the SPD entry implies an intent to carry ALL traffic between the address ranges. But if multiple SPD entries could match a fragment, and those entries reference different subsets of port fields (vs. ANY), then it is not possible to map an outbound non-initial fragment to the right entry unambiguously. (If we choose to allow carriage of fragments on transport mode SAs for IPv6, the problem arises in that context as well.) 😭
This problem largely, though not exclusively, motivated the definition of OPAQUE as a selector value for port fields in RFC 2401. The other motivation for OPAQUE is the observation that port fields might not be accessible due to the prior application of IPsec. For example, if a host applied IPsec to its traffic and that traffic arrived at an SG, these fields would be encrypted. The algorithm specified for locating the "next layer protocol" described in RFC 2401 also motivated use of OPAQUE to accommodate an encrypted next layer protocol field in such circumstances. Nonetheless, the primary use of the OPAQUE value was to match traffic selector fields in packets that didn't contain port fields (non-initial fragments), or packets in which the port fields were already encrypted (as a result of nested application of IPsec). RFC 2401 was ambiguous in discussing the use of OPAQUE vs. ANY, suggesting in some places that ANY might be an alternative to OPAQUE. 🙈
We gain additional access control capability by defining both ANY and OPAQUE values. OPAQUE can be defined to match only fields that are not accessible. We could define ANY as the complement of OPAQUE, i.e., it would match all values but only for accessible port fields. We have therefore simplified the procedure employed to locate the next layer protocol in this document, so that we treat ESP and AH as next layer protocols. As a result, the notion of an encrypted next layer protocol field has vanished, and there is also no need to worry about encrypted port fields either. And accordingly, OPAQUE will be applicable only to non-initial fragments. Main character energy, honestly. 👑
Since we have adopted the definitions above for ANY and OPAQUE, we need to clarify how these values work when the specified protocol does not have port fields, and when ANY is used for the protocol selector. Accordingly, if a specific protocol value is used as a selector, and if that protocol has no port fields, then the port field selectors are to be ignored and ANY MUST be specified as the value for the port fields. (In this context, ICMP TYPE and CODE values are lumped together as a single port field (for IKEv2 negotiation), as is the IPv6 Mobility Header TYPE value.) If the protocol selector is ANY, then this should be treated as equivalent to specifying a protocol for which no port fields are defined, and thus the port selectors should be ignored, and MUST be set to ANY. Iconic. Periodt. 💅
D.3. The Problem of Non-Initial Fragments ✨
Okay so for an SG implementation, it's obvious that fragments might come in from end systems sitting behind the SG 💅. A BITW implementation can also run into fragments from a host or gateway behind it 🫶. (As noted earlier, native host implementations and BITS implementations probably can avoid the problems described below.) In the worst case, fragments from one packet could land at distinct BITW or SG instantiations 😭, which means reassembly is off the table as a solution. So back in RFC 2401 we made a general requirement that fragments must be accommodated in tunnel mode for all implementations. But RFC 2401 didn't give a perfect solution 💀. Using OPAQUE as a selector value for port fields (a SHOULD in RFC 2401) let an SA carry non-initial fragments 🎀.
Using the features defined in RFC 2401, if you defined an SA between two IPsec (SG or BITW) implementations using the OPAQUE value for both port fields, then all non-initial fragments matching the source/destination (S/D) address and protocol values for the SA would get mapped to that SA 🦋. Initial fragments would NOT map to this SA, if we adopt a strict definition of OPAQUE. RFC 2401 didn't give detailed guidance on this, so it might not have been obvious that using this feature would basically create a "non-initial fragment only" SA 🙈.
While we were talking through the "fragment-only" SA approach, some subtle problems came up that RFC 2401 didn't consider, and they'd have to be avoided 👀. For example, an SA like this must be configured to offer the "highest quality" security services for any traffic between the indicated S/D addresses (for the specified protocol). This is needed so that traffic captured by the fragment-only SA doesn't get degraded security compared to what it would have gotten if the packet weren't fragmented 🔒. The tricky bit is that we may not be able to identify the "highest quality" security services defined for use between two IPsec implementations, since the choice of security protocols, options, and algorithms is a lattice, not a totally ordered set. (We might safely say that BYPASS < AH < ESP w/integrity, but it gets complicated if we have multiple ESP encryption or integrity algorithm options.) So one has to impose a total ordering on these security parameters to make this work, but this can be done locally 🧠.
However, this conservative strategy has a possible performance downside 📉. If most traffic traversing an IPsec implementation for a given S/D address pair (and specified protocol) is bypassed, then a fragment-only SA for that address pair might cause a dramatic increase in the volume of traffic afforded crypto processing. If the crypto implementation cannot support high traffic rates, this could cause problems. (An IPsec implementation that is capable of line rate or near line rate crypto performance would not be adversely affected by this SA configuration approach. Nonetheless, the performance impact is a potential concern, specific to implementation capabilities.)
Another concern is that non-initial fragments sent over a dedicated SA might be used to effect overlapping reassembly attacks, when combined with an apparently acceptable initial fragment 🚨. (This sort of attack assumes creation of bogus fragments and is not a side effect of normal fragmentation.) This concern is easily addressed in IPv4, by checking the fragment offset value to ensure that no non-initial fragments have a small enough offset to overlap port fields that should be contained in the initial fragment. Recall that the IPv4 MTU minimum is 576 bytes, and the max IP header length is 60 bytes, so any ports should be present in the initial fragment. If we require all non-initial fragments to have an offset of, say, 128 or greater, just to be on the safe side, this should prevent successful attacks of this sort 🛡️. If the intent is only to protect against this sort of reassembly attack, this check need be implemented only by a receiver.
IPv6 also has a fragment offset, carried in the fragmentation extension header 🧩. However, IPv6 extension headers are variable in length, and there is no analogous max header length value that we can use to check non-initial fragments and reject ones that might be used for an attack of the sort noted above. A receiver would need to maintain state analogous to reassembly state to provide equivalent protection. So, only for IPv4 is it feasible to impose a fragment offset check that would reject attacks designed to circumvent port field checks by IPsec (or firewalls) when passing non-initial fragments.
Another possible concern is that in some topologies and SPD configurations this approach might result in an access control surprise 😬. The notion is that if we create an SA to carry ALL (non-initial) fragments, then that SA would carry some traffic that might otherwise arrive as plaintext via a separate path, e.g., a path monitored by a proxy firewall. But this concern arises only if the other path allows initial fragments to traverse it without requiring reassembly, presumably a bad idea for a proxy firewall. Nonetheless, this does represent a potential problem in some topologies and under certain assumptions with respect to SPD and (other) firewall rule sets.
Administrators need to be warned of this possibility ⚠️.
A less serious concern is that non-initial fragments sent over a non-initial fragment-only SA might represent a DoS opportunity 🥀, in that they could be sent when no valid, initial fragment will ever arrive. This might be used to attack hosts behind an SG or BITW device. However, the incremental risk posed by this sort of attack, which can be mounted only by hosts behind an SG or BITW device, seems small 🤷♀️.
If we interpret the ANY selector value as encompassing OPAQUE, then a single SA with ANY values for both port fields would be able to accommodate all traffic matching the S/D address and protocol traffic selectors, as an alternative to using the OPAQUE value. But using ANY here precludes multiple, distinct SAs between the same IPsec implementations for the same address pairs and protocol. So it is not an exactly equivalent alternative 🤔.
Fundamentally, fragment handling problems arise only when more than one SA is defined with the same S/D address and protocol selector values, but with different port field selector values 💜.
D.4. BYPASS/DISCARD Traffic 🌸
We also have to address the non-initial fragment processing issue for BYPASS/DISCARD entries, independent of SA processing. This is largely a local matter, for two reasons:
- We have no means for coordinating SPD entries for such traffic between IPsec implementations, since IKE is not invoked.
- Many of these entries refer to traffic that is NOT directed to or received from a location that is using IPsec. So there is no peer IPsec implementation to coordinate with via any means.
However, this document should provide guidance here, consistent with our goal of offering a well-defined, access control function for all traffic, relative to the IPsec boundary ✨. To that end, this document says that implementations MUST support fragment reassembly for BYPASS/DISCARD traffic when port fields are specified. An implementation also MUST permit a user or administrator to accept such traffic or reject such traffic using the SPD conventions described in Section 4.4.1. The concern is that BYPASS of a cleartext, non-initial fragment arriving at an IPsec implementation could undermine the security afforded IPsec-protected traffic directed to the same destination 😱. For example, consider an IPsec implementation configured with an SPD entry that calls for IPsec-protection of traffic between a specific source/destination address pair, and for a specific protocol and destination port, e.g., TCP traffic on port 23 (Telnet). Assume that the implementation also allows BYPASS of traffic from the same source/destination address pair and protocol, but for a different destination port, e.g., port 119 (NNTP). An attacker could send a non-initial fragment (with a forged source address) that, if bypassed, could overlap with IPsec-protected traffic from the same source and thus violate the integrity of the IPsec-protected traffic 🥺. Requiring stateful fragment checking for BYPASS entries with non-trivial port ranges prevents attacks of this sort 🔐.
D.5. Just say no to ports? 🙅♀️
It has been suggested that we could avoid the problems described above by not allowing port field selectors to be used in tunnel mode. But the discussion above shows this to be an unnecessarily stringent approach, i.e., since no problems arise for the native OS and BITS implementations 🙄. Moreover, some WG members have described scenarios where use of tunnel mode SAs with (non-trivial) port field selectors is appropriate. So the challenge is defining a strategy that can deal with this problem in BITW and SG contexts 🧩. Also note that BYPASS/DISCARD entries in the SPD that make use of ports pose the same problems, irrespective of tunnel vs. transport mode notions.
Some folks have suggested that a firewall behind an SG or BITW should be left to enforce port-level access controls and the effects of fragmentation. However, this seems to be an incongruous suggestion, in that elsewhere in IPsec (e.g., in IKE payloads) we are concerned about firewalls that always discard fragments. If many firewalls don't pass fragments in general, why should we expect them to deal with fragments in this case? So this analysis rejects the suggestion of disallowing use of port field selectors with tunnel mode SAs 🚫.
D.6. Other Suggested Solutions 💡
Okay so bestie, people floated a couple of other ideas here 🧩. The first one is to just reassemble the fragments at the sending IPsec implementation, so the problem never happens in the first place. Honestly iconic. A receiver can't even tell it's going on, so it could be adopted as a purely local implementation option 💅.
A more sophisticated version of that idea says to establish and maintain minimal state from each initial fragment encountered, so non-initial fragments can be matched to the right SAs or SPD/cache entries 🦋. That implies an extension to the current processing model (and the old one too, periodt). The IPsec implementation would intercept all fragments, capture Source/Destination IP addresses, protocol, packet ID, and port fields from initial fragments, and then use that data to map non-initial fragments to SAs that require port fields. If you go this route, the receiver needs an equivalent scheme too, because it also has to verify that received fragments are consistent with SA selector values. A non-initial fragment that arrives before its initial fragment could be cached or discarded while it waits for the initial one to show up 🥺.
Now the downside of both approaches: they will not always work 😭. When a BITW device or SG is configured in a topology that might let some fragments for a packet get processed at different SGs or BITW devices, there is no guarantee that all the fragments ever arrive at the same IPsec device. This approach also raises processing problems. If the sender caches non-initial fragments until the corresponding initial fragment arrives, buffering problems might pop up, especially at high speeds. If the non-initial fragments get discarded instead of cached, there's no guarantee traffic will ever pass, e.g., retransmission will result in different packet IDs that can't be matched with prior transmissions 💀. Either way, housekeeping procedures are needed to decide when to delete the fragment state data, which adds some complexity to the system. Nonetheless, this is a viable solution in some topologies, and those are likely to be common topologies 🌸.
The Working Group rejected an earlier version of the convention of creating an SA to carry only non-initial fragments. That was supported implicitly under the RFC 2401 model via OPAQUE port fields, but it was never clearly articulated in RFC 2401 🙃. The rejected text called for each non-initial fragment to be treated as protocol 44 (the IPv6 fragment header protocol ID) by the sender and receiver. This approach has the potential to make IPv4 and IPv6 fragment handling more uniform, but it does not fundamentally change the problem, nor does it address the issue of fragment handling for BYPASS/DISCARD traffic. Given the fragment overlap attack problem that IPv6 poses, it doesn't seem worth the effort to adopt this strategy 🙈.
D.7. Consistency 🎀
Earlier, the WG agreed to allow an IPsec BITS, BITW, or SG to perform fragmentation prior to IPsec processing. If this fragmentation is performed after SA lookup at the sender, there is no "mapping to the right SA" problem. But the receiver still needs to be able to verify that the non-initial fragments are consistent with the SA via which they are received. Since the initial fragment might be lost en route, the receiver runs into all of the potential problems noted above 😵. So if we want to be consistent in our decisions, we need to say how a receiver will deal with the non-initial fragments that arrive ✨.
D.8. Conclusions 👑
There is no simple, uniform way to handle fragments in all contexts 🫠. Different approaches work better in different contexts. So this document offers 3 choices: one MUST and two MAYs. At some point in the future, if the community gains experience with the two MAYs, they may become SHOULDs or MUSTs or other approaches may be proposed 🦋.
Appendix E: Example of Supporting Nested SAs via SPD and Forwarding Table Entries 🧚
This appendix is the example I wish someone had shown me sooner 🥹. It walks through how to configure the SPD and forwarding tables to support a nested pair of SAs, consistent with the new processing model. For simplicity, this example assumes just one SPD-I.
The goal here is to support a transport mode SA from A to C, carried over a tunnel mode SA from A to B. For example, A might be a laptop connected to the public Internet, B might be a firewall that protects a corporate network, and C might be a server on the corporate network that demands end-to-end authentication of A's traffic 💻🔥.
+---+ +---+ +---+
| A |=====| B | | C |
| |------------| |
| |=====| | | |
+---+ +---+ +---+
A's SPD contains entries of the form:
Next Layer
Rule Local Remote Protocol Action
---- ----- ------ ---------- -----------------------
1 C A ESP BYPASS
2 A C ICMP,ESP PROTECT(ESP,tunnel,integr+conf)
3 A C ANY PROTECT(ESP,transport,integr-only)
4 A B ICMP,IKE BYPASS
Wait, I need to keep that exact. Here's the SPD table again, copied character for character:
Next Layer
Rule Local Remote Protocol Action
---- ----- ------ ---------- -----------------------
1 C A ESP BYPASS
2 A C ICMP,ESP PROTECT(ESP,tunnel,integr+conf)
3 A C ANY PROTECT(ESP,transport,integr-only)
4 A B ICMP,IKE BYPASS
A's unprotected-side forwarding table is set so that outbound packets destined for C are looped back to the protected side. A's protected-side forwarding table is set so that inbound ESP packets are looped back to the unprotected side 🔁. A's forwarding tables contain entries of the form:
Unprotected-side forwarding table
Rule Local Remote Protocol Action
---- ----- ------ -------- ---------------------------
1 A C ANY loop back to protected side
2 A B ANY forward to B
Protected-side forwarding table
Rule Local Remote Protocol Action
---- ----- ------ -------- -----------------------------
1 A C ESP loop back to unprotected side
Okay, now the fun part, the packet journey 🦋. An outbound TCP packet from A to C would match SPD rule 3 and have transport mode ESP applied to it. The unprotected-side forwarding table would then loop back the packet. The packet is compared against SPD-I (see Figure 2), matches SPD rule 1, and so it is BYPASSed. The packet is treated as an outbound packet and compared against the SPD for a third time 🌀. This time it matches SPD rule 2, so ESP is applied in tunnel mode. This time the forwarding table doesn't loop back the packet, because the outer destination address is B, so the packet goes out onto the wire 🚀.
Now the inbound direction. An inbound TCP packet from C to A is wrapped in two ESP headers; the outer header (ESP in tunnel mode) shows B as the source, whereas the inner header (ESP transport mode) shows C as the source 🎁. Upon arrival at A, the packet would be mapped to an SA based on the SPI, have the outer header removed, and be decrypted and integrity-checked. Then it would be matched against the SAD selectors for this SA, which would specify C as the source and A as the destination, derived from SPD rule 2. The protected-side forwarding function would then send it back to the unprotected side based on the addresses and the next layer protocol (ESP), which is indicative of nesting 🪞. It is compared against SPD-O (see Figure 3) and found to match SPD rule 1, so it is BYPASSed. The packet is mapped to an SA based on the SPI, integrity-checked, and compared against the SAD selectors derived from SPD rule 3. The forwarding function then passes it up to the next layer, because it isn't an ESP packet 💖.
References ⭐
Normative References
[BBCDWW98] Blake, S., Black, D., Carlson, M., Davies, E., Wang, Z., and W. Weiss, "An Architecture for Differentiated Service", RFC 2475, December 1998.
[Bra97] Bradner, S., "Key words for use in RFCs to Indicate Requirement Level", BCP 14, RFC 2119, March 1997.
[CD98] Conta, A. and S. Deering, "Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) Specification", RFC 2463, December 1998.
[DH98] Deering, S., and R. Hinden, "Internet Protocol, Version 6 (IPv6) Specification", RFC 2460, December 1998.
[Eas05] 3rd Eastlake, D., "Cryptographic Algorithm Implementation Requirements For Encapsulating Security Payload (ESP) and Authentication Header (AH)", RFC 4305, December 2005.
[HarCar98] Harkins, D. and D. Carrel, "The Internet Key Exchange (IKE)", RFC 2409, November 1998.
[Kau05] Kaufman, C., Ed., "The Internet Key Exchange (IKEv2) Protocol", RFC 4306, December 2005.
[Ken05a] Kent, S., "IP Encapsulating Security Payload (ESP)", RFC 4303, December 2005.
[Ken05b] Kent, S., "IP Authentication Header", RFC 4302, December 2005.
[MD90] Mogul, J. and S. Deering, "Path MTU discovery", RFC 1191, November 1990.
[Mobip] Johnson, D., Perkins, C., and J. Arkko, "Mobility Support in IPv6", RFC 3775, June 2004.
[Pos81a] Postel, J., "Internet Protocol", STD 5, RFC 791, September 1981.
[Pos81b] Postel, J., "Internet Control Message Protocol", RFC 792, September 1981.
[Sch05] Schiller, J., "Cryptographic Algorithms for use in the Internet Key Exchange Version 2 (IKEv2)", RFC 4307, December 2005.
[WaKiHo97] Wahl, M., Kille, S., and T. Howes, "Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names", RFC 2253, December 1997.
Informative References 📚✨
okay bestie, these are the extra reads that back up the spec, the ones that aren't strictly required but are super useful for understanding where everything came from 🤓💜
[CoSa04] Condell, M., and L. Sanchez, "On the Deterministic Enforcement of Un-ordered Security Policies", BBN Technical Memo 1346, March 2004.
[FaLiHaMeTr00] Farinacci, D., Li, T., Hanks, S., Meyer, D., and P. Traina, "Generic Routing Encapsulation (GRE)", RFC 2784, March 2000. 🎀
[Gro02] Grossman, D., "New Terminology and Clarifications for Diffserv", RFC 3260, April 2002.
[HC03] Holbrook, H. and B. Cain, "Source Specific Multicast for IP", Work in Progress, November 3, 2002. 🌸
[HA94] Haller, N. and R. Atkinson, "On Internet Authentication", RFC 1704, October 1994.
[NiBlBaBL98] Nichols, K., Blake, S., Baker, F., and D. Black, "Definition of the Differentiated Services Field (DS Field) in the IPv4 and IPv6 Headers", RFC 2474, December 1998. 🦋
[Per96] Perkins, C., "IP Encapsulation within IP", RFC 2003, October 1996.
[RaFlBl01] Ramakrishnan, K., Floyd, S., and D. Black, "The Addition of Explicit Congestion Notification (ECN) to IP", RFC 3168, September 2001. ✨
[RFC2401] Kent, S. and R. Atkinson, "Security Architecture for the Internet Protocol", RFC 2401, November 1998. 🔐 this one's the ancestor of the document we've been reading, so it's a big deal
[RFC2983] Black, D., "Differentiated Services and Tunnels", RFC 2983, October 2000.
[RFC3547] Baugher, M., Weis, B., Hardjono, T., and H. Harney, "The Group Domain of Interpretation", RFC 3547, July 2003. 💅
[RFC3740] Hardjono, T. and B. Weis, "The Multicast Group Security Architecture", RFC 3740, March 2004.
[RaCoCaDe04] Rajahalme, J., Conta, A., Carpenter, B., and S. Deering, "IPv6 Flow Label Specification", RFC 3697, March 2004. 🧚
[Sch94] Schneier, B., Applied Cryptography, Section 8.6, John Wiley & Sons, New York, NY, 1994. 📖
[Shi00] Shirey, R., "Internet Security Glossary", RFC 2828, May 2000. 🫶 the glossary is literally the best place to look up unfamiliar terms
[SMPT01] Shacham, A., Monsour, B., Pereira, R., and M. Thomas, "IP Payload Compression Protocol (IPComp)", RFC 3173, September 2001. 🍓
[ToEgWa04] Touch, J., Eggert, L., and Y. Wang, "Use of IPsec Transport Mode for Dynamic Routing", RFC 3884, September 2004. 🌈
[VK83] V.L. Voydock & S.T. Kent, "Security Mechanisms in High-level Networks", ACM Computing Surveys, Vol. 15, No. 2, June 1983. 👑 vintage 1983 energy, ngl iconic
Authors' Addresses 🎀
Stephen Kent BBN Technologies 10 Moulton Street Cambridge, MA 02138 USA
Phone: +1 (617) 873-3988 EMail: kent@bbn.com
Karen Seo BBN Technologies 10 Moulton Street Cambridge, MA 02138 USA
Phone: +1 (617) 873-3152 EMail: kseo@bbn.com
Full Copyright Statement ©
Copyright (C) The Internet Society (2005).
This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.
This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
Intellectual Property 💜
The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.
Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.
The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.
Acknowledgement 🫶
Funding for the RFC Editor function is currently provided by the Internet Society. and that's a wrap on RFC 4301, bestie!! 🌈✨💖
📦 where this page comes from
- ietf: rfc4301 2005-12
- 💖 girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms