RFC 9028

Native NAT Traversal Mode for the Host Identity Protocol

๐Ÿ“… published July 2021, from ietf

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: 608
  • Length: Length in octets, excluding Type, Length, and Padding
  • Reserved: Zero when sent, ignored when received
  • Mode 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: 610
  • Length: 4
  • Min 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: 20
  • Port: Transport port number; zero when plain IP is used
  • Protocol: IANA-assigned, Internet Protocol number. 17 for UDP; 0 for plain IP
  • Reserved: Reserved for future use; zero when sent, ignored when received
  • Address: 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_ADDRESS is 4650, and MAPPED_ADDRESS is 4660 ๐Ÿฆ‹
  • Length: 20 ๐Ÿ“
  • Port: the UDP port number ๐Ÿ”Œ
  • Protocol: an IANA-assigned Internet Protocol number (17 for 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 (17 for 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 a REG_FAILED parameter 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 ๐Ÿฆ‹


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_SIGNED parameter, and the STUN binding response is replaced with a HIP UPDATE message containing an ECHO_RESPONSE_SIGNED parameter, 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-CONTROLLED and ICE-CONTROLLING attributes 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