RFC 9028
Native NAT Traversal Mode for the Host Identity Protocol
1. Introduction โจ
Okay so bestie, this is the doc that's basically HIP (Host Identity Protocol) getting a glow-up for NAT traversal ๐ It's a brand-new, experimental mode, and the whole thing is built on top of ICE, but with HIP messages doing the work instead of STUN and TURN. Iconic. ๐ฆ
Here's the title block, the tea โ: this is RFC 9028, titled "Native NAT Traversal Mode for the Host Identity Protocol." The authors are A. Kerรคnen, J. Melรฉn, and M. Komu (Ed.), all from Ericsson. It's published as Experimental (not Standards Track), it's dated July 2021, and it's ISSN 2070-1721. Nothing is obsoleted or updated by it, so no drama there. ๐ธ
1.1. Hmm, wait, the sections are kinda... ๐
Sorry, quick correction, I got a bit carried away! The section headings in this doc are numbered exactly as written, and here we're in Section 1 (Introduction). There's no 1.1 in the original, so I'm not inventing one. Let's keep it real. ๐
The Host Identity Protocol [RFC7401] is specified to run directly on top of IPv4 or IPv6. But tbh, a lot of middleboxes on the Internet, like NATs and firewalls, often only let UDP or TCP traffic through [RFC5207]. Also, NATs usually need the host behind them to create forwarding state before outside hosts can reach it. So people came up with a bunch of methods called NAT traversal techniques to fix this. ๐ง
One of those solutions is Teredo-based NAT traversal for HIP and related Encapsulating Security Payload (ESP) traffic, which is mentioned in the HIP experiment report [RFC6538]. It comes with double tunneling overhead, so it's not the most glamorous option. ๐
Another solution is "Legacy ICE-HIP", specified in [RFC5770]. The experimental Legacy ICE-HIP spec combines the Interactive Connectivity Establishment (ICE) protocol (originally [RFC5245]) with HIP. Basically, ICE handles NAT traversal and connectivity testing, while HIP handles end-host authentication and IPsec key management. The result uses HIP, Session Traversal Utilities for NAT (STUN), and ESP messages tunneled over a single UDP flow. โจ
The benefit of ICE and its STUN / Traversal Using Relays around NAT (TURN) messaging formats is that you can reuse the NAT traversal infrastructure already out there, like STUN and TURN servers. Some middleboxes are also STUN aware and might do something "smart" when they see STUN being used, which is kinda cool. ๐ฆ
Now here's the problem, bestie. HIP doesn't play nicely with standard ICE. It's not just the kernel-space dependencies, it's also the super close integration with kernel-space IPsec. And while [RFC5770] gives us a technically workable path, HIP takes unacceptable performance drawbacks for kernel-space implementations. ๐ญ On top of that, implementing and integrating a full ICE/STUN/TURN protocol stack the Legacy ICE-HIP way is a LOT of effort and code, when we could just reuse and extend HIP messages and state machines for the same purpose. Obsessed with the efficiency here. ๐ซถ
So this document specifies an alternative NAT traversal mode called "Native ICE-HIP". It uses the HIP messaging format instead of STUN or TURN for the connectivity checks, keepalives, and data relaying. ๐ Native ICE-HIP also specifies how mobility management works in the context of NAT traversal, which the Legacy ICE-HIP spec is missing. And the native spec is based on HIPv2, whereas the legacy one is based on HIPv1. The differences from Legacy ICE-HIP are elaborated further in Appendix B. ๐
This one is giving "build on what we already have" energy, because it builds on the HIP registration extensions [RFC8003], the base exchange procedure [RFC7401], and its closing procedures, just like Legacy ICE-HIP does. So bestie, I'd recommend getting familiar with those specs first. ๐ Quick recap: the registration extensions let a HIP Initiator (usually a "client" host) ask a HIP Responder (usually a "server" host) for specific services. Those registration parameters ride along in a base exchange, which is essentially a four-way Diffie-Hellman key exchange authenticated with the end hosts' public keys. ๐ฅ
If the hosts negotiate support for ESP [RFC7402] during the base exchange, they can deliver ESP-protected application payload to each other. And when either host moves and changes its IP address, the two hosts re-establish connectivity using the mobility extensions [RFC8046]. The mobility process is a three-way procedure: the mobile host first announces its new location to the peer, then the peer tests connectivity (the so-called return routability check), and then the mobile host must respond to the announcement to activate its new location. ๐
Lowkey important: this specification builds on the mobility procedures but modifies them to be compatible with ICE. The differences in the mobility extensions are specified in Appendix C. And multihoming support as specified in [RFC8047] is left for further study. ๐
This spec also builds heavily on the ICE methodology, so it's recommended that you're familiar with the ICE specification [RFC8445], especially the overview. Native ICE-HIP does not implement all the ICE features though, so the different ICE features are cross referenced using [RFC2119] terminology for clarity. Appendix B explains the differences to ICE, and it's recommended you read that section alongside the ICE spec. Periodt. ๐
2. Terminology โจ
okay bestie, let's get the vocab down first ๐ the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" mean what BCP 14 [RFC2119] [RFC8174] says they mean, but ONLY when they show up in ALL CAPS like that ๐ this doc borrows its terms from [RFC5770], [RFC7401], [RFC8046], [RFC9063], [RFC8445], and [RFC8489]. here are the terms that keep popping up in the text ๐ฆ
ICE: Interactive Connectivity Establishment (ICE) protocol as specified in [RFC8445]. ๐ธ
Legacy ICE-HIP: this is the "Basic Host Identity Protocol (HIP) Extensions for Traversal of Network Address Translators" from [RFC5770]. this doc gives you an alternative to Legacy ICE-HIP, so it's the new hotness ๐ฅ
Native ICE-HIP: the protocol in this document, aka Native NAT Traversal Mode for HIP. โจ
Initiator: the host that starts the base exchange by sending an I1 message [RFC7401]. ๐ง
Responder: the host that gets the I1 packet from the Initiator [RFC7401]. ๐
Control Relay Server: a registrar host that forwards any kind of HIP control plane packets between the Initiator and the Responder. this host is critical ๐ญ because it relays the locators between them so they can try to set up a direct path with each other. it's used to replace HIP Rendezvous Servers [RFC8004] for hosts in private address realms. in Legacy ICE-HIP [RFC5770], this one's called "HIP Relay Server". ๐ก๏ธ
Control Relay Client: a requester host that registers with a Control Relay Server and asks it to forward its control plane traffic (aka HIP control messages). in Legacy ICE-HIP [RFC5770], this is called "HIP Relay Client". ๐ซถ
Data Relay Server: a brand new entity introduced in this document! it's a registrar host that forwards HIP related data plane packets, like Encapsulating Security Payload (ESP) [RFC7402], between two hosts. it does similar stuff to TURN servers ๐
Data Relay Client: a requester host that registers with a Data Relay Server and asks it to forward data plane traffic (e.g. ESP traffic). this functionality is new and introduced in this document. ๐
Locator: as defined in [RFC8046]: "A name that controls how the packet is routed through the network and demultiplexed by the end host. It may include a concatenation of traditional network addresses such as an IPv6 address and end-to-end identifiers such as an ESP SPI. It may also include transport port numbers or IPv6 Flow Labels as demultiplexing context, or it may simply be a network address." ๐
LOCATOR_SET (written in capital letters): a HIP control packet parameter that bundles multiple locators together [RFC8046]. โจ
HIP offer: before two end hosts can set up a channel using the NAT traversal procedures in this document, they need to swap their locators (aka candidates) with each other. in ICE, this is called Candidate Exchange, and ICE doesn't say how it happens, though Session Description Protocol (SDP) "offer/answer" is mentioned as an example. HIP's Candidate Exchange is different: it's the base exchange itself, or a later UPDATE procedure that happens after a handover. following [RFC5770] and the SDP naming conventions [RFC3264], the "HIP offer" is the Initiator's LOCATOR_SET parameter in a HIP I2 or in an UPDATE control packet. ๐
HIP answer: the Responder's LOCATOR_SET parameter in a HIP R2 or UPDATE control packet. it matches the SDP answer parameter [RFC3264] but it's HIP specific. check out the longer "HIP offer" description above too ๐
HIP connectivity checks: to get a direct end-to-end path (no Data Relay Server involved), two HIP hosts try to "punch holes" through their NAT boxes using this mechanism. it's like the ICE connectivity checks, but it uses HIP return routability checks instead. ๐ฆ
Controlling host: the controlling host [RFC8445] is always the Initiator in this specification. it nominates the candidate pair that gets used with the controlled host. ๐
Controlled host: the controlled host [RFC8445] is always the Responder in this specification. it waits for the controlling host to nominate an address candidate pair. ๐
Checklist: a list of address candidate pairs that need connectivity testing (same as in [RFC8445]). ๐ธ
Transport address: a transport-layer port plus its matching IPv4/v6 address (same as in [RFC8445]). ๐ง
Candidate: a transport address that's a potential point of contact for receiving data (same as in [RFC8445]). โจ
Host candidate: a candidate you get by binding to a specific port on an IP address on the host (same as in [RFC8445]). ๐
Server-reflexive candidate: a translated transport address of a host, as seen by a Control or Data Relay Server (same as in [RFC8445]). ๐
Peer-reflexive candidate: a translated transport address of a host, as seen by its peer (same as in [RFC8445]). ๐ซถ
Relayed candidate: a transport address that exists on a Data Relay Server. packets that arrive at this address get relayed toward the Data Relay Client. the concept is the same as in [RFC8445], except a Data Relay Server is used instead of a TURN server. ๐
Permission: in the context of a Data Relay Server, permission is similar to TURN's [RFC8656] channels. before a host can use a relayed candidate to forward traffic through a Data Relay Server, it has to activate that relayed candidate with a specific peer host. ๐
Base: similar to [RFC8445], the base of a candidate is the local source address a host uses to send packets for that candidate. for example, the base of a server-reflexive address is the local address the host used to register itself with the associated Control or Data Relay Server. the base of a host candidate is the host candidate itself. ๐
3. Overview of Operation
+--------------+
| Control |
+--------+ | Relay Server | +--------+
| Data | +----+-----+---+ | Data |
| Relay | / \ | Relay |
| Server | / \ | Server |
+--------+ / \ +--------+
/ \
/ \
/ \
/ <- Signaling -> \
/ \
+-------+ +-------+
| NAT | | NAT |
+-------+ +-------+
/ \
/ \
+-------+ +-------+
| Init- | | Resp- |
| iator | | onder |
+-------+ +-------+
Figure 1: Example Network Configuration
okay so picture Figure 1 ๐ in this setup, both the Initiator and the Responder are chilling behind one or more NATs, and both private networks are hooked up to the public Internet. to be reachable from behind a NAT, at least the Responder has to be registered with a Control Relay Server that's reachable on the public Internet ๐ญ the Responder can also register with a Data Relay Server that forwards the data plane if NAT traversal fails. the Initiator doesn't strictly need a Data Relay Server, but it can switch roles with other hosts, and the Responder's Data Relay Server connection might fail, so the Initiator might also need to register with a Control and/or Data Relay Server. ๐ฆ
also, a Control and Data Relay doesn't keep the source address of a passing packet. it always rewrites the source address and source port of a packet it forwards to its own ๐
as a starting point, we assume the Initiator already knows the Responder's Host Identity Tag (HIT) and the address(es) of the Responder's Control Relay Server(s). how the Initiator finds out about the Responder's Control Relay Server is outside the scope of this document, but it could be learned through DNS or another name service ๐ง
the first steps are for both the Initiator and the Responder to register with a Control Relay Server (it doesn't have to be the same one!) and collect a set of address candidates. the hosts use either Control Relay Servers or Data Relay Servers to gather those candidates. next, the HIP base exchange happens: the HIP control packets get encapsulated in UDP datagrams and sent through the Responder's Control Relay Server. during the base exchange, each HIP host learns its peer's candidate addresses through the HIP offer/answer procedure embedded in it โจ
once the base exchange is done, the two HIP hosts have a working session for signaling through a Control Relay Server ๐ but they still need to find a better path for the ESP data flow, ideally one that doesn't use a Data Relay Server. so connectivity checks run until a working pair of addresses turns up ๐ if that works out, the hosts end up with a UDP-based tunnel that traverses both NATs, with data flowing directly from NAT to NAT or through a Data Relay Server. at that point, HIP signaling can also be sent over the same address/port pair, and it gets demultiplexed (aka separated) from IPsec as described in the UDP encapsulation standard for IPsec [RFC3948] ๐ finally, the two hosts send NAT keepalives as needed to keep their UDP-tunnel state alive in the associated NAT boxes ๐
if either host knows it isn't behind a NAT, the hosts can negotiate a different NAT traversal mode during the base exchange. that mode skips HIP connectivity checks and only uses UDP encapsulation of HIP and ESP ๐ธ it's also possible for the Initiator to try a base exchange with and without UDP encapsulation at the same time. if the base exchange without UDP encapsulation succeeds, then no HIP connectivity checks or UDP encapsulation of ESP are needed at all! ๐
4. Protocol Description
this section is the normative stuff for the "Native ICE-HIP" protocol extension ๐ most of the procedures look like what's in [RFC5770], just with different or additional parameter types and values. there's also a new type of relaying server, the Data Relay Server, specified here ๐ and heads up: HIP version 2 [RFC7401] MUST be used instead of HIPv1 with this NAT traversal mode ๐ฅ
4.1. Relay Registration โจ
Okay so bestie, two hosts stuck behind NATs need a reliable way to swap info, or they're just yelling into the void ๐. That's where the "HIP Relay Server" from [RFC5770] comes in ๐ง. It relays HIP control plane traffic over UDP in NATed environments and forwards HIP control packets between the Initiator and the Responder. In this doc we call it the "Control Relay Server" so everything lines up with the rest of the terminology ๐ . You register to it using the RELAY_UDP_HIP parameter, which we'll get into below โจ.
To also make sure data plane delivery survives all the different NAT devices out there, a host MAY also register for UDP-encapsulated ESP relaying using Registration Type RELAY_UDP_ESP (value 3) ๐ฆ. This can be bundled with the Control Relay Server or offered separately on another server. If the server supports UDP-encapsulated ESP relaying, the host is allowed to register for a data-relaying service using the registration extensions in Section 3.3 of [RFC8003] ๐. If the server has enough relaying resources (free port numbers, bandwidth, etc.), it opens a UDP port on one of its addresses and tells the registering host the address and port using the RELAYED_ADDRESS parameter (defined in Section 5.12 in this document) ๐ธ. If the Data Relay Server would accept the data-relaying request but doesn't currently have enough resources, it MUST reject the request with Failure Type "Insufficient resources" [RFC8003] ๐.
The registration process follows the generic registration extensions defined in [RFC8003]. The HIP control plane relaying registration follows [RFC5770], but the data plane registration is its own thing ๐. It's worth noting that if the HIP control and data plane relay services live on different hosts, the client has to register separately to each one. In the example below, both services are coupled on a single host. The text uses "Relay Client" and "Relay Server" as shorthand when the procedures apply to both control and data cases ๐ซถ.
Control/Data Control/Data
Relay Client (Initiator) Relay Server (Responder)
| 1. UDP(I1) |
+---------------------------------------------------------------->|
| |
| 2. UDP(R1(REG_INFO(RELAY_UDP_HIP,[RELAY_UDP_ESP]))) |
|<----------------------------------------------------------------+
| |
| 3. UDP(I2(REG_REQ(RELAY_UDP_HIP),[RELAY_UDP_ESP])) |
+---------------------------------------------------------------->|
| |
| 4. UDP(R2(REG_RES(RELAY_UDP_HIP,[RELAY_UDP_ESP]), REG_FROM, |
| [RELAYED_ADDRESS])) |
|<----------------------------------------------------------------+
| |
Figure 2: Example Registration with a HIP Relay
Okay, so the steps go like this ๐.
Step 1 is the Relay Client (Initiator) kicking things off by sending an I1 packet over UDP to the Relay Server. It is RECOMMENDED that the Relay Client pick a random source port number from the ephemeral port range 49152-65535 for starting a base exchange. Alternatively, a host MAY also use one fixed port for starting all outgoing connections. Just know that the allocated port MUST be kept until all of the corresponding HIP associations are closed ๐ฅ. It is RECOMMENDED that the Relay Server listen for incoming connections on UDP port 10500. If some other port number is used, potential Relay Clients need to know about it ๐ง.
Step 2 is the Relay Server (Responder) listing the services it supports in the R1 packet ๐. Support for HIP control plane relaying over UDP is shown by the Registration Type value RELAY_UDP_HIP (see Section 5.9). If the server also does ESP relaying over UDP, it adds the Registration Type value RELAY_UDP_ESP too โจ.
Step 3 is the Relay Client choosing which services it wants and listing them in the REG_REQ parameter ๐. For the Control Relay service, it lists the RELAY_UDP_HIP value in the request parameter. If the Relay Client also needs ESP relaying over UDP, it lists RELAY_UDP_ESP as well ๐ฆ.
Step 4 is the Relay Server wrapping up the registration with an R2 packet and acknowledging the registered services in the REG_RES parameter ๐. Any unsuccessful registrations get flagged in the REG_FAILED parameter of R2. The Relay Server also includes a REG_FROM parameter, which holds the transport address of the Relay Client as the Relay Server sees it (the server-reflexive candidate) ๐ซถ. If the Relay Client signed up for ESP relaying, the Relay Server includes a RELAYED_ADDRESS parameter describing the UDP port allocated to it for that. Here's the important bit: the Data Relay Client must first activate this UDP port by sending an UPDATE message to the Data Relay Server that includes a PEER_PERMISSION parameter, as described in Section 4.12.1. This has to happen both after the base exchange and after handover procedures ๐ . Also, the Data Relay Server should follow the port allocation recommendations in Section 7.5 โญ.
Once registered, the Relay Client periodically sends NAT keepalives to the Relay Server so the NAT bindings between them stay alive. The keepalive extensions are described in Section 4.10 ๐ธ.
The Data Relay Client MUST keep an active HIP association with the Data Relay Server for as long as it needs the data-relaying service ๐. When the HIP association gets closed (or times out), or the registration lifetime runs out without the Data Relay Client refreshing it, the Data Relay Server MUST stop relaying packets for that host and close the corresponding UDP port. The exception is when other Data Relay Clients are still using that port ๐.
The Data Relay Server SHOULD offer a different relayed address and port for each Data Relay Client, because not doing so can cause problems with stateful firewalls (see Section 7.5) ๐.
When a Control Relay Client sends an UPDATE (for example, because the host moved or it wants to renew its service registration), the Control Relay Server MUST follow the general guidelines defined in [RFC8003]. The difference is that all UPDATE messages get delivered on top of UDP ๐ฆ. On top of that, the Control Relay Server MUST include the REG_FROM parameter in all UPDATE responses sent to the Control Relay Client. This applies to both service registration renewals and host movement. It's especially important for host movement, because that's how the Control Relay Client learns its new server-reflexive address candidate ๐.
A Data Relay Client can request multiple relayed candidates from the Data Relay Server (for example, for the reasons in Section 4.12.3) โจ. After the base exchange with registration, the Data Relay Client can request additional relayed candidates in a similar way to how it did during the base exchange. It does this by sending an UPDATE message with a REG_REQ parameter asking for the RELAY_UDP_ESP service. That UPDATE message MUST also include a SEQ and an ECHO_REQUEST_SIGNED parameter ๐ง. The Data Relay Server MUST respond with an UPDATE message that includes the matching response parameters: REG_RES, ACK and ECHO_REQUEST_SIGNED. If the Data Relay Server allocated a new relayed UDP port for the Data Relay Client, the REG_RES parameter MUST list RELAY_UDP_ESP as a service, and the UPDATE message MUST also include a RELAYED_ADDRESS parameter describing that relayed UDP port ๐. The Data Relay Server MUST also include the server-reflexive candidate in a REG_FROM parameter. Worth mentioning too: the Data Relay Client MUST activate the UDP port as described in Section 4.12.1 before it can be used for any ESP relaying ๐ฅ.
A Data Relay Client can get rid of a relayed candidate in two ways. It can wait for the lifetime to expire, or it can explicitly ask for it with zero lifetime using the UPDATE mechanism ๐. To expire all relayed candidates, the Data Relay Client can send a REG_REQ parameter with zero lifetime to the Data Relay Server. To expire one specific relayed candidate, the Data Relay Client MUST also include a RELAYED_ADDRESS parameter, as sent by the server, in the UPDATE message ๐ญ. When the HIP association is closed (through the CLOSE-CLOSE-ACK procedure, initiated by either party), the Data Relay Server MUST also expire all relayed candidates ๐ .
Last but definitely not least, please also check out Section 7.8 for protection against cross-protocol attacks, for both the Control Relay Client and the Control Relay Server ๐ซถ.
4.2. Transport Address Candidate Gathering at the Relay Client โจ
okay bestie, so an Initiator needs to gather a set of address candidates before it contacts a (non-relay) Responder ๐ฆ. These candidates are used for connectivity checks, which let two hosts find a direct, non-relayed path to talk to each other. One server-reflexive candidate can be discovered during registration with the Control Relay Server, from the REG_FROM parameter, and another can come from the Data Relay Server if one is being used ๐
.
The candidate gathering can happen at any time, but it has to be done before sending an I2 or R2 in the base exchange if ICE-HIP-UDP mode is going to be used for the connectivity checks โฐ. It is RECOMMENDED that all three types of candidates (host, server reflexive, and relayed) get gathered to maximize the probability of successful NAT traversal ๐ซถ. However, if no Data Relay Server is used, and the host has only a single local IP address to use, the host MAY use the local address as the only host candidate, and the address from the REG_FROM parameter discovered during the Control Relay Server registration as a server-reflexive candidate. In this case, no further candidate gathering is needed ๐ธ.
A Data Relay Client MAY register only a single relayed candidate that it uses with multiple other peers ๐. However, it is RECOMMENDED that a Data Relay Client registers a new server relayed candidate for each of its peers, for the reasons described in Section 4.12.3 ๐. The procedures for registering multiple relayed candidates are described in Section 4.1 ๐.
If a Relay Client has more than one network interface, it can discover additional server-reflexive candidates by sending UPDATE messages from each of its interfaces to the Relay Server ๐ง. Each such UPDATE message MUST include the following parameters: the registration request (REG_REQ) parameter with Registration Type CANDIDATE_DISCOVERY (value 4) and the ECHO_REQUEST_SIGNED parameter. When a Control Relay Server receives an UPDATE message with a registration request containing a CANDIDATE_DISCOVERY type, it MUST include a REG_FROM parameter in the response, containing the same information as if this were a Control Relay Server registration (in addition to the mandatory ECHO_RESPONSE_SIGNED parameter). This request type SHOULD NOT create any state at the Control Relay Server ๐.
The rules in Section 5.1.1 of [RFC8445] for candidate gathering are followed here. A number of host candidates (loopback, anycast and others) should be excluded, as described in the ICE specification (Section 5.1.1.1 of [RFC8445]). Relayed candidates SHOULD be gathered in order to guarantee successful NAT traversal, and implementations SHOULD support this functionality even if it will not be used in deployments, so it can be enabled by software configuration update if needed at some point ๐ฅ. Similarly, as explained in the ICE specification (Section 5.1.1.2 of [RFC8445]), if an IPv6-only host is in a network that utilizes NAT64 [RFC6146] and DNS64 [RFC6147] technologies, it may also gather IPv4 server-reflexive and/or relayed candidates from IPv4-only Control or Data Relay Servers. IPv6-only hosts SHOULD also utilize IPv6 prefix discovery [RFC7050] to discover the IPv6 prefix used by NAT64 (if any), and generate server-reflexive candidates for each IPv6-only interface accordingly. The NAT64 server-reflexive candidates are prioritized like IPv4 server-reflexive candidates ๐.
HIP-based connectivity can be utilized by IPv4 applications using Local Scope Identifiers (LSIs), and by IPv6-based applications using HITs. The LSIs and HITs of the local virtual interfaces MUST be excluded in the candidate gathering phase as well, to avoid creating unnecessary loopback connectivity tests ๐.
Gathering of candidates MAY also be performed by other means than described in this section ๐ง. For example, the candidates could be gathered as specified in Section 4.2 of [RFC5770] if STUN servers are available, or if the host has just a single interface and no STUN or Data Relay Server is available.
Each local address candidate MUST be assigned a priority. The following recommended formula (as described in [RFC8445]) SHOULD be used:
priority = (2^24)*(type preference) + (2^8)*(local preference) +
(2^0)*(256 - component ID)
In the formula, the type preference follows the ICE specification (as defined in Section 5.1.2.1 of [RFC8445]). The RECOMMENDED values are 126 for host candidates, 100 for server-reflexive candidates, 110 for peer-reflexive candidates, and 0 for relayed candidates. The highest value is 126 (the most preferred), and the lowest is 0 (last resort) ๐. For all candidates of the same type, the preference type value MUST be identical, and, correspondingly, the value MUST be different for different types. For peer-reflexive values, the type preference value MUST be higher than for server-reflexive types. It should be noted that peer-reflexive values are learned later, during connectivity checks โญ.
Following the ICE specification, the local preference MUST be an integer from 0 (lowest preference) to 65535 (highest preference), inclusive. In the case the host has only a single address candidate, the value SHOULD be 65535. In the case of multiple candidates, each local preference value MUST be unique. Dual-stack considerations for IPv6 also apply here, as defined in Section 5.1.2.2 of [RFC8445] ๐ฆ.
Unlike with SDP used in conjunction with ICE, this protocol only creates a single UDP flow between the two communicating hosts, so only a single component exists. Hence, the component ID value MUST always be set to 1 ๐.
As defined in Section 14.3 of [RFC8445], the retransmission timeout (RTO) for address gathering from a Control/Data Relay Server SHOULD be calculated as follows:
RTO = MAX (1000 ms, Ta * (Num-Of-Cands))
where Ta is the value used for the connectivity check pacing, and Num-Of-Cands is the number of server-reflexive and relay candidates. A smaller value than 1000 ms for the RTO MUST NOT be used ๐ซ.
4.3. NAT Traversal Mode Negotiation ๐
this section is all about a non-critical parameter type called NAT_TRAVERSAL_MODE, with a brand new mode called ICE-HIP-UDP ๐ง. The presence of the new mode in the NAT_TRAVERSAL_MODE parameter in a HIP base exchange means that the end host supports the NAT traversal extensions described in this document. Since the parameter is non-critical (as defined in Section 5.2.1 of [RFC7401]), it can be ignored by an end host, which means the host is not required to support it, or may decline to use it ๐คทโโ๏ธ.
With registration with a Control/Data Relay Server, it's usually enough to use the UDP-ENCAPSULATION mode of NAT traversal, since the Relay Server is assumed to be in public address space. So the Relay Server SHOULD propose the UDP-ENCAPSULATION mode as the preferred or only mode ๐ . The NAT traversal mode negotiation in a HIP base exchange is illustrated in Figure 3. It's worth noting that the Relay Server could be located between the hosts, but it's omitted here for simplicity ๐ธ.
Initiator Responder
| 1. UDP(I1) |
+----------------------------------------------------------------->|
| |
| 2. UDP(R1(.., NAT_TRAVERSAL_MODE(ICE-HIP-UDP), ..)) |
|<-----------------------------------------------------------------+
| |
| 3. UDP(I2(.., NAT_TRAVERSAL_MODE(ICE-HIP-UDP), ENC(LOC_SET), ..))|
+----------------------------------------------------------------->|
| |
| 4. UDP(R2(.., ENC(LOC_SET), ..)) |
|<-----------------------------------------------------------------+
| |
Figure 3: Negotiation of NAT Traversal Mode
In step 1, the Initiator sends an I1 to the Responder ๐จ.
In step 2, the Responder responds with an R1. As specified in [RFC5770], the NAT_TRAVERSAL_MODE parameter in R1 contains a list of NAT traversal modes the Responder supports. The mode specified in this document is ICE-HIP-UDP (value 3) ๐ฆ.
In step 3, the Initiator sends an I2 that includes a NAT_TRAVERSAL_MODE parameter. It contains the mode selected by the Initiator from the list of modes offered by the Responder. If ICE-HIP-UDP mode was selected, the I2 also includes the "Transport address" locators (as defined in Section 5.7) of the Initiator, in a LOCATOR_SET parameter (denoted here with LOC_SET). With ICE-HIP-UDP mode, the LOCATOR_SET parameter MUST be encapsulated within an ENCRYPTED parameter (denoted here with ENC), according to the procedures in Sections 5.2.18 and 6.5 in [RFC7401]. The locators in I2 are the "HIP offer" ๐.
In step 4, the Responder concludes the base exchange with an R2 packet. If the Initiator chose ICE-HIP-UDP traversal mode, the Responder includes a LOCATOR_SET parameter in the R2 packet. With ICE-HIP-UDP mode, the LOCATOR_SET parameter MUST be encapsulated within an ENCRYPTED parameter, according to the procedures in Sections 5.2.18 and 6.5 in [RFC7401]. The locators in R2, encoded like the locators in I2, are the "ICE answer" โจ. If the NAT traversal mode selected by the Initiator is not supported by the Responder, the Responder SHOULD reply with a NOTIFY packet with type NO_VALID_NAT_TRAVERSAL_MODE_PARAMETER and abort the base exchange ๐.
4.4. Connectivity Check Pacing Negotiation โฐ
As explained in Legacy ICE-HIP [RFC5770], when a NAT traversal mode with connectivity checks is used, new transactions should not be started too fast, to avoid congestion and overwhelming the NATs ๐. For this purpose, during the base exchange, hosts can negotiate a transaction pacing value, Ta, using a TRANSACTION_PACING parameter in R1 and I2 packets. The parameter contains the minimum time (expressed in milliseconds) the host would wait between two NAT traversal transactions, such as starting a new connectivity check or retrying a previous check. The value that both hosts use is the higher of the two offered values ๐ง.
The minimum Ta value SHOULD be configurable, and if no value is configured, a value of 50 ms MUST be used. Guidelines for selecting a Ta value are given in Appendix A ๐. Hosts MUST NOT use values smaller than 5 ms for the minimum Ta, since such values may not work well with some NATs (as explained in [RFC8445]) ๐
โโ๏ธ. The Initiator MUST NOT propose a smaller value than what the Responder offered. If a host does not include the TRANSACTION_PACING parameter in the base exchange, a Ta value of 50 ms MUST be used as that host's minimum value ๐ซถ.
4.5. Base Exchange via Control Relay Server ๐ฆ
okay so this section is all about how the Initiator and Responder do their base exchange through a Control Relay Server ๐
. Connectivity pacing (we call it TA_P here) already got covered in Section 4.4, so we're not redoing it ๐. Same deal for the NAT traversal mode negotiation (NAT_TM in the example), which lives in Section 4.3. The big rule to know up front: if a Control Relay Server gets an R1 or I2 packet that's missing the NAT traversal mode parameter, it MUST drop it, and it SHOULD send a NOTIFY error packet with type NO_VALID_NAT_TRAVERSAL_MODE_PARAMETER back to whoever sent the R1 or I2 ๐ญ.
It is RECOMMENDED that the Initiator send its I1 packet encapsulated in UDP when it's headed to an IP address of the Responder ๐ซถ. The Responder MUST respond to that I1 with a UDP-encapsulated R1 packet, and all the rest of the communication for the HIP association MUST also use UDP encapsulation. Consistency is everything, bestie ๐.
Figure 4 shows the whole base exchange via a Control Relay Server โจ. We're assuming the Responder (aka the Control Relay Client) has already registered with the Control Relay Server. The Initiator might have registered somewhere too, either with the same server or a different one, but the base exchange always goes through the Control Relay Server of the Responder. No skipping that step, periodt ๐.
Initiator Control Relay Server Responder
| 1. UDP(I1) | |
+--------------------------------->| 2. UDP(I1(RELAY_FROM)) |
| +------------------------------->|
| | |
| | 3. UDP(R1(RELAY_TO, NAT_TM, |
| | TA_P)) |
| 4. UDP(R1(RELAY_TO, NAT_TM, |<-------------------------------+
| TA_P)) | |
|<---------------------------------+ |
| | |
| 5. UDP(I2(ENC(LOC_SET)), | |
| NAT_TM, TA_P)) | |
+--------------------------------->| 6. UDP(I2(ENC(LOC_SET), |
| | RELAY_FROM, NAT_TM, TA_P))|
| +------------------------------->|
| | |
| | 7. UDP(R2(ENC(LOC_SET), |
| 8. UDP(R2(ENC(LOC_SET), | RELAY_TO)) |
| RELAY_TO)) |<-------------------------------+
|<---------------------------------+ |
| | |
Figure 4: Base Exchange via a HIP Relay Server
In step 1, the Initiator sends an I1 packet over UDP through the Control Relay Server to the Responder ๐. In the HIP header, the source HIT is the Initiator's and the destination HIT is the Responder's. The Initiator sends the I1 from its IP address to the Control Relay Server's IP address over UDP.
In step 2, the Control Relay Server catches the I1 packet ๐. If the destination HIT belongs to a successfully registered Control Relay Client (the host labelled "Responder" in Figure 4), the server processes the packet. Otherwise, the Control Relay Server MUST drop the packet silently ๐. The server then tacks a RELAY_FROM parameter onto the I1, holding the transport source address and port of the I1 as the Control Relay Server saw it. It protects the I1 with RELAY_HMAC, except the parameter type is different, as described in Section 5.8. After that, the Control Relay Server swaps the source and destination ports and IP addresses so they match what the Responder used when it registered, meaning the reverse of the R2 from registration. The Control Relay Server MUST recalculate the transport checksum and forward the packet to the Responder ๐.
In step 3, the Responder receives the I1 packet โจ. It processes the packet according to the rules in [RFC7401]. On top of that, the Responder validates the RELAY_HMAC following Section 5.8 and silently drops the packet if validation fails. Assuming everything checks out, the Responder replies with an R1 packet that includes RELAY_TO and NAT traversal mode parameters. The Responder MUST include ICE-HIP-UDP in the NAT traversal modes. The RELAY_TO parameter MUST contain the same information as RELAY_FROM, which is the Initiator's transport address, but the parameter type is different. And here's a fun one: RELAY_TO is not integrity protected by the signature of the R1, which lets the Responder pre-create R1 packets ๐ง.
In step 4, the Control Relay Server receives the R1 packet ๐ซฃ. It drops the packet silently if the source HIT belongs to a Control Relay Client that hasn't successfully registered. The Control Relay Server MAY verify the signature of the R1 packet and drop it if the signature is invalid. Otherwise, the server rewrites the source address and port, and changes the destination address and port to match the RELAY_TO information. Last but not least, it recalculates the transport checksum and forwards the packet ๐ฌ.
In step 5, the Initiator receives the R1 packet and processes it according to [RFC7401] ๐. The Initiator MAY use the address in the RELAY_TO parameter as a local peer-reflexive candidate for this HIP association, as long as it's different from all known local candidates. Then the Initiator replies with an I2 packet that uses the destination transport address of the R1 as its source address and port. The I2 packet carries a LOCATOR_SET parameter inside an ENCRYPTED parameter, listing all the HIP candidates (the HIP offer) of the Initiator. The candidates are encoded using the format defined in Section 5.7. The I2 packet MUST also contain a NAT traversal mode parameter that includes ICE-HIP-UDP mode. The ENCRYPTED parameter, along with how its key material gets generated, is explained in detail in Sections 5.2.18 and 6.5 in [RFC7401] ๐.
In step 6, the Control Relay Server receives the I2 packet ๐ฆ. It appends a RELAY_FROM and a RELAY_HMAC to the I2 in the same way as step 2, then forwards the packet to the Responder.
In step 7, the Responder receives the I2 and processes it according to [RFC7401] ๐ธ. It validates the RELAY_HMAC following Section 5.8 and silently drops the packet if validation fails. Then it replies with an R2 packet and includes a RELAY_TO parameter, just like it did in step 3. The R2 packet carries a LOCATOR_SET parameter inside an ENCRYPTED parameter, listing all the HIP candidates (the ICE answer) of the Responder. The RELAY_TO parameter is protected by the Hashed Message Authentication Code (HMAC). The ENCRYPTED parameter and its key material generation are described in detail in Sections 5.2.18 and 6.5 in [RFC7401] ๐.
In step 8, the Control Relay Server processes the R2 the same way as step 4 ๐. Then it forwards the packet to the Initiator. Once the Initiator has received the R2 and processed it successfully, the base exchange is complete ๐.
Hosts MUST include the address of one or more Control Relay Servers (including the one used for the initial signaling) in the LOCATOR_SET parameter in I2 and R2 messages if they want to keep using those servers for relaying HIP signaling right after the base exchange finishes ๐
. The traffic type of these addresses MUST be "HIP signaling" (see Section 5.7), and they MUST NOT be used for the connectivity tests described in Section 4.6 ๐
โโ๏ธ. If the Control Relay Server locator that relayed the base exchange isn't included in the I2 or R2 LOCATOR_SET parameters, it SHOULD NOT be used after the base exchange. Instead, further HIP signaling SHOULD use the same path as the data traffic ๐ค๏ธ. It is RECOMMENDED to stick with the same Control Relay Server for the whole lifetime of the host association that was used to forward the base exchange, if the Responder includes it in the locator parameter of the R2 message ๐ซถ.
4.6. Connectivity Checks ๐
When the Initiator and Responder finish the base exchange through the Control Relay Server, they both use the Control Relay Server's IP address as the destination address for their packets ๐. The address of the Control Relay Server MUST NOT be used as a destination for data plane traffic, unless that server also supports Data Relay Server functionality and the Client has successfully registered to use it. When NAT traversal mode with ICE-HIP-UDP gets successfully negotiated and selected, the Initiator and Responder MUST start the connectivity checks to try to get direct end-to-end connectivity through NAT devices โจ. Worth noting: the connectivity checks MUST be completed even if no ESP_TRANSFORM ends up being negotiated and selected ๐.
The connectivity checks follow the ICE methodology [ICE-NONSIP], except that UDP-encapsulated HIP control messages get used instead of ICE messages ๐ฆ. As the ICE specification says, the basic procedure for connectivity checks has three phases: sorting the candidate pairs by priority, sending checks in that prioritized order, and acknowledging the checks from the peer host ๐.
The Initiator MUST take the role of controlling host, and the Responder acts as the controlled host ๐. Those roles MUST persist for the entire HIP association lifetime, and they get reused even during mobility UPDATE procedures ๐. If both communicating nodes start talking to each other with an I1 packet, the conflict gets resolved as defined in Section 6.7 of [RFC7401]: the host with the "larger" HIT changes its role to Responder. Drama alert ๐จ, but here's the rule: the host changing its role to Responder MUST also switch to the controlled role ๐.
The protocol follows the standard HIP UPDATE sending and processing rules defined in Sections 6.11 and 6.12 in [RFC7401] ๐
, but some new parameters are introduced: CANDIDATE_PRIORITY, MAPPED_ADDRESS, NOMINATE, PEER_PERMISSION, and RELAYED_ADDRESS ๐ง.
4.6.1. Connectivity Check Procedure โจ
Okay so Figure 5 shows connectivity checks in a super simplified scenario where the Initiator and Responder only have ONE candidate pair to check ๐ซถ. Usually NATs drop messages until both sides have sent something using the same port pair ๐. Here the Responder sends a connectivity check first, but the Initiator's NAT drops it. Then the Initiator's check gets through to the Responder because it uses the same port pair as that first message ๐ฆ. Also, real life is messier! The flow below is idealistic, and in practice more messages would get dropped, especially at the start. Connectivity tests always begin with the highest-priority candidates, which are host candidates, and those wouldn't reach the recipient in this scenario ๐.
Here's the figure:
Initiator NAT1 NAT2 Responder
| | 1. UDP(UPDATE(SEQ, CAND_PRIO, | |
| | ECHO_REQ_SIGN)) | |
| X<-----------------------------------+----------------+
| | | |
| 2. UDP(UPDATE(SEQ, ECHO_REQ_SIGN, CAND_PRIO)) | |
+-------------+------------------------------------+--------------->|
| | | |
| 3. UDP(UPDATE(ACK, ECHO_RESP_SIGN, MAPPED_ADDR)) | |
|<------------+------------------------------------+----------------+
| | | |
| 4. UDP(UPDATE(SEQ, ECHO_REQ_SIGN, CAND_PRIO)) | |
|<------------+------------------------------------+----------------+
| | | |
| 5. UDP(UPDATE(ACK, ECHO_RESP_SIGN, MAPPED_ADDR)) | |
+-------------+------------------------------------+--------------->|
| | | |
| 6. Other connectivity checks using UPDATE over UDP |
|<------------+------------------------------------+---------------->
| | | |
| 7. UDP(UPDATE(SEQ, ECHO_REQ_SIGN, CAND_PRIO, NOMINATE)) |
+-------------+------------------------------------+--------------->|
| | | |
| 8. UDP(UPDATE(SEQ, ACK, ECHO_REQ_SIGN, ECHO_RESP_SIGN, |
| NOMINATE)) | |
|<------------+------------------------------------+----------------+
| | | |
| 9. UDP(UPDATE(ACK, ECHO_RESP_SIGN)) | |
+-------------+------------------------------------+--------------->+
| | | |
| 10. ESP data traffic over UDP | |
+<------------+------------------------------------+--------------->+
| | | |
Figure 5: Connectivity Checks
Okay, let's go step by step ๐.
In step 1, the Responder sends a connectivity check to the Initiator, and the Initiator's NAT drops it ๐. The message carries a bunch of parameters. As specified in [RFC7401], the SEQ parameter holds a running sequence identifier for the connectivity check ๐ข. The candidate priority (CAND_PRIO in the figure) tells you how important the address candidate being tested is โญ. The ECHO_REQUEST_SIGNED parameter (ECHO_REQ_SIGN in the figure) carries a nonce, and the recipient has to sign it and echo it back exactly as it is ๐.
In step 2, the Initiator sends a connectivity check using the same address pair candidate as in the previous step, and this time the message gets through both NATs ๐. It has the same parameters as the previous step. Worth noting: the sequence identifier is assigned locally by the Initiator, so it can be different from the one in the previous step ๐ธ.
In step 3, the Responder has received that check from the Initiator and starts building a response ๐. Since the Initiator's message included a SEQ, the Responder has to acknowledge it with an ACK parameter. The nonce from the echo request also gets echoed back, this time in an ECHO_RESPONSE_SIGNED parameter (ECHO_RESP_SIGN in the figure). The Responder also adds a MAPPED_ADDRESS parameter (MAPPED_ADDR in the figure), which holds the transport address of the Initiator as the Responder sees it. That's the peer-reflexive candidate ๐ฆ. The message reaches the Initiator, and when it does, the Initiator marks the candidate pair as valid โ
.
In step 4, the Responder retransmits the connectivity check from step 1, since nobody has acknowledged it yet ๐.
In step 5, the Initiator answers the Responder's previous check ๐
. It acknowledges the SEQ from that message with an ACK parameter, and it handles ECHO_REQUEST_SIGNED with ECHO_RESPONSE_SIGNED. It also includes the MAPPED_ADDR parameter with the peer-reflexive candidate. This response reaches the Responder, and when it does, the Responder marks the candidate pair as valid ๐.
In step 6, even though both hosts now have valid address candidates, they keep testing the remaining candidates the same way as before ๐ง. Every connectivity check has its own unique sequence number in the SEQ parameter, so no two checks are mixed up ๐ข.
In step 7, the Initiator has finished testing all the address candidates and nominates one to use ๐. It sends an UPDATE message on the selected candidates with a bunch of parameters: SEQ, ECHO_REQUEST_SIGNED, CANDIDATE_PRIORITY, and the NOMINATE parameter.
In step 8, the Responder gets that message with NOMINATE in it and sends a reply that also includes NOMINATE, plus a few other parameters ๐. The ACK and ECHO_RESPONSE_SIGNED parameters acknowledge the SEQ and ECHO_REQUEST_SIGNED from the Initiator's message. The Responder also includes its own SEQ and ECHO_REQUEST_SIGNED so it can get an acknowledgment back from the Initiator ๐ซถ.
In step 9, the Initiator finishes the nomination by confirming it got the Responder's message ๐. In this confirmation, ACK and ECHO_RESPONSE_SIGNED line up with the SEQ and ECHO_REQUEST_SIGNED from the Responder's step 8 message โจ.
In step 10, the Initiator and Responder can start sending application payloads over the candidates that got nominated ๐.
Heads up, bestie ๐จ: if either host has registered a relayed address candidate from a Data Relay Server, the host MUST activate that address before doing connectivity checks. It does this by sending an UPDATE message with the PEER_PERMISSION parameter, as described in Section 4.12.1. If it doesn't, the Data Relay Server drops the ESP packets that use the relayed address ๐.
Now for a plot twist ๐. Say both the Initiator and the Responder are advertising their own relayed address candidates. It's possible the two hosts end up picking those two relayed addresses through the ICE nomination algorithm. That can actually be a good thing, and even desirable for privacy reasons ๐. But it's pretty unlikely, because relayed address candidates get a low priority. If it does happen, though, the nominated address pair is always symmetric ๐. The nomination algorithm stops asymmetric pairs, where each side picks a different pair. For example, a Data Relay Client wouldn't be allowed to use its own Data Relay Server to send data straight to its peer while receiving data from the Data Relay Server of its peer. Iconic behaviour from the algorithm, honestly ๐ โจ.
4.6.2. Rules for Connectivity Checks โจ
okay bestie, the HITs of both hosts MUST be used as credentials in this protocol ๐ (this is different from ICE, which uses username-password fragments). A HIT pair uniquely identifies its HIT association, and a SEQ number in an UPDATE message identifies one particular connectivity check. iconic, right? ๐
All of the connectivity check messages MUST be protected with HIP_HMAC and signatures ๐ (the illustrations in this spec leave them out to keep things simple, but they're still required) according to [RFC7401]. Each connectivity check a host sends MUST include a SEQ parameter and an ECHO_REQUEST_SIGNED parameter, and the peer MUST respond to these using ACK and ECHO_RESPONSE_SIGNED following the rules in [RFC7401]. The vibe is very "every message gets a reply" ๐ซถ
The host that sends a connectivity check MUST check that the response uses the same pair of UDP ports, and it MUST drop the packet if it doesn't. no mismatched ports allowed, periodt ๐ โโ๏ธ
A host may get a connectivity check before it has received the candidates from its peer ๐. When that happens, the host MUST immediately queue a response by putting it in the triggered-check queue, and then keep waiting for the candidates. a host MUST NOT select a candidate pair until it has verified that pair with a connectivity check as defined in Section 4.6.1. no shortcuts, bestie ๐ซ
Section 5.3.5 of [RFC7401] says UPDATE packets have to include either a SEQ or an ACK parameter (or both ๐คธโโ๏ธ). In the connectivity check procedure from Section 4.6.1, each SEQ parameter should be acknowledged separately. Now here's the drama ๐ญ: because of NATs, some of the SEQ parameters sent in connectivity checks will get lost or arrive out of order. From the receiver's side this is fine, since it just "blindly" acknowledges the SEQ ๐. The sender, though, needs to be ready for lost sequence identifiers and for ACK parameters that show up out of order.
As specified in [RFC7401], one ACK parameter may acknowledge multiple sequence identifiers. The earlier examples don't show this, but it's also allowed when using ICE-HIP-UDP mode โจ.
In ICE-HIP-UDP mode, a retransmission of a connectivity check SHOULD be sent with the same sequence identifier in the SEQ parameter ๐. Some tested address candidates will never produce a working address pair, so they may cause retransmissions. Once an address pair has been nominated successfully, a host SHOULD immediately stop sending those retransmissions ๐.
Full ICE procedures for prioritizing candidates, removing redundant candidates, forming checklists (including pruning), and triggered-check queues MUST be followed as specified in Section 6.1 of [RFC8445] ๐. The one exception is that the foundation, frozen candidates, and default candidates are not used. From the point of view of the ICE specification [RFC8445], this protocol uses a component ID of 1 on all candidates, and the foundation of every candidate is unique ๐ฆ. This spec only defines "full ICE" mode, and "lite ICE" is not supported. the reasons for leaving those features out are explained in Appendix B ๐.
The connectivity check messages MUST be paced by the Ta value negotiated during the base exchange, as described in Section 4.4 โฑ๏ธ. If neither host announced a minimum pacing value, a value of 50 ms MUST be used.
Both hosts MUST form a priority-ordered checklist and begin checking transactions every Ta milliseconds, as long as the checks are running and there are candidate pairs whose tests have not started ๐ธ. The retransmission timeout (RTO) for the connectivity check UPDATE packets SHOULD be calculated like this:
RTO = MAX (1000 ms, Ta * (Num-Waiting + Num-In-Progress))
In the RTO formula, Ta is the value used for connectivity check pacing, Num-Waiting is the number of pairs in the checklist in the "Waiting" state, and Num-In-Progress is the number of pairs in the "In-Progress" state. This matches the formula in [RFC8445] when there's only one checklist ๐งฎ. A value smaller than 1000 ms for the RTO MUST NOT be used. no speedrunning the timeout, bestie ๐ข
Each connectivity check request packet MUST contain a CANDIDATE_PRIORITY parameter (see Section 5.14). It carries the priority value that would be assigned to a peer-reflexive candidate if one was learned from the matching check ๐. An UPDATE packet that acknowledges a connectivity check request MUST be sent from the same address that received the check, and it MUST be delivered to the same address the check came from. Each acknowledgment UPDATE packet MUST contain a MAPPED_ADDRESS parameter with the port, protocol, and IP address of the address the connectivity check request came from ๐บ๏ธ.
Following the ICE guidelines [RFC8445], it is RECOMMENDED to limit the total number of connectivity checks to 100 for each host association ๐ฏ. You can do that by only checking the 100 candidate pairs with the highest priority. ngl, that's a clean way to keep things tidy ๐งน
4.6.3. Rules for Concluding Connectivity Checks ๐
The controlling agent might find more than one working candidate pair ๐ฏ. To conclude the connectivity checks, it SHOULD nominate the pair with the highest priority. The controlling agent MUST nominate a candidate pair by basically repeating a connectivity check, using an UPDATE message that contains a SEQ parameter (with a new sequence number), an ECHO_REQUEST_SIGNED parameter, the priority of the candidate in a CANDIDATE_PRIORITY parameter, and a NOMINATE parameter to signal that the checks are done ๐. Since the nominated address pair has already been tested for reachability, the controlled host should be able to receive the message. When it arrives, the controlled host SHOULD select the nominated address pair โ
.
The response MUST include a SEQ parameter with a new sequence identifier, an acknowledgment of the controlling host's sequence in an ACK parameter, a new ECHO_REQUEST_SIGNED parameter, an ECHO_RESPONSE_SIGNED parameter that matches the ECHO_REQUEST_SIGNED parameter from the controlling host, and the NOMINATE parameter ๐. After sending this packet, the controlled host can create IPsec security associations using the nominated address candidate to deliver application payload to the controlling host ๐.
Since the message from the controlled host included a new sequence identifier and echo request for the signature, the controlling host MUST acknowledge it with a new UPDATE message that includes ACK and ECHO_RESPONSE_SIGNED parameters ๐ค. After this final concluding message, the controlling host can also create IPsec security associations to deliver application payload to the controlled host ๐.
Packets can be delayed by the network, so both hosts MUST keep responding to any connectivity checks even after an address pair has been nominated ๐.
If all the connectivity checks have failed, the hosts MUST NOT send ESP traffic to each other ๐ซ. They MAY keep communicating using HIP packets and the locators used for the base exchange, though ๐ฌ. The hosts SHOULD also tell each other about the failure with a CONNECTIVITY_CHECKS_FAILED NOTIFY packet (see Section 5.10). it's giving "we tried, we failed, but we're still friends" ๐ฅฒ
4.7. NAT Traversal Optimizations โก
4.7.1. Minimal NAT Traversal Support ๐ฟ
If the Responder has a fixed, publicly reachable IPv4 address and does not employ a Control Relay Server, the explicit NAT traversal mode negotiation MAY be omitted ๐. That means even the UDP-ENCAPSULATION mode doesn't have to be negotiated. In that setup, the Initiator sends an I1 message over UDP, and the Responder replies with an R1 message over UDP without including any NAT traversal mode parameter. The rest of the base exchange follows the procedures in [RFC7401], except that the control and data planes use UDP encapsulation. Here, using UDP for NAT traversal is agreed upon implicitly ๐คซ. This way of operating is still subject to NAT timeouts, so the hosts MUST employ NAT keepalives as defined in Section 4.10 ๐.
When UDP-ENCAPSULATION mode is chosen, either explicitly or implicitly, the connectivity checks defined in this document MUST NOT be used ๐ โโ๏ธ. If the hosts lose connectivity, they MUST instead use the procedures in [RFC8046] or [RFC8047], with the difference that UDP-based tunneling MUST be employed for the entire lifetime of the corresponding HIP association ๐ค๏ธ.
4.7.2. Base Exchange without Connectivity Checks ๐
It's possible to run a base exchange without any connectivity checks, as defined in Legacy ICE-HIP (Section 4.8 of [RFC5770]). This procedure also applies in the context of this specification, so it's repeated here for completeness ๐.
In certain network environments, the connectivity checks can be skipped to cut down on initial connection setup latency, because the base exchange acts as an implicit connectivity test by itself โก. For this to work, the Initiator MUST be able to reach the Responder by simply UDP-encapsulating HIP and ESP packets sent to the Responder's address. Detecting and configuring this particular scenario is prone to failure unless it's carefully planned ๐ฌ.
In such a scenario, the Responder MAY include the UDP-ENCAPSULATION NAT traversal mode as one of its supported modes in the R1 packet ๐. If the Responder has registered with a Control Relay Server to discover its address candidates, it MUST also include a LOCATOR_SET parameter, encapsulated inside an ENCRYPTED parameter, in an R1 message. That parameter contains a preferred address where the Responder can receive UDP-encapsulated ESP and HIP packets. This locator MUST be of type "Transport address", its Traffic type MUST be "both", and it MUST have the "Preferred bit" set (see Table 2) ๐ง. If there's no such locator in R1, the Initiator MUST use the source address of the R1 as the Responder's preferred address ๐.
The Initiator MAY choose the UDP-ENCAPSULATION mode if the Responder listed it among its supported modes, and the Initiator doesn't want to use the connectivity checks defined in this document to look for a better path ๐ฃ๏ธ. In this case, the Initiator sends the I2 with UDP-ENCAPSULATION mode in the NAT traversal mode parameter directly to the Responder's preferred address (that is, to the preferred locator in R1, or to the address the R1 came from if there was no preferred locator in it) ๐ฌ. The Initiator MAY include locators in I2, but they MUST NOT be taken as address candidates, because the connectivity checks defined in this document won't be used for connections with UDP-ENCAPSULATION NAT traversal mode ๐ . Instead, if R2 and I2 are received and processed successfully, a security association can be created, and UDP-encapsulated ESP can be exchanged between the hosts once the base exchange completes, following the rules in Section 4.4 of [RFC7401] ๐โจ.
The Control Relay Server can be used to discover address candidates, but it isn't meant to relay end-host packets in the UDP-ENCAPSULATION NAT mode ๐ง. Since an I2 packet with UDP-ENCAPSULATION NAT traversal mode selected MUST NOT be sent via a Control Relay Server, the Responder SHOULD reject such I2 packets and reply with a NO_VALID_NAT_TRAVERSAL_MODE_PARAMETER NOTIFY packet (see Section 5.10) ๐
โโ๏ธ๐.
If there's no answer to the I2 packet sent directly to the Responder's preferred address, the Initiator MAY send another I2 via the Control Relay Server. However, it MUST NOT choose UDP-ENCAPSULATION NAT traversal mode for that I2 ๐ซถ.
4.7.3. Initiating a Base Exchange Both with and without UDP Encapsulation โจ
okay so it's possible to run a base exchange in parallel, both with and without UDP encapsulation ๐ฆ Legacy ICE-HIP (Section 4.9 of [RFC5770]) covers this too. This spec uses the same procedure, so we're repeating it here for completeness ๐
The Initiator MAY also try to simultaneously perform a base exchange with the Responder without UDP encapsulation. ๐ซถ In that case, the Initiator sends two I1 packets to the Responder, one without UDP encapsulation and one with it. The Initiator MAY wait for a while before sending the other I1. How long to wait and which I1 goes first can be decided based on local policy. For retransmissions, the same procedure is repeated ๐
The I1 packet without UDP encapsulation may arrive directly at the Responder, without passing a Control Relay Server. ๐ When that happens, the procedures in [RFC7401] are followed for the rest of the base exchange. The Initiator may receive multiple R1 packets from the Responder, with and without UDP encapsulation. However, after receiving a valid R1 and answering it with an I2, any further R1 packets that are not retransmissions of the first R1 received MUST be ignored. ๐ซ this is giving "one R1 is the main character, the rest are background extras" ๐
The I1 packet without UDP encapsulation may also arrive at a HIP-capable middlebox. ๐ง When that middlebox is a HIP Rendezvous Server and the Responder has successfully registered with the rendezvous service, the middlebox follows the rendezvous procedures in [RFC8004] ๐ธ
If the Initiator receives a NAT traversal mode parameter in R1 without UDP encapsulation, the Initiator MAY ignore this parameter. ๐ It can then send an I2 without UDP encapsulation and without any selected NAT traversal mode. When the Responder gets that I2, it will assume no NAT traversal mechanism is needed. Packet processing is then done as described in [RFC7401] โจ The Initiator MAY store the NAT traversal modes for future use, for example if a mobility or multihoming event causes NAT traversal to be needed during the lifetime of the HIP association. ๐
4.8. Sending Control Packets after the Base Exchange
the same considerations for sending control packets after the base exchange that are described in Legacy ICE-HIP (Section 5.10 of [RFC5770]) also apply here, so we're repeating them for completeness ๐
After the base exchange, the two end hosts MAY send HIP control packets directly to each other, using the transport address pair established for a data channel. No Control Relay Servers needed! ๐ฆ If a host doesn't get acknowledgments, for example to an UPDATE or CLOSE packet, and the timeout based on local policies has passed, the host SHOULD resend the packet through the peer's associated Data Relay Server. This only works if the peer listed that server in its LOCATOR_SET parameter during the base exchange, following the rules in Section 4.4.2 of [RFC7401] ๐
If a Control Relay Client sends a packet through a Control Relay Server, the Control Relay Client MUST always use the RELAY_TO parameter. ๐ซถ The Control Relay Server SHOULD forward HIP control packets from a Control Relay Client to the address given in the RELAY_TO parameter. In the other direction, the Control Relay Server SHOULD forward HIP control packets to the Control Relay Clients, and MUST add a RELAY_FROM parameter to the control packets it relays to them. โจ this is the whole "who sent this, and where should it go" handshake, and it's so iconic ๐
If the Control Relay Server is not willing or able to relay a HIP packet, it MAY notify the sender with a MESSAGE_NOT_RELAYED error notification (see Section 5.10). ๐ it's basically the server saying "not today, bestie" ๐
4.9. Mobility Handover Procedure โจ
okay so bestie, a host can totally move around after the base exchange and connectivity checks are done ๐ฆ HIP mobility extensions in [RFC8046] already cover handover without NATs ๐ this section is about how the two hosts handle handover when NATs are in the picture ๐ธ the extensions here only do simple mobility with a pair of security associations, and multihoming is left for later specs ๐ the procedures give you the same vibe as "ICE restart" from [RFC8445] ๐ฅ the example only shows a Control Relay Server for the peer, but the mobile host can have one too ๐ง
so the assumption is that both hosts already negotiated and picked ICE-HIP-UDP mode during the base exchange (see Section 4.3) ๐ the Initiator of the base exchange MUST store that it was the controlling host, and the Responder MUST store that it was the controlled host ๐
before starting handover with all peer hosts, the mobile host SHOULD first send its locators in UPDATE messages to its Control and Data Relay Servers if it's registered with them โจ it SHOULD wait for all of them to respond for a configurable time (default is two minutes) and then carry on with the handover without info from any Relay Server that didn't respond ๐ญ like we said in Section 4.1, a response from a Control Relay Server includes a REG_FROM parameter that describes the mobile host's server-reflexive candidate to use in the candidate exchange during handover ๐ซถ and an UPDATE to a Data Relay Server is necessary so it can forward data to the right IP address after handover ๐
the mobility extensions for NAT traversal are shown in Figure 6 ๐ฆ the mobile host is the one that changed its locators, and the peer host is the one it has a host association with ๐ the mobile host might have several peers and repeats this with each one ๐ in the figure, the Control Relay Server belongs to the peer, so the peer is a Control Relay Client for it ๐ this figure matches figure 3 in [RFC8046], but the big difference is that the main UPDATE procedure goes over the relay and the connectivity gets tested separately ๐ here's the step-by-step:
Mobile Host Control Relay Server Peer Host
| 1. UDP(UPDATE(ESP_INFO, | |
| ENC(LOC_SET), SEQ)) | |
+--------------------------------->| 2. UDP(UPDATE(ESP_INFO, |
| | ENC(LOC_SET), SEQ, |
| | RELAY_FROM)) |
| +------------------------------->|
| | |
| | 3. UDP(UPDATE(ESP_INFO, SEQ, |
| | ACK, ECHO_REQ_SIGN, |
| | RELAY_TO)) |
| 4. UDP(UPDATE(ESP_INFO, SEQ, |<-------------------------------+
| ACK, ECHO_REQ_SIGN, | |
| RELAY_TO)) | |
|<---------------------------------+ |
| | |
| 5. UDP(UPDATE(ACK, | |
| ECHO_RESP_SIGNED)) | |
+--------------------------------->| 6. UDP(UPDATE(ACK, |
| | ECHO_RESP_SIGNED, |
| | RELAY_FROM)) |
| +------------------------------->|
| | |
| 7. connectivity checks over UDP |
+<----------------------------------------------------------------->+
| | |
| 8. ESP data over UDP |
+<----------------------------------------------------------------->+
| | |
Figure 6: HIP UPDATE Procedure
step 1 is the mobile host saying "hey, I moved!" ๐ง it sends a location update to its peer through the peer's Control Relay Server ๐ฆ the UPDATE packet has the mobile host's own HIT as source and the peer's HIT as destination ๐ธ the source IP is the mobile host and the destination IP is the Control Relay Server ๐ the packet has an ESP_INFO parameter where, in this case, OLD SPI and NEW SPI both hold the pre-existing incoming SPI ๐ it also carries the mobile host's locators in a LOCATOR_SET parameter, wrapped inside an ENCRYPTED parameter (check Sections 5.2.18 and 6.5 in [RFC7401] for the ENCRYPTED parameter details) ๐ there's a SEQ number too, which the peer has to acknowledge ๐ and like [RFC8046] says, the packet might also include a HOST_ID (for middlebox inspection) and a DIFFIE_HELLMAN parameter for rekeying ๐ซถ
step 2 is the Control Relay Server getting the UPDATE and forwarding it to the peer (the peer is the Control Relay Client) โจ the server rewrites the destination IP address and tacks a RELAY_FROM parameter onto the message ๐
step 3 is the peer getting the UPDATE, processing it, and firing back another UPDATE ๐ฅ this one goes to the mobile host's HIT and the Control Relay Server's IP address ๐ it has an ESP_INFO parameter where OLD SPI and NEW SPI both hold the pre-existing incoming SPI ๐ฆ the peer adds a new SEQ and an ECHO_REQUEST_SIGNED parameter for the mobile host to acknowledge ๐ it acknowledges the earlier SEQ with an ACK parameter ๐ and the RELAY_TO parameter tells the Control Relay Server which address of the mobile host to forward to ๐
step 4 is the Control Relay Server getting that message, rewriting the destination IP address and UDP port based on RELAY_TO, and forwarding it to the mobile host ๐ง
step 5 is the mobile host receiving the UPDATE and processing it ๐ธ it wraps up the handover by acknowledging the SEQ with an ACK parameter and the ECHO_REQUEST_SIGNED with an ECHO_RESPONSE_SIGNED parameter ๐ the packet goes to the peer's HIT and the HIP relay's address ๐ the mobile host can start connectivity checks right after this packet โจ
step 6 is the HIP relay getting the UPDATE and forwarding it to the peer (the Relay Client) ๐ it rewrites the destination IP address and port, then appends a RELAY_FROM parameter ๐ฅ once the peer gets this final UPDATE, it can kick off the connectivity checks ๐
step 7 is the two hosts testing connectivity across NATs using the procedures in Section 4.6 ๐ฆ the original Initiator is the controlling host and the original Responder is the controlled host ๐
step 8 is when the connectivity checks finish successfully and the controlling host has nominated one address pair to use ๐ the hosts then set up security associations to deliver the application payload ๐
it's worth noting that Control and Data Relay Clients do not have to re-register for the related services after a handover ๐ซถ however, if a Data Relay Client has registered a relayed address candidate from a Data Relay Server, the Data Relay Client MUST reactivate that address before the connectivity checks by sending an UPDATE message with the PEER_PERMISSION parameter, as described in Section 4.12.1 ๐ญ otherwise, the Data Relay Server drops ESP packets sent to the relayed address ๐
now the "double jump" (aka simultaneous mobility) scenario ๐ both peers change location at the same time ๐ฅ in that case, both peers kick off the procedure above at the same moment ๐ง basically, both communicating hosts send an UPDATE carrying locators at the same time, or with some delay ๐ฆ when locators get exchanged almost simultaneously (reliably, via Control Relay Servers), the two hosts can carry on with connectivity checks once both have separately finished the steps in Figure 6 ๐ the tricky case is when one host (called host "M" here) moves later, during the connectivity checks ๐ฌ then host M sends a locator to the peer, who is in the middle of connectivity checks ๐ when the peer gets that UPDATE, it replies with an UPDATE with ECHO_REQ_SIGN, as in step 3 of Figure 6 โจ once the peer gets the valid response from host M as described in step 6, the peer MUST restart the connectivity checks with host M ๐ฅ that way, both hosts start connectivity checks roughly in sync ๐ซถ and it's really important that the peer does not restart connectivity checks until step 6 is successfully completed, because an attacker could replay the UPDATE message carrying locators from step 1 ๐ฑ๐
4.10. NAT Keepalives ๐ธ
okay so keepalives are how you stop NAT states from expiring ๐ communicating hosts MUST send periodic keepalives to other hosts they have a HIP association with, every 15 seconds (this is the so-called Tr value in ICE) ๐ฆ other values MAY be used, but a Tr value smaller than 15 seconds MUST NOT be used ๐ both a Control/Data Relay Client and Control/Data Relay Server, plus two peers using UDP-ENCAPSULATION or ICE-HIP-UDP mode, SHOULD send HIP NOTIFY packets unless they've already exchanged some other traffic over the UDP ports in use โจ the Data Relay Client and Data Relay Server, however, MUST employ only HIP NOTIFY packets to keep the server-reflexive candidates alive ๐ฅ the keepalive message encoding format is defined in Section 5.3 ๐ and if the base exchange or mobility handover procedure happens over an extremely slow path, a host (with a HIP association with the peer) MAY also send HIP NOTIFY packets every 15 seconds to keep the path active with the recipient ๐ง๐
4.11. Closing Procedure ๐
Okay bestie, closing a HIP association is a two-way handshake defined in [RFC7401] ๐ซถ. One host starts it by sending a CLOSE message, and the other host confirms with CLOSE_ACK โจ. Every packet is locked down with HMACs and signatures ๐, and the CLOSE messages carry an ECHO_REQUEST_SIGNED parameter so nobody can replay them at you ๐. Iconic, no cap.
Same procedure, same vibes, but this time the messages travel through the UDP-encapsulated tunnel the two hosts are already using ๐ฆ. The sender SHOULD try a direct link first. If it keeps retransmitting and nothing comes back, it MUST send through the recipient's Control Relay Server, but only if one exists ๐. A host that gets CLOSE directly, with no Control Relay Server involved, SHOULD answer directly. And if the CLOSE came via a Control Relay Server, the host SHOULD reply through that same Control Relay Server ๐.
4.12. Relaying Considerations ๐ธ
4.12.1. Forwarding Rules and Permissions ๐
The Data Relay Server runs a permission model that's basically TURN-server energy ๐ง. Before it forwards any ESP data packets from a peer to a Data Relay Client (or the other way around), the client MUST set a permission for the peer's address. The permissions also set up a forwarding rule for each direction, kinda like TURN's channels, and they're keyed on the Security Parameter Index (SPI) values in the ESP packets ๐.
Permissions aren't required for HIP control packets ๐
. BUT if a relayed address (the one conveyed in the RELAYED_ADDRESS parameter from the Data Relay Server) gets picked to carry data, the Control Relay Client MUST send an UPDATE message to the Data Relay Server. That UPDATE has a PEER_PERMISSION parameter (see Section 5.13) with the UDP port and address for the server-reflexive address, the UDP port and address of the peer, and the inbound and outbound SPIs used for ESP. The packet MUST be sent to the same UDP tunnel the Client used in the base exchange to reach the Server.
Not to the port the server-reflexive candidate is sitting on! ๐
To avoid dropping ESP packets, the Control Relay Client SHOULD send the PEER_PERMISSION parameter before connectivity checks, both for base exchange and for mobility handover. Worth noting: the UPDATE includes a SEQ parameter (as specified in [RFC7401]) that the Data Relay Server must acknowledge, so if the message gets lost, the Control Relay Client can resend it with the PEER_PERMISSION parameter ๐.
When a Data Relay Server receives an UPDATE with a PEER_PERMISSION parameter, it MUST check whether the sender is registered for data-relaying service, and drop the UPDATE if the host wasn't registered ๐ซ. If it was, the Data Relay Server looks for a permission with matching info (protocol, addresses, ports, and SPI values). No match? A new permission MUST be created, and its lifetime MUST be set to 5 minutes โฐ. If an identical permission already exists, it MUST be refreshed by setting the lifetime to 5 minutes. A Data Relay Client SHOULD refresh permissions 1 minute before they expire, as long as they're still needed ๐.
When a Data Relay Server gets an UPDATE from a registered client that has no PEER_PERMISSION parameter but does have a new locator set, the Data Relay Server can assume the mobile host has moved and isn't reachable at its previous location ๐โโ๏ธ. In that case, the Data Relay Server SHOULD deactivate the permission and stop relaying data plane traffic to the client.
The relayed address MUST be activated with the PEER_PERMISSION parameter both after a base exchange and after a handover procedure with another ICE-HIP-UDP-capable host. Until it's activated, the Data Relay Server MUST drop all ESP packets ๐. Also, a Data Relay Client doesn't have to renew its registration upon a change-of-location UPDATE. It only needs to do that when the registration lifetime is close to ending โณ.
4.12.2. HIP Data Relay and Relaying of Control Packets ๐ฌ
When a Data Relay Server agrees to relay UDP-encapsulated ESP between a Data Relay Client and its peer, it opens a UDP port (the relayed address) for that purpose, as described in Section 4.1 ๐. That same port can also deliver control packets, because connectivity checks cover the path through the Data Relay Server.
If the Data Relay Server receives a UDP-encapsulated HIP control packet on that port, it MUST forward the packet to the Data Relay Client and add a RELAY_FROM parameter, as if the Data Relay Server were acting as a Control Relay Server. When the Data Relay Client replies to a control packet with a RELAY_FROM parameter via its Data Relay Server, it MUST add a RELAY_TO parameter containing the peer's address, and use its Data Relay Server's address as the destination address. Further, the Data Relay Server MUST send this packet to the peer's address from the relayed address ๐.
If the Data Relay Server receives a UDP packet that isn't a HIP control packet, sent to the relayed address, it MUST check whether it has a permission set for the peer the packet is arriving from (in other words, the sender's address and SPI value match an installed permission) ๐ต๏ธ. If permissions are set, the Data Relay Server MUST forward the packet to the Data Relay Client that created the permission. The Data Relay Server MUST also implement similar checks for the reverse direction (that is, ESP packets from the Data Relay Client to the peer). Packets without a permission MUST be dropped silently ๐คซ.
4.12.3. Handling Conflicting SPI Values ๐งฉ
From a host's point of view, its remote peers can have overlapping inbound SPI numbers, because IPsec also uses the destination IP address to index the remote peer host. But a Data Relay Server can represent multiple remote peers, which masks the actual destination ๐ญ. A Data Relay Server might be juggling a whole crowd of Relay Clients and their peers, so it can run into collisions in the SPI namespace and end up unable to forward datagrams to the correct destination ๐ต. The SPI space is 32 bits and SPI values should be random, so a conflicting SPI is fairly unlikely, but it could happen on a busy Data Relay Server ๐ฒ. Two problematic cases are described in this section.
In the first scenario, the SPI collision happens when two hosts have registered with the same Data Relay Server and a third host initiates a base exchange with both of them ๐ฏ. The two Responders (that is, Data Relay Clients) claim the same inbound SPI number with the same Initiator (peer). Here's the plot twist: the Data Relay Server has given the two Data Relay Clients, now acting as Responders, separate UDP ports (as recommended in Section 7.5). When the third host sends an ESP packet, the Data Relay Server can forward it to the correct Data Relay Client, because the destination UDP port is different for each client โ .
In the second scenario, an SPI collision may occur when two Initiators run a base exchange to the same Responder (that is, Data Relay Client), and both Initiators claim the same inbound SPI at the Data Relay Server using the PEER_PERMISSION parameter ๐. The Data Relay Server can't disambiguate which destination an ESP packet from the Data Relay Client is meant for, since the SPI could belong to either peer. (The destination IP and UDP port belonging to the Data Relay Server aren't unique either.) The recommended way and a contingency plan to solve this are described below ๐.
The recommended way to mitigate the problem goes like this. For each new HIP association, a Data Relay Client acting as a Responder SHOULD register a new server-reflexive candidate, as described in Section 4.2. Similarly, the Data Relay Server SHOULD NOT reuse port numbers, as described in Section 7.5. That way, each server-reflexive candidate for the Data Relay Client has its own UDP port, which the Data Relay Server can use to tell packet destinations apart when SPIs collide ๐ช.
When the Data Relay Client isn't registering, or failed to register a new relay candidate for a new peer, it MUST follow a contingency plan. Upon receiving an I2 with a colliding SPI, the Data Relay Client acting as the Responder MUST NOT include the relayed address candidate in the R2 message, because the Data Relay Server wouldn't be able to demultiplex the related ESP packet to the correct Initiator ๐
โโ๏ธ. The same goes for handover procedures: the Data Relay Client MUST NOT include the relayed address candidate when sending its new locator set in an UPDATE to its peer if that would cause an SPI conflict with another peer ๐ฆ.
5. Packet Formats ๐ฆ
The following subsections define the parameter and packet encodings for the HIP and ESP packets. All values MUST be in network byte order ๐ง .
It's worth noting that all of the parameters are shown for completeness, even though they're already specified in Legacy ICE-HIP [RFC5770]. New parameters are explicitly described as new ๐.
5.1. HIP Control Packets ๐
Okay so, Figure 7 shows what a UDP-encapsulated HIP packet looks like. Bestie, it's literally the same as Legacy ICE-HIP [RFC5770], so if you already know that one, you're basically set ๐
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Length | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 32 bits of zeroes |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
~ HIP Header and Parameters ~
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 7: Format of UDP-Encapsulated HIP Control Packets
So HIP control packets get wrapped in UDP packets, following Section 2.2 of [RFC3948], "IKE Header Format for Port 4500" ๐ฆ The one difference is that a different port number gets used. After the UDP header come 32 zero bits, and those are what let you tell HIP control packets apart from ESP packets ๐ The HIP header and parameters follow the conventions of [RFC7401], with one twist: the HIP header checksum MUST be zero. Why? Two reasons, and they're both very valid. First, the UDP header already has a checksum. Second, the checksum definition in [RFC7401] includes the IP addresses in its calculation, and NATs that don't know about HIP can't recompute the HIP checksum after they change IP addresses. Not great, not great ๐
A Control/Data Relay Server or a non-relay Responder SHOULD listen at UDP port 10500 for incoming UDP-encapsulated HIP control packets. If some other port number is used, potential Initiators need to know about it ๐ง
Okay, now the MTU drama ๐ญ UDP encapsulation of HIP packets shrinks the Maximum Transmission Unit (MTU) size of the control plane by 12 bytes (8-byte UDP header plus 4-byte zero SPI marker), and the data plane by 8 bytes. Extra HIP relay parameters, like RELAY_HMAC, RELAY_UDP_HIP, RELAY_UDP_ESP, and so on, make certain HIP packets even bigger. So when it comes to MTU, here's what an implementation needs to think about:
- A HIP host SHOULD implement ICMP message handling to support Path MTU Discovery (PMTUD) as described in [RFC1191] and [RFC8201].
- Relying on IP fragmentation is unlikely to be a viable strategy through NATs. If ICMP MTU discovery isn't working, MTU-related path black holes may occur ๐
- One mitigation strategy is to constrain the MTU, especially for virtual interfaces, to expected safe MTU values, e.g., 1400 bytes for the underlying interfaces that support 1500 bytes MTU.
- Future extensions to this specification may define a HIP-based mechanism to find a working path MTU without unnecessarily constraining that size, using Packetization Layer Path MTU Discovery for Datagram Transports [RFC8899]. For instance, such a mechanism could be implemented between a HIP Relay Client and HIP Relay Server โจ
- It's worth noting that further HIP extensions can trim off 8 bytes in the ESP header by negotiating implicit initialization vector (IV) support in the ESP_TRANSFORM parameter, as described in [RFC8750] ๐ธ
5.2. Connectivity Checks
Connectivity checks in HIP are just HIP UPDATE packets! ๐ Their format is specified in [RFC7401], so no need to reinvent anything.
5.3. Keepalives
Here's the vibe for keepalives. The RECOMMENDED encoding format is HIP NOTIFY packets, as specified in [RFC7401], with the Notify message type field set to NAT_KEEPALIVE (16385) and an empty Notification data field ๐ It's worth noting that sending such a HIP NOTIFY message SHOULD be omitted if the host is already sending some other traffic (HIP or ESP) to the peer host over the related UDP tunnel during the Tr period. Like, if you're already chatting, you don't need to send a keepalive on top ๐ For instance, the host MAY actively send ICMPv6 requests (or respond with an ICMPv6 response) inside the ESP tunnel to test the health of the associated IPsec security association. Alternatively, the host MAY use UPDATE packets as a substitute. A minimal UPDATE packet would consist of a SEQ and a single ECHO_REQ_SIGN parameter, and a more complex one would involve rekeying procedures as specified in Section 6.8 of [RFC7402] ๐ฅ One last heads-up: a host that's actively sending periodic UPDATE packets to a busy server may increase the computational load of that server, since it has to verify HMACs and signatures in UPDATE messages. Be considerate, bestie ๐ซถ
5.4. NAT Traversal Mode Parameter
The format of the NAT traversal mode parameter is defined in Legacy ICE-HIP [RFC5770], but it's repeated here so everything's in one place ๐ง The NAT_TRAVERSAL_MODE parameter looks a lot like the ESP_TRANSFORM parameter in [RFC7402], and you can see it in Figure 8. The Native ICE-HIP extension in this document defines a brand-new NAT traversal mode identifier for ICE-HIP-UDP, and it reuses the UDP-ENCAPSULATION mode from Legacy ICE-HIP [RFC5770]. The identifier named RESERVED is reserved for future use. Future specifications may define more traversal modes.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved | Mode ID #1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Mode ID #2 | Mode ID #3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Mode ID #n | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 8: Format of the NAT_TRAVERSAL_MODE Parameter
Here's what each field does:
Type: 608Length: Length in octets, excluding Type, Length, and PaddingReserved: Zero when sent, ignored when receivedMode ID: Defines the proposed or selected NAT traversal mode(s)
And here are the NAT traversal mode IDs that are defined:
+===================+=======+
| ID name | Value |
+===================+=======+
| RESERVED | 0 |
+-------------------+-------+
| UDP-ENCAPSULATION | 1 |
+-------------------+-------+
| ICE-STUN-UDP | 2 |
+-------------------+-------+
| ICE-HIP-UDP | 3 |
+-------------------+-------+
Table 1: NAT Traversal
Mode IDs
Now the rules, and these ones are strict ๐ โโ๏ธ The sender of a NAT_TRAVERSAL_MODE parameter MUST make sure there are no more than six (6) Mode IDs in one NAT_TRAVERSAL_MODE parameter. The receiving side MUST be prepared to handle received NAT traversal mode parameters that contain more than six Mode IDs, by accepting the first six Mode IDs and dropping the rest. The limited number of Mode IDs sets the maximum size of the NAT_TRAVERSAL_MODE parameter, so it's all capped out nicely โจ The modes MUST be in preference order, with the most preferred mode(s) first.
Implementations conforming to this specification MUST implement UDP-ENCAPSULATION and SHOULD implement ICE-HIP-UDP modes. Non-negotiable for UDP-ENCAPSULATION, very strongly suggested for ICE-HIP-UDP ๐
5.5. Connectivity Check Transaction Pacing Parameter
The TRANSACTION_PACING parameter is defined in [RFC5770], but it's shown again in Figure 9 for completeness ๐ It only contains the connectivity check pacing value, written in milliseconds as a 32-bit unsigned integer.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Min Ta |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 9: Format of the TRANSACTION_PACING Parameter
Type: 610Length: 4Min Ta: The minimum connectivity check transaction pacing value the host would use (in milliseconds)
5.6. Relay and Registration Parameters
Okay, this one's the family reunion ๐ The REG_FROM, RELAY_FROM, and RELAY_TO parameters all share the same format, as you can see in Figure 10. The only difference between them is the type. Of the three, only REG_FROM is covered by the signature ๐
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Port | Protocol | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Address |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 10: Format of the REG_FROM, RELAY_FROM, and RELAY_TO
Parameters
Here's the breakdown of each field:
Type:- REG_FROM: 950
- RELAY_FROM: 63998
- RELAY_TO: 64002
Length: 20Port: Transport port number; zero when plain IP is usedProtocol: IANA-assigned, Internet Protocol number. 17 for UDP; 0 for plain IPReserved: Reserved for future use; zero when sent, ignored when receivedAddress: An IPv6 address or an IPv4 address in "IPv4-mapped IPv6 address" format
REG_FROM holds the transport address and protocol from which the Control Relay Server sees the registration coming. RELAY_FROM holds the address from which the relayed packet was received by the Control Relay Server, plus the protocol that was used. RELAY_TO holds the same information about the address a packet should be forwarded to ๐ฆ
5.7. LOCATOR_SET Parameter โจ
okay so this one is the address candidate parameter, and it's giving organized ๐ It reuses the UDP-based locator format from Legacy ICE-HIP [RFC5770] so hosts can share their address candidates with each other. The generic and NAT-traversal-specific locator parameters are drawn out in Figure 11, bestie ๐ฆ
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Traffic Type | Locator Type | Locator Length| Reserved |P|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Locator Lifetime |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Locator |
| |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
. .
. .
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Traffic Type | Loc Type = 2 | Locator Length| Reserved |P|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Locator Lifetime |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Transport Port | Transp. Proto| Kind |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Priority |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| SPI |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Address |
| |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 11: LOCATOR_SET Parameter
Table 2 breaks down every field ๐
+===========+==========+=========================================+
| Field | Value(s) | Purpose |
+===========+==========+=========================================+
| Type | 193 | Parameter type |
+-----------+----------+-----------------------------------------+
| Length | Variable | Length in octets, excluding Type and |
| | | Length fields and padding |
+-----------+----------+-----------------------------------------+
| Traffic | 0-2 | The locator for either HIP signaling |
| Type | | (1) or ESP (2), or for both (0) |
+-----------+----------+-----------------------------------------+
| Locator | 2 | "Transport address" locator type |
| Type | | |
+-----------+----------+-----------------------------------------+
| Locator | 7 | Length of the fields after Locator |
| Length | | Lifetime in 4-octet units |
+-----------+----------+-----------------------------------------+
| Reserved | 0 | Reserved for future extensions |
+-----------+----------+-----------------------------------------+
| Preferred | 0 or 1 | Set to 1 for a Locator in R1 if the |
| (P) bit | | Responder can use it for the rest of |
| | | the base exchange, otherwise set to |
| | | zero |
+-----------+----------+-----------------------------------------+
| Locator | Variable | Locator lifetime in seconds, see |
| Lifetime | | Section 4 of [RFC8046] |
+-----------+----------+-----------------------------------------+
| Transport | Variable | Transport-layer port number |
| Port | | |
+-----------+----------+-----------------------------------------+
| Transport | Variable | IANA-assigned, transport-layer Internet |
| Protocol | | Protocol number. Currently, only UDP |
| | | (17) is supported. |
+-----------+----------+-----------------------------------------+
| Kind | Variable | 0 for host, 1 for server reflexive, 2 |
| | | for peer reflexive (currently unused), |
| | | or 3 for relayed address |
+-----------+----------+-----------------------------------------+
| Priority | Variable | Locator's priority as described in |
| | | [RFC8445]. It is worth noting that |
| | | while the priority of a single locator |
| | | candidate is 32 bits, an implementation |
| | | should a 64-bit integer to calculate |
| | | the priority of a candidate pair for |
| | | the ICE priority algorithm. |
+-----------+----------+-----------------------------------------+
| SPI | Variable | Security Parameter Index (SPI) value |
| | | that the host expects to see in |
| | | incoming ESP packets that use this |
| | | locator |
+-----------+----------+-----------------------------------------+
| Address | Variable | IPv6 address or an "IPv4-mapped IPv6 |
| | | address" format IPv4 address [RFC4291] |
+-----------+----------+-----------------------------------------+
Table 2: Fields of the LOCATOR_SET Parameter
The LOCATOR parameter MUST be encapsulated inside an ENCRYPTED parameter. ๐ฅ That's a hard rule, no notes!
5.8. RELAY_HMAC Parameter ๐
okay so as Legacy ICE-HIP [RFC5770] says, the RELAY_HMAC parameter value has TLV type 65520. It has the same semantics as RVS_HMAC from Section 4.2.1 of [RFC8004] ๐ธ Similar to RVS_HMAC, RELAY_HMAC is also keyed with the HIP integrity key (HIP-lg or HIP-gl, as in Section 6.5 of [RFC7401]), which gets established during the relay registration procedure described in Section 4.1. Main character energy โจ
5.9. Registration Types ๐ฆ
The REG_INFO, REG_REQ, REG_RESP, and REG_FAILED parameters carry Registration Type [RFC8003] values for Control Relay Server registration. RELAY_UDP_HIP is 2 as set out in Legacy ICE-HIP [RFC5770], and RELAY_UDP_ESP is 3. ๐
5.10. Notify Packet Types ๐
A Control/Data Relay Server and end hosts can use NOTIFY packets to signal different error conditions. The NOTIFY packet types match Legacy ICE-HIP [RFC5770] except for the last two, which are new, lowkey iconic ๐
The Notify Packet Types [RFC7401] are shown below. The Notification Data field for the error notifications SHOULD contain the HIP header of the rejected packet, and SHOULD be empty for the CONNECTIVITY_CHECKS_FAILED type. ๐ซถ
+=====================================================+=======+
| NOTIFICATION PARAMETER - ERROR TYPES | Value |
+=====================================================+=======+
| NO_VALID_NAT_TRAVERSAL_MODE_PARAMETER | 60 |
| | |
| If a Control Relay Server does not forward a base | |
| exchange packet due to a missing NAT traversal mode | |
| parameter, or the Initiator selects a NAT traversal | |
| mode that the (non-relay) Responder did not expect, | |
| the Control Relay Server or the Responder may send | |
| back a NOTIFY error packet with this type. | |
+-----------------------------------------------------+-------+
| CONNECTIVITY_CHECKS_FAILED | 61 |
| | |
| Used by the end hosts to signal that NAT traversal | |
| connectivity checks failed and did not produce a | |
| working path. | |
+-----------------------------------------------------+-------+
| MESSAGE_NOT_RELAYED | 62 |
| | |
| Used by a Control Relay Server to signal that it | |
| was not able or willing to relay a HIP packet. | |
+-----------------------------------------------------+-------+
| SERVER_REFLEXIVE_CANDIDATE_ALLOCATION_FAILED | 63 |
| | |
| Used by a Data Relay Server to signal that it was | |
| not able or willing to allocate a new server- | |
| reflexive candidate for the Data Relay Client. | |
+-----------------------------------------------------+-------+
| RVS_HMAC_PROHIBITED_WITH_RELAY | 64 |
| | |
| In the unintended event that a Control Relay Server | |
| sends any HIP message with an RVS_HMAC parameter, | |
| the Control Relay Client drops the received HIP | |
| message and sends a notify message back to the | |
| Control Relay Server using this notify type. | |
+-----------------------------------------------------+-------+
Table 3: Notify Packet Types
5.11. ESP Data Packets ๐ง
okay the format for ESP data packets is identical to Legacy ICE-HIP [RFC5770], so no new drama there ๐
[RFC3948] describes UDP encapsulation of the IPsec ESP transport and tunnel modes. On the wire, HIP ESP packets don't differ from transport mode ESP, so their encapsulation is the same as UDP-encapsulated transport mode ESP. The (semantic) difference from the Bound End-to-End Tunnel (BEET) mode ESP packets HIP uses is that the IP header is not used in the BEET integrity protection calculation. ๐คโจ
During the HIP base exchange, the two peers exchange parameters that let them define a pair of IPsec ESP security associations (SAs), as described in [RFC7402]. When two peers perform a UDP-encapsulated base exchange, they MUST define a pair of IPsec SAs that produces UDP-encapsulated ESP data traffic. Non-negotiable, bestie ๐
The management of encryption/authentication protocols and SPIs is defined in [RFC7402]. The UDP encapsulation format and processing of HIP ESP traffic is described in Section 6.1 of [RFC7402]. ๐ฆ
5.12. RELAYED_ADDRESS and MAPPED_ADDRESS Parameters
okay so the format of the RELAYED_ADDRESS and MAPPED_ADDRESS parameters is identical to REG_FROM, RELAY_FROM, and RELAY_TO ๐ same vibes, different names, no cap. these new type values are the only real difference. ๐ This spec only covers UDP relaying, so only protocol 17 is allowed for now. future docs might add other protocols though, so stay tuned ๐
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Port | Protocol | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| Address |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 12: Format of the RELAYED_ADDRESS and MAPPED_ADDRESS Parameters
- Type:
RELAYED_ADDRESSis4650, andMAPPED_ADDRESSis4660๐ฆ - Length:
20๐ - Port: the UDP port number ๐
- Protocol: an IANA-assigned Internet Protocol number (
17for UDP) ๐ - Reserved: reserved for future use, so zero when sent and ignored when received ๐ซถ
- Address: an IPv6 address, or an IPv4 address in "IPv4-mapped IPv6 address" format โจ
5.13. PEER_PERMISSION Parameter
the new PEER_PERMISSION parameter is the one that sets up and refreshes forwarding rules, plus the permissions for data packets at the Data Relay Server ๐ it holds one or more sets of Port, Protocol, Address, Outbound SPI (OSPI), and Inbound SPI (ISPI) values, and each set defines a rule for one peer address ๐ธ very organised, very iconic.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| RPort | PPort |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Protocol | Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| RAddress |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
| PAddress |
| |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| OSPI |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ISPI |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 13: Format of the PEER_PERMISSION Parameter
- Type:
4680๐ฏ - Length:
48๐ - RPort: the transport-layer (UDP) port at the Data Relay Server (i.e., the port of the server-reflexive candidate) ๐ช
- PPort: the transport-layer (UDP) port number of the peer ๐ฏ
- Protocol: an IANA-assigned Internet Protocol number (
17for UDP) ๐ - Reserved: reserved for future use, so zero when sent and ignored when received ๐ซถ
- RAddress: an IPv6 address, or an IPv4 address in "IPv4-mapped IPv6 address" format, of the server-reflexive candidate ๐
- PAddress: an IPv6 address, or an IPv4 address in "IPv4-mapped IPv6 address" format, of the peer ๐ง
- OSPI: the outbound SPI value the Data Relay Client is using for the peer ๐
- ISPI: the inbound SPI value the Data Relay Client is using for the peer ๐
5.14. HIP Connectivity Check Packets
okay the connectivity requests are HIP UPDATE packets that carry a brand new CANDIDATE_PRIORITY parameter ๐ and the response UPDATE packets carry a MAPPED_ADDRESS parameter (the same one from Figure 12, bestie, we already met her ๐).
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Priority |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 14: Format of the CANDIDATE_PRIORITY Parameter
- Type:
4700โญ - Length:
4๐ - Priority: the priority of a (potential) peer-reflexive candidate ๐
5.15. NOMINATE Parameter
figure 15 is the NOMINATE parameter ๐ it's the one that wraps up the candidate nomination process, so it's kind of the big finale ๐
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Reserved |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 15: Format of the NOMINATE Parameter
- Type:
4710๐ - Length:
4๐ - Reserved: reserved for future extension purposes ๐ฑ
6. IAB Considerations
so the ICE spec [RFC8445] talks about "Unilateral Self-Address Fixing" in Section 18 ๐ง this protocol is based on ICE, so those same considerations apply here too, no cap ๐ซถ
7. Security Considerations
okay bestie, this part is serious ๐ญ๐ฅ the control plane protocol and Control Relay Server are basically the same as in Legacy ICE-HIP [RFC5770] (with a few minor differences). so the same security considerations from Sections 7.1, 7.2, 7.3, and 7.4 still apply, and they're repeated here for completeness ๐ new stuff is in Section 7.5 for the new Data Relay Server, and the new connectivity check protocol gets covered in Sections 7.6 and 7.7 ๐ฆ
7.1. Privacy Considerations
end users might not want to reveal every locator to each other ๐ for example, if a multihoming end host reveals all of its locators to its peer during a base exchange, tracking its physical location gets way easier ๐ and revealing host addresses also exposes info about the local topology, which some corporate environments don't allow ๐ข so for these two local policy reasons, it might seem tempting to leave certain host addresses out of an end host's LOCATOR_SET parameter, but this is NOT RECOMMENDED โ
why? because it creates non-optimal paths when the hosts sit behind the same NAT ๐ this could be a real problem with a legacy NAT that doesn't support routing from the private address realm back to itself through the outer address of the NAT. that's called the hairpin problem [RFC5128] ๐ฅจ with a legacy NAT like that, the only option left is a relayed transport address from a Data Relay Server ๐
also, Control and Data Relay Servers can be useful for privacy. for example, a privacy-concerned Responder might only reveal its Control Relay Server and Relayed candidates to Initiators ๐ต๏ธโโ๏ธ this partially protects the Responder against Denial-of-Service (DoS) attacks, because it can still start new connections even if its relays become unavailable from a DoS attack ๐ก๏ธ
7.2. Opportunistic Mode
in opportunistic HIP mode (cf. Section 4.1.8 of [RFC7401]), an Initiator sends an I1 without setting the destination HIT of the Responder (i.e., the Control Relay Client) ๐ซง a Control Relay Server SHOULD have a unique IP address per Control Relay Client when it's serving more than one Control Relay Client and supports opportunistic mode ๐ otherwise, the Control Relay Server can't guarantee it'll deliver the I1 packet to the intended recipient ๐ญ
future extensions might let opportunistic mode work with non-unique IP addresses, which could be used as a HIP-level anycast or multicast mechanism ๐ both of those cases would need separate registration parameters that the Control Relay Server proposes and the Control Client Server accepts during registration ๐ค
7.3. Base Exchange Replay Protection for Control Relay Server
so in some scenarios an attacker (or two attackers) can replay an earlier base exchange through a Control Relay Server by pretending to be the original Initiator and Responder ๐ฑ the attack doesn't need the attacker(s) to compromise the private key(s) of the attacked host(s) ๐ but for it to work, the legitimate Responder has to be disconnected from the Control Relay Server ๐ด
the Control Relay Server can protect itself by getting involved in the base exchange, introducing nonces that the end hosts (Initiator and Responder) are required to sign โ๏ธ one way to do this is to add ECHO_REQUEST_M parameters to the R1 and I2 packets, as described in [HIP-MIDDLEBOXES], and then drop the I2 or R2 packets if the matching ECHO_RESPONSE_M parameters aren't there ๐ก๏ธ
7.4. Demultiplexing Different HIP Associations
Section 5.1 of [RFC3948] describes a security issue for UDP encapsulation in standard IP tunnel mode ๐ it happens when two hosts behind different NATs have the same private IP address and start talking to the same Responder on the public Internet ๐ตโ๐ซ the Responder can't tell the two hosts apart, because the security associations are based on the same inner IP addresses ๐ฅด
good news though: this doesn't happen with the UDP encapsulation of the HIP ESP transport format, because the Responder uses HITs to tell different Initiators apart ๐โจ
7.5. Reuse of Ports at the Data Relay Server
if the Data Relay Server uses the same relayed address and port (as conveyed in the RELAYED_ADDRESS parameter) for multiple Data Relay Clients, then to all the peers and their firewalls, it looks like every Data Relay Client is at the same address ๐ so a stateful firewall might let packets through from hosts that normally wouldn't be able to send packets to a peer behind that firewall ๐จ
so a Data Relay Server SHOULD NOT reuse port numbers ๐ซ if it does need to reuse them, it SHOULD have a sufficiently large pool of port numbers and randomly pick ports from that pool, which lowers the chances of a Data Relay Client getting the same address as another host behind the same firewall ๐ฒ๐ฆ
7.6. Amplification Attacks ๐ฅ
okay bestie, so a sneaky host could send its peer a totally bogus list of candidates ๐ค and then use them to aim a flood of connectivity checks at some poor victim ๐ญ to stop that, this protocol borrows the ICE mechanism, which caps the total number of connectivity checks, as defined in Section 4.7 ๐ก๏ธ no cap, it's a cute little safety net ๐ง
7.7. Attacks against Connectivity Checks and Candidate Gathering ๐
Section 19.2 of [RFC8445] covers attacks on ICE connectivity checks ๐ HIP builds its control plane security on Diffie-Hellman key exchange, public keys, and Hashed Message Authentication codes ๐ so the security concerns in that section don't apply to HIP either, periodt ๐ that section also talks about man-in-the-middle replay attacks, which are hard to stop ๐ฉ but the connectivity checks in this protocol are effectively immune to replay attacks ๐ because a connectivity request carries a random nonce that the recipient has to sign and send back in its response โจ
Section 19.3 of [RFC8445] describes attacks on server-reflexive address gathering ๐ same deal here: if the DNS, a Control Relay Server, or a Data Relay Server has been compromised, there isn't much anyone can do ๐ but the scenario where attackers inject fake messages from a shared network segment, like Wi-Fi, doesn't apply here ๐ฆ HIP messages are integrity and replay protected, so you can't inject fake server-reflexive address candidates ๐
Section 19.4 of [RFC8445] describes attacks on relayed candidate gathering ๐ similar to ICE TURN servers, a Data Relay Server requires an authenticated base exchange, which protects relayed address gathering against fake requests and responses ๐ซถ and replay attacks aren't possible either, because the HIP base exchange (and the UPDATE procedure too) is protected against replay attacks ๐ฅ
7.8. Cross-Protocol Attacks ๐
Section 4.1 explains how a Control Relay Client registers for the RELAY_UDP_HIP service from a Control Relay Server ๐ but the same server may also offer Rendezvous functionality, so a client can register for both a RELAY_UDP_HIP and a RENDEZVOUS (see [RFC8004]) service from the same server ๐ง this could open up a cross-protocol attack (or really, a "cross-message" attack), because the key material is the same for the Control Relay Service and Rendezvous HMACs ๐ณ deriving different keys for the Control Relay Service would fix it, but a simpler measure was picked because the exact attack scenario wasn't clear ๐คทโโ๏ธ so this section defines a mandatory mitigation that stops Rendezvous and Control Relay Service from being used at the same time within a single HIP Association ๐
The registration involves three parameters, typically delivered in order in R1 (REG_INFO parameter), I2 (REG_REQUEST), and R2 (REG_RESPONSE) messages ๐ฌ they can also be delivered in UPDATE messages, as described in [RFC8003] ๐ here's how each one gets its glow-up:
REG_INFO: The Control Relay Server advertises its available services with this parameter ๐ฃ RELAY_UDP_HIP and RENDEZVOUS services MAY be included in the first advertisement for the HIP association, but later ones MUST include only one of them, the one agreed in earlier registrations (see steps 2 and 3) ๐REG_REQUEST: The Control Relay Client picks the services it needs with this parameter ๐๏ธ if the Control Relay Server offered both RENDEZVOUS and RELAY_UDP_HIP, the Control Relay Client MUST choose only one of them in the REG_REQUEST parameter ๐ โโ๏ธ once it has picked one, that choice sticks for the whole lifetime of the HIP association, and the Control Relay Client MUST NOT register the other one in a later UPDATE message ๐REG_RESPONSE: The Control Relay Server checks the services the Control Relay Client asked for using this parameter ๐ if the Control Relay Server offered both RENDEZVOUS and RELAY_UDP_HIP service, and the Control Relay Client requested both of them, the Control Relay Client MUST offer only RELAY_UDP_HIP service in the REG_RESPONSE parameter, and include aREG_FAILEDparameter in the same message, with RENDEZVOUS as the Registration Type and 9 as the Failure Type ๐
As an extra measure against cross-protocol attacks ๐ก๏ธ the Control Relay Client MUST drop any HIP message that includes an RVS_HMAC parameter when it comes from a successfully registered Control Relay Server ๐ซ if that (unintended) event happens, the Control Relay Client MUST send a NOTIFY message with RVS_HMAC_PROHIBITED_WITH_RELAY as the Notify Message Type to the Control Relay Server ๐ฎ
8. IANA Considerations ๐๏ธ
This section is to be interpreted according to [RFC8126] ๐ง
This document reuses the same default UDP port number 10500 as specified by Legacy ICE-HIP [RFC5770] for tunneling both HIP control and data plane traffic ๐ the port was registered separately for [RFC5770] to coauthor Ari Kerรคnen originally, but it has been reassigned for IESG control ๐ with Ari Kerรคnen's permission, the new assignee is the IESG and the contact is <chair@ietf.org> ๐ IANA has also added a reference to this document in the entry for UDP port 10500 in the "Service Name and Transport Protocol Port Number Registry" ๐ the selection between Legacy ICE-HIP and Native ICE-HIP mode is negotiated using the NAT_TRAVERSAL_MODE parameter during the base exchange ๐ค by default, hosts listen on this port for incoming UDP datagrams and can also use it to send UDP datagrams ๐ค other ephemeral port numbers are negotiated and used dynamically ๐ฆ
IANA has assigned the following values in the HIP "Parameter Types" registry [RFC7401] ๐
4650 for RELAYED_ADDRESS (length 20)
4660 for MAPPED_ADDRESS (length 20; defined in Section 5.12)
4680 for PEER_PERMISSION (length 48; defined in Section 5.13)
4700 for CANDIDATE_PRIORITY (length 4; defined in Section 5.14)
4710 for NOMINATE (length 4; defined in Section 5.15)
IANA has assigned the following value in the "HIP NAT Traversal Modes" registry specified in Legacy ICE-HIP [RFC5770] ๐ธ
3 for ICE-HIP-UDP (defined in Section 5.4)
IANA has assigned the following values in the HIP "Notify Message Types" registry ๐
16385 for NAT_KEEPALIVE in Section 5.3
63 for SERVER_REFLEXIVE_CANDIDATE_ALLOCATION_FAILED in Section 5.10
64 for RVS_HMAC_PROHIBITED_WITH_RELAY in Section 5.10
IANA has assigned the following values in the "Registration Types" registry for the HIP Registration Extension [RFC8003] ๐ง
3 for RELAY_UDP_ESP (defined in Section 5.9) for allowing registration
with a Data Relay Server for ESP-relaying service
4 for CANDIDATE_DISCOVERY (defined in Section 4.2) for performing
server-reflexive candidate discovery
IANA has assigned one value in the "Registration Failure Types" registry as defined in Section 7.8 ๐ the value is 9, and the Registration Failure Type is "Simultaneous Rendezvous and Control Relay Service usage prohibited" ๐ซ
9. References ๐
9.1. Normative References ๐
[RFC1191] Mogul, J. and S. Deering, "Path MTU discovery", RFC 1191,
DOI 10.17487/RFC1191, November 1990,
<https://www.rfc-editor.org/info/rfc1191>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[RFC4291] Hinden, R. and S. Deering, "IP Version 6 Addressing
Architecture", RFC 4291, DOI 10.17487/RFC4291, February
2006, <https://www.rfc-editor.org/info/rfc4291>.
[RFC5770] Komu, M., Henderson, T., Tschofenig, H., Melen, J., and A.
Keranen, Ed., "Basic Host Identity Protocol (HIP)
Extensions for Traversal of Network Address Translators",
RFC 5770, DOI 10.17487/RFC5770, April 2010,
<https://www.rfc-editor.org/info/rfc5770>.
[RFC7050] Savolainen, T., Korhonen, J., and D. Wing, "Discovery of
the IPv6 Prefix Used for IPv6 Address Synthesis",
RFC 7050, DOI 10.17487/RFC7050, November 2013,
<https://www.rfc-editor.org/info/rfc7050>.
[RFC7401] Moskowitz, R., Ed., Heer, T., Jokela, P., and T.
Henderson, "Host Identity Protocol Version 2 (HIPv2)",
RFC 7401, DOI 10.17487/RFC7401, April 2015,
<https://www.rfc-editor.org/info/rfc7401>.
[RFC7402] Jokela, P., Moskowitz, R., and J. Melen, "Using the
Encapsulating Security Payload (ESP) Transport Format with
the Host Identity Protocol (HIP)", RFC 7402,
DOI 10.17487/RFC7402, April 2015,
<https://www.rfc-editor.org/info/rfc7402>.
[RFC8003] Laganier, J. and L. Eggert, "Host Identity Protocol (HIP)
Registration Extension", RFC 8003, DOI 10.17487/RFC8003,
October 2016, <https://www.rfc-editor.org/info/rfc8003>.
[RFC8004] Laganier, J. and L. Eggert, "Host Identity Protocol (HIP)
Rendezvous Extension", RFC 8004, DOI 10.17487/RFC8004,
October 2016, <https://www.rfc-editor.org/info/rfc8004>.
[RFC8005] Laganier, J., "Host Identity Protocol (HIP) Domain Name
System (DNS) Extension", RFC 8005, DOI 10.17487/RFC8005,
October 2016, <https://www.rfc-editor.org/info/rfc8005>.
[RFC8046] Henderson, T., Ed., Vogt, C., and J. Arkko, "Host Mobility
with the Host Identity Protocol", RFC 8046,
DOI 10.17487/RFC8046, February 2017,
<https://www.rfc-editor.org/info/rfc8046>.
[RFC8047] Henderson, T., Ed., Vogt, C., and J. Arkko, "Host
Multihoming with the Host Identity Protocol", RFC 8047,
DOI 10.17487/RFC8047, February 2017,
<https://www.rfc-editor.org/info/rfc8047>.
[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
Writing an IANA Considerations Section in RFCs", BCP 26,
RFC 8126, DOI 10.17487/RFC8126, June 2017,
<https://www.rfc-editor.org/info/rfc8126>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[RFC8201] McCann, J., Deering, S., Mogul, J., and R. Hinden, Ed.,
"Path MTU Discovery for IP version 6", STD 87, RFC 8201,
DOI 10.17487/RFC8201, July 2017,
<https://www.rfc-editor.org/info/rfc8201>.
[RFC8445] Keranen, A., Holmberg, C., and J. Rosenberg, "Interactive
Connectivity Establishment (ICE): A Protocol for Network
Address Translator (NAT) Traversal", RFC 8445,
DOI 10.17487/RFC8445, July 2018,
<https://www.rfc-editor.org/info/rfc8445>.
[RFC8489] Petit-Huguenin, M., Salgueiro, G., Rosenberg, J., Wing,
D., Mahy, R., and P. Matthews, "Session Traversal
Utilities for NAT (STUN)", RFC 8489, DOI 10.17487/RFC8489,
February 2020, <https://www.rfc-editor.org/info/rfc8489>.
[RFC8961] Allman, M., "Requirements for Time-Based Loss Detection",
BCP 233, RFC 8961, DOI 10.17487/RFC8961, November 2020,
<https://www.rfc-editor.org/info/rfc8961>.
9.2. Informative References โจ
Okay bestie, these are the informative references ๐ They're not strictly required reading, but they're great for backstory on the wider NAT and HIP drama ๐ฆ
- [HIP-MIDDLEBOXES] Heer, T., Hummen, R., Wehrle, K., and M. Komu, "End-Host Authentication for HIP Middleboxes", Work in Progress, Internet-Draft, draft-heer-hip-middle-auth-04, 31 October 2011,
https://datatracker.ietf.org/doc/html/draft-heer-hip-middle-auth-04. - [ICE-NONSIP] Rosenberg, J., "Guidelines for Usage of Interactive Connectivity Establishment (ICE) by non Session Initiation Protocol (SIP) Protocols", Work in Progress, Internet-Draft, draft-rosenberg-mmusic-ice-nonsip-01, 14 July 2008,
https://datatracker.ietf.org/doc/html/draft-rosenberg-mmusic-ice-nonsip-01. - [RFC2475] Blake, S., Black, D., Carlson, M., Davies, E., Wang, Z., and W. Weiss, "An Architecture for Differentiated Services", RFC 2475, DOI 10.17487/RFC2475, December 1998,
https://www.rfc-editor.org/info/rfc2475. - [RFC3264] Rosenberg, J. and H. Schulzrinne, "An Offer/Answer Model with Session Description Protocol (SDP)", RFC 3264, DOI 10.17487/RFC3264, June 2002,
https://www.rfc-editor.org/info/rfc3264. - [RFC3948] Huttunen, A., Swander, B., Volpe, V., DiBurro, L., and M. Stenberg, "UDP Encapsulation of IPsec ESP Packets", RFC 3948, DOI 10.17487/RFC3948, January 2005,
https://www.rfc-editor.org/info/rfc3948. - [RFC5128] Srisuresh, P., Ford, B., and D. Kegel, "State of Peer-to-Peer (P2P) Communication across Network Address Translators (NATs)", RFC 5128, DOI 10.17487/RFC5128, March 2008,
https://www.rfc-editor.org/info/rfc5128. - [RFC5207] Stiemerling, M., Quittek, J., and L. Eggert, "NAT and Firewall Traversal Issues of Host Identity Protocol (HIP) Communication", RFC 5207, DOI 10.17487/RFC5207, April 2008,
https://www.rfc-editor.org/info/rfc5207. - [RFC5245] Rosenberg, J., "Interactive Connectivity Establishment (ICE): A Protocol for Network Address Translator (NAT) Traversal for Offer/Answer Protocols", RFC 5245, DOI 10.17487/RFC5245, April 2010,
https://www.rfc-editor.org/info/rfc5245. - [RFC6146] Bagnulo, M., Matthews, P., and I. van Beijnum, "Stateful NAT64: Network Address and Protocol Translation from IPv6 Clients to IPv4 Servers", RFC 6146, DOI 10.17487/RFC6146, April 2011,
https://www.rfc-editor.org/info/rfc6146. - [RFC6147] Bagnulo, M., Sullivan, A., Matthews, P., and I. van Beijnum, "DNS64: DNS Extensions for Network Address Translation from IPv6 Clients to IPv4 Servers", RFC 6147, DOI 10.17487/RFC6147, April 2011,
https://www.rfc-editor.org/info/rfc6147. - [RFC6538] Henderson, T. and A. Gurtov, "The Host Identity Protocol (HIP) Experiment Report", RFC 6538, DOI 10.17487/RFC6538, March 2012,
https://www.rfc-editor.org/info/rfc6538. - [RFC8656] Reddy, T., Ed., Johnston, A., Ed., Matthews, P., and J. Rosenberg, "Traversal Using Relays around NAT (TURN): Relay Extensions to Session Traversal Utilities for NAT (STUN)", RFC 8656, DOI 10.17487/RFC8656, February 2020,
https://www.rfc-editor.org/info/rfc8656. - [RFC8750] Migault, D., Guggemos, T., and Y. Nir, "Implicit Initialization Vector (IV) for Counter-Based Ciphers in Encapsulating Security Payload (ESP)", RFC 8750, DOI 10.17487/RFC8750, March 2020,
https://www.rfc-editor.org/info/rfc8750. - [RFC8899] Fairhurst, G., Jones, T., Tรผxen, M., Rรผngeler, I., and T. Vรถlker, "Packetization Layer Path MTU Discovery for Datagram Transports", RFC 8899, DOI 10.17487/RFC8899, September 2020,
https://www.rfc-editor.org/info/rfc8899. - [RFC9063] Moskowitz, R., Ed. and M. Komu, "Host Identity Protocol Architecture", RFC 9063, DOI 10.17487/RFC9063, July 2021,
https://www.rfc-editor.org/info/rfc9063.
Appendix A. Selecting a Value for Check Pacing ๐
Picking the right value for connectivity check transaction pacing is literally essential ๐ญ It makes or breaks the performance of connectivity check-based NAT traversal. The value can't be so small that the checks cause network congestion or overwhelm the NATs, but it also can't be so high that the checks drag on forever and delay connection setup ๐
The Ta value may be configured by the user in environments where the network characteristics are known beforehand. But if the characteristics are not known, it is recommended that the value is adjusted dynamically ๐ฆ In that case, it is recommended that the hosts estimate the round-trip time (RTT) between them, and they SHOULD set the minimum Ta value so that at most a single connectivity check message is sent on every RTT โจ
There's a neat way to estimate the RTT: use the time it takes for the Control Relay Server registration exchange to complete. This gives an estimate of the registering host's access link RTT ๐ธ The I1/R1 exchange could also be used for estimating the RTT, but since the R1 can be cached in the network, or the relaying service can increase the delay notably, this is not recommended ๐
Honestly, estimating RTT can be difficult and error prone ๐ฉ So the guidelines for choosing a Ta value in Section 4.4 MUST be followed. No skipping, periodt ๐
Appendix B. Differences with Respect to ICE ๐
Okay so, Legacy ICE-HIP just reuses the ICE/STUN/TURN protocol stack as it is ๐. The perks are reusing STUN/TURN infrastructure and maybe existing software libraries, but there are drawbacks too. ICE is meant for application-layer protocols, whereas HIP operates at layer 3.5 between transport and network layers, and that is super messy ๐ญ. It's especially messy because the implementations use kernel-space IPsec ESP as their data plane. Demultiplexing incoming ESP, HIP, and TURN messages meant capturing all UDP packets destined to port 10500 and sending them up to userspace, because ESP and STUN have different, incompatible markers. That adds software complexity and an unnecessary latency/throughput bottleneck for dataplane performance ๐
. It's also worth noting that demultiplexing STUN packets in the kernel would still cost performance (just less than doing it in userspace ๐ธ). Securely verifying STUN messages would also need communication between the kernel-space STUN detector and the HIP daemon, which usually lives in userspace. Yep, more overhead ๐.
Legacy ICE-HIP has some other complexities compared to the approach in this document too โจ. Relaying ESP packets via TURN relays wasn't that simple, because TURN relays require adding and removing extra TURN framing for the relayed packets. And the developers of the two Legacy ICE-HIP implementations concluded that integrating an ICE library into a HIP implementation took quite a bit more effort than they first estimated ๐ฉ. The extra code (some 10 kLoC) needed for all the new parsers, state machines, etc. was also pretty high, and by reusing the HIP code, you should be able to get away with much less. That should mean a smaller binary size, fewer bugs, and easier debugging ๐ง.
So the HIP working group decided to follow the ICE methodology but reuse the HIP messaging format to achieve the same functionality as ICE ๐. The result is this document, which specifies the Native ICE-HIP protocol ๐ฆ.
The Native ICE-HIP protocol specified in this document follows the semantics of ICE as closely as possible, and most of the differences are syntactical because it uses a different protocol ๐. Here's how it differs from ICE, bestie ๐ซถ.
- ICE operates at the application layer, whereas this protocol operates between transport and network layers, which hides the protocol details from the application ๐.
- The STUN protocol is not employed. Instead, Native ICE-HIP reuses the HIP control plane format so that demultiplexing different protocols is simpler ๐. For example, the STUN binding response is replaced with a HIP UPDATE message containing an
ECHO_REQUEST_SIGNEDparameter, and the STUN binding response is replaced with a HIP UPDATE message containing anECHO_RESPONSE_SIGNEDparameter, as defined in Section 4.6. Be warned, though: a drawback of not employing STUN is that discovering the address candidates requires creating state (using HIP base exchange) and maintaining it (using HIP UPDATE procedures) at the Control Relay Client and Control Relay Server ๐ฌ. Future extensions to this document may define a stateless, HIP-specific mechanism for an end host to discover its address candidates โจ. - The TURN protocol is not utilized. Instead, Native ICE-HIP reuses Control Relay Servers for the same purpose ๐ฅ.
- ICMP errors may be used in ICE to signal failure. In the Native ICE-HIP protocol, HIP NOTIFY messages are used instead ๐.
- Instead of the ICE username fragment and password mechanism for credentials, Native ICE-HIP uses the HIT, which is derived from a public key, for the same purpose ๐. The username fragments are "transient host identifiers, bound to a particular session established as part of the candidate exchange" [RFC8445]. Generally in HIP, a local public key and the derived HIT are considered long-term identifiers that stay invariant across different host associations and different transport-layer flows ๐ธ.
- In ICE, the conflict when two communicating endpoints take the same controlling role is solved using random values (a so-called tie-breaker value). In the Native ICE-HIP protocol, the conflict is solved by the standard HIP base exchange procedure, where the host with the "larger" HIT switches to the Responder role, which also changes it to the controlled role ๐ญ.
- The
ICE-CONTROLLEDandICE-CONTROLLINGattributes are not included in the connectivity checks ๐ . - The foundation concept is unnecessary in Native ICE-HIP, because only a single UDP flow for the IPsec tunnel will be negotiated ๐ง.
- Frozen candidates are omitted for the same reason the foundation concept is excluded ๐ซง.
- Components are omitted for the same reason the foundation concept is excluded ๐.
- Native ICE-HIP supports only "full ICE", where the two communicating hosts actively take part in the connectivity checks. The "lite" mode is not supported ๐ . This design decision follows the ICE guidelines, which recommend full ICE implementations. However, a publicly reachable Responder may refuse to negotiate the ICE mode, as described in Section 4.7.2. That would result in a HIP base exchange (as per [RFC7401]) tunneled over UDP, followed by ESP traffic over the same tunnel, without the connectivity check procedures defined in this document. In some sense, this mode corresponds to the case where two ICE lite implementations connect, since no connectivity checks are sent ๐.
- Because "ICE lite" is not adopted here, and both sides are capable of ICE-HIP-UDP mode (negotiated during the base exchange), default candidates are not employed in Native ICE-HIP ๐ท.
- If the agent is using Diffserv Codepoint markings [RFC2475] in its media packets, it SHOULD apply those same markings to its connectivity checks ๐.
- Unlike in ICE, the addresses are not XORed in the Native ICE-HIP protocol. They are encrypted instead, to avoid middlebox tampering ๐.
- ICE defines Related Address and Port attributes for diagnostic/SIP purposes, but the Native ICE-HIP protocol does not employ these attributes ๐ง.
- The minimum RTO is 500 ms in ICE but 1000 ms in the Native ICE-HIP protocol, in favor of [RFC8961] ๐ฐ๏ธ.
Appendix C. Differences to Base Exchange and UPDATE Procedures โจ
okay so this section is basically design guidance for implementers ๐ง it's all about how this protocol extends and differs from [RFC7401] and [RFC8046], and honestly it's giving very "here's what's different and why" energy ๐
- Both the control and data plane run on top of UDP, not directly on IP ๐ฆ
- A minimal implementation would only need to conform to Sections 4.7.1 or 4.7.2, which basically just tunnels HIP control and data traffic over UDP. The catch? It only works in the limited cases where the Responder has a public address ๐
- A Rendezvous Server [RFC8004] wasn't designed for NATed scenarios, because it just relays the first I1 packet and doesn't use UDP encapsulation. The Control Relay Server forwards all control traffic, so it's way more suitable in NATed environments ๐ธ Also, the Data Relay Server guarantees forwarding of data plane traffic even when the NAT traversal procedures fail ๐ซถ
- Registration with a Control/Data Relay Server is similar to registering with a Rendezvous Server, but the parameters are different because the service is different ๐ The Control/Data Relay Server also includes a REG_FROM parameter that tells the Control/Data Relay Client about its server-reflexive address โจ A Data Relay Server also includes a RELAYED_ADDRESS, which contains the relayed address for the Data Relay Client ๐
- In [RFC7401], the Initiator and Responder can start exchanging application payload right after the base exchange. Exchanging data right after a base exchange via a Data Control Relay would also be possible here, but we follow the ICE methodology to set up a direct path between two hosts using connectivity checks ๐ฅ So yes, there's some extra delay before application payload can be sent, and the same goes for the UPDATE procedure since the connectivity checks add a bit of wait time ๐ญ
- Without any NAT traversal support, the base exchange acts as an implicit connectivity check, and the mobility and multihoming extensions support explicit connectivity checks ๐ง After a base exchange or UPDATE-based connectivity checks, a host can use the associated address pair to send application payload. In this Native ICE-HIP extension we follow the ICE methodology, where one endpoint acting in the controlled role chooses the used address pair on behalf of the other endpoint acting in the controlled role. That's different from HIP without NAT traversal support ๐ The choice is also explicitly signaled using nomination packets. The nomination process in this protocol only supports a single address pair, and multihoming extensions are left for further study ๐
- The UPDATE procedure resembles the mobility extensions defined in [RFC8046] ๐ง The first UPDATE message from the mobile host is exactly the same as in the mobility extensions. The second UPDATE message from the peer host and the third from the mobile host are different, though: they just acknowledge and wrap up the reception of the candidates through the Control Relay Server. So they don't test for connectivity yet (apart from reachability through the Control Relay Server), unlike the mobility extensions ๐ The idea is that the connectivity check procedure follows the ICE specification, which is kinda different from the HIP mobility extensions ๐
- The connectivity checks in the mobility extensions [RFC8046] are only triggered by the peer of the mobile host. But successful NAT traversal requires that both endpoints test connectivity, so both the mobile host and its peer host have to test for connectivity ๐ค On top of that, this protocol also validates the UDP ports. The ports in the connectivity check must match the response, as required by ICE ๐
- Okay, the state stuff is where it gets spicy ๐ In [RFC8046] (HIP mobility), an outbound locator has some state. UNVERIFIED means the locator hasn't been tested for reachability, ACTIVE means the address has been verified for reachability and is actively in use, and DEPRECATED means the locator lifetime has expired. In the subset of ICE specifications this protocol uses, an individual address candidate only has two properties: type and priority โจ The real state in ICE is tied to candidate pairs instead of individual addresses. For a candidate pair, this subset requires these attributes: valid bit, nominated bit, base, and the state of the connectivity check. The connectivity checks can be in these states: Waiting, In-progress, Succeeded, and Failed. Handling this state needs some extra logic compared to the mobility extensions, because the state belongs to a local-remote address pair rather than just a remote address. So the mobility and ICE states don't have a clean one-to-one mapping ๐คฏ
- Credit-based authorization as defined in [RFC8046] could be used before candidate nomination has been concluded, which is when working candidate pairs are discovered ๐ซถ However, this may result in using asymmetric paths for a short time at the start of communications. So support for credit-based authorization is left for further study ๐ฅบ
Appendix D. Multihoming Considerations ๐ฆ
this one's all about multihoming ๐ธ This document lets a host collect address candidates from multiple interfaces, but it doesn't support activating and using multiple address candidates at the same time. Multihoming extensions that give similar functionality to [RFC8047] are left for further study and experimentation. Still, we can imagine some potential compatibility improvements to support multihoming, so here they are ๐
- Data Relay Registration: a Data Relay Client acting as an Initiator with another peer host should register a new server-reflexive candidate for each local transport address candidate ๐ A Data Relay Client acting as a Responder should register a new server-reflexive candidate for each {local transport address candidate, new peer host} pair, for the reasons described in Section 4.12.3 โจ In both cases, the Data Relay Client should request the additional server-reflexive candidates by sending UPDATE messages originating from each of the local address candidates, as described in Section 4.1 ๐ Since the UPDATE messages come from an unknown location from the viewpoint of the Data Relay Server, it must also include an ECHO_REQUEST_SIGNED in the response so it can test for return routability ๐
- Data Relay unregistration: this follows the procedure in Section 4, but the Data Relay Client should unregister using the particular transport address to be unregistered ๐งน All transport address pair registrations can be unregistered when no RELAYED_ADDRESS parameter is included ๐
- PEER_PERMISSION parameter: this needs to be extended, or an additional parameter is needed, to declare the specific local candidate of the Data Relay Client ๐ Alternatively, PEER_PERMISSION could be used as a wild card to open permissions for a specific peer to all of the candidates of the Data Relay Client ๐
- Connectivity checks: the controlling host should be able to nominate multiple candidates, by repeating step 7 in Figure 5 in Section 4.6 using the additional candidate pairs ๐
- Keepalives: these should be sent for all the nominated candidate pairs ๐ซถ Similarly, the Control/Data Relay Client should send keepalives from its local candidates to its Control/Data Relay Server transport addresses ๐ฆ
Appendix E. DNS Considerations
This section updates Appendix B of [RFC5770], which will be replaced with the mechanism described in this section.
[RFC5770] did not specify how an end host can look up another end host via DNS and initiate a UDP-based HIP base exchange with it, so this section makes an attempt to fill this gap. ๐ธโจ Bestie, there was a whole hole here and this section is literally the patch.
[RFC8005] specifies how a HIP end host and its Rendezvous Server is registered to DNS. Essentially, the public key of the end host is stored as a HI record and its Rendezvous Server as an A or AAAA record. This way, the Rendezvous Server can act as an intermediary for the end host and forward packets to it based on the DNS configuration. The Control Relay Server offers similar functionality to the Rendezvous Server, with the difference being that the Control Relay Server forwards all control messages, not just the first I1 message. ๐ฆ So the Rendezvous Server only forwards the first I1, but the Control Relay Server forwards everything control-y. Iconic. ๐
Prior to this document, the A and AAAA records in the DNS refer either to the HIP end host itself or a Rendezvous Server [RFC8005], and control and data plane communication with the associated host has been assumed to occur directly over IPv4 or IPv6. However, this specification extends the records to be used for UDP-based communications. ๐ Okay so the records used to just point at the host or its Rendezvous Server, and everything was assumed to go straight over IPv4 or IPv6. Now they get to be used for UDP stuff too. Plot twist, periodt. ๐ฅ
Let us consider the case of a HIP Initiator with the default policy to employ UDP encapsulation and the extensions defined in this document. The Initiator looks up the Fully Qualified Domain Name (FQDN) of a Responder, and retrieves its HI, A, and AAAA records. Since the default policy is to use UDP encapsulation, the Initiator MUST send the I1 message over UDP to destination port 10500 (either over IPv4 in the case of an A record or over IPv6 in the case of an AAAA record). It MAY send an I1 message both with and without UDP encapsulation in parallel. In the case in which the Initiator receives R1 messages both with and without UDP encapsulation from the Responder, the Initiator SHOULD ignore the R1 messages without UDP encapsulation. ๐ง Lowkey the whole vibe is: default to UDP, you're allowed to double up, but if the Responder answers both ways, ignore the non-UDP R1s. No cap.
The UDP-encapsulated I1 packet could be received by four different types of hosts: ๐
HIP Control Relay Server: In this case, the A/AAAA records refer to a Control Relay Server, which will forward the packet to the corresponding Control Relay Client based on the destination HIT in the I1 packet.
HIP Responder supporting UDP encapsulation: In this case, the A/AAAA records refer to the end host. Assuming the destination HIT belongs to the Responder, the Responder receives and processes the I1 packet according to the negotiated NAT traversal mechanism. The support for the protocol defined in this document, as opposed to the support defined in [RFC5770], is dynamically negotiated during the base exchange. The details are specified in Section 4.3. ๐ The real Responder that speaks UDP encapsulation just takes the I1 and runs with it, and whether this new protocol gets used is negotiated mid-handshake. Full details live in Section 4.3, bestie.
HIP Rendezvous Server: This entity is not listening to UDP port 10500, so it will drop the I1 message. ๐ Rendezvous Server? Not listening on that port. Dropped. Oop.
HIP Responder not supporting UDP encapsulation: The targeted end host is not listening to UDP port 10500, so it will drop the I1 message. ๐ Same energy, no UDP listener, I1 gets dropped.
The A/AAAA record MUST NOT be configured to refer to a Data Relay Server unless the host in question also supports Control Relay Server functionality. ๐ซ๐ Do NOT point an A or AAAA record at a Data Relay Server unless that same host also does Control Relay stuff. Non-negotiable, no debate.
It is also worth noting that SRV records are not employed in this specification. While they could be used for more flexible UDP port selection, they are not suitable for end-host discovery but rather would be more suitable for the discovery of HIP-specific infrastructure. Further extensions to this document may define SRV records for Control and Data Relay Server discovery within a DNS domain. ๐ SRV records are not used here. They could help with flexible port picking, but they're better for finding HIP infrastructure, not individual end hosts. Maybe a future extension will add SRV for relay discovery. Stay tuned, ngl I'm excited.
Acknowledgments
Thanks to Jonathan Rosenberg, Christer Holmberg, and the rest of the MMUSIC WG folks for the excellent work on ICE. The authors would also like to thank Andrei Gurtov, Simon Schuetz, Martin Stiemerling, Lars Eggert, Vivien Schmitt, and Abhinav Pathak for their contributions, and Tobias Heer, Teemu Koponen, Juhana Mattila, Jeffrey M. Ahrenholz, Kristian Slavov, Janne Lindqvist, Pekka Nikander, Lauri Silvennoinen, Jukka Ylitalo, Juha Heinanen, Joakim Koskela, Samu Varjonen, Dan Wing, Tom Henderson, Alex Elsayed, Jani Hautakorpi, Tero Kauppinen, and Timo Simanainen for their comments to [RFC5770] and this document. Thanks to รric Vyncke, Alvaro Retana, Adam Roach, Ben Campbell, Eric Rescorla, Mirja Kรผhlewind, Spencer Dawkins, Derek Fawcus, Tianran Zhou, Amanda Barber, Colin Perkins, Roni Even, Alissa Cooper, Carl Wallace, Martin Duke, and Benjamin Kaduk for reviewing this document. ๐ซถ So many legends credited, I'm literally tearing up.
This work has been partially funded by the Cyber Trust Program by Digile/Tekes in Finland. โจ
Contributors
Marcelo Bagnulo, Philip Matthews, and Hannes Tschofenig have contributed to [RFC5770]. This document leans heavily on the work in that RFC. ๐งโโ๏ธ
Authors' Addresses
Ari Kerรคnen Ericsson Hirsalantie 11 FI-02420 Jorvas Finland
Email: ari.keranen@ericsson.com
Jan Melรฉn Ericsson Hirsalantie 11 FI-02420 Jorvas Finland
Email: jan.melen@ericsson.com
Miika Komu (editor) Ericsson Hirsalantie 11 FI-02420 Jorvas Finland
Email: miika.komu@ericsson.com
That's the whole thing, bestie. We made it through all 18 parts. ๐๐๐
๐ฆ where this page comes from
- ietf: rfc9028 2021-07
- ๐ girlified by claude-haiku-5-5 on : a language model's rewrite of the original, under its terms