RFC 6886

NAT Port Mapping Protocol (NAT-PMP)

๐Ÿ“… published April 2013, from ietf

NAT Port Mapping Protocol (NAT-PMP) ๐Ÿฆ‹ (Part 1 of 8)

the title block tea โ˜•๐Ÿ’…

  • RFC: 6886
  • Title: NAT Port Mapping Protocol (NAT-PMP)
  • Authors: S. Cheshire and M. Krochmal, both from Apple Inc. ๐ŸŽ
  • Category: Informational
  • Stream: Independent Submission
  • ISSN: 2070-1721
  • Date: April 2013
  • Obsoletes / Updates: the title block doesn't list anything this one obsoletes or updates โœจ

Abstract

okay so this doc is all about automating NAT port mappings ๐Ÿฆ‹ so you don't have to set them up by hand. ๐Ÿ™ˆ It also includes a way to ask a NAT gateway for its external IPv4 address, so a client can tell peers who want to talk to it what its external IPv4 address and port are. ๐Ÿ’–

fun history: from 2005 onwards this protocol was in Apple products, like Mac OS X, Bonjour for Windows, and AirPort wireless base stations ๐Ÿ“ ngl that's a whole legacy. โœจ

then in 2013, NAT-PMP got superseded by the IETF Standards Track RFC "Port Control Protocol (PCP)" ๐Ÿ‘‘. PCP builds on NAT-PMP and uses a compatible packet format, but it adds a bunch of significant enhancements ๐Ÿ”ฅ literally the upgrade we deserve.


Status of This Memo

this doc is not an Internet Standards Track specification ๐Ÿ™…โ€โ™€๏ธ it's published for informational purposes only. ๐Ÿ’œ

it's a contribution to the RFC Series, independently of any other RFC stream ๐ŸŒˆ the RFC Editor chose to publish it at their discretion and makes no statement about its value for implementation or deployment ๐Ÿคทโ€โ™€๏ธ and documents approved for publication by the RFC Editor are not a candidate for any level of Internet Standard. see Section 2 of RFC 5741 for the receipts ๐Ÿงพ

for current status, errata, and how to give feedback, check:

http://www.rfc-editor.org/info/rfc6886


Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved. ยฉ๏ธโœจ

this doc is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication. please read these carefully, because they describe your rights and restrictions with respect to this document ๐Ÿ“œ don't skip the fine print bestie ๐Ÿฅน


Table of Contents

   1. Introduction ....................................................3
      1.1. Transition to Port Control Protocol ........................4
   2. Conventions and Terminology Used in This Document ...............5
   3. Protocol and Packet Format ......................................5
      3.1. Requests and Responses .....................................6
      3.2. Determining the External Address ...........................7
      3.3. Requesting a Mapping ......................................10
      3.4. Destroying a Mapping ......................................13
      3.5. Result Codes ..............................................14
      3.6. Seconds Since Start of Epoch ..............................16
      3.7. Recreating Mappings on NAT Gateway Reboot .................16
      3.8. NAT Gateways with NAT Function Disabled ...................18
      3.9. All Mappings Are Bidirectional ............................19
   4. UNSAF Considerations ...........................................20
      4.1. Scope .....................................................20
      4.2. Transition Plan ...........................................20
      4.3. Failure Cases .............................................21
      4.4. Long-Term Solution ........................................23
      4.5. Existing Deployed NATs ....................................23
   5. Security Considerations ........................................23
   6. IANA Considerations ............................................24
   7. Acknowledgments ................................................24
   8. Deployment History .............................................25
   9. Noteworthy Features of NAT Port Mapping Protocol and PCP .......26
      9.1. Simplicity ................................................27
      9.2. Focused Scope .............................................27
      9.3. Efficiency ................................................27
      9.4. Atomic Allocation Operations ..............................29
      9.5. Garbage Collection ........................................29
      9.6. State Change Announcements ................................30
      9.7. Soft State Recovery .......................................31
      9.8. On-Path NAT Discovery .....................................31
   10. References ....................................................32
      10.1. Normative References .....................................32
      10.2. Informative References ...................................32

1. Introduction ๐ŸŒธ

okay so Network Address Translation (NAT) is a method of sharing one public Internet address with a bunch of devices ๐Ÿ  this doc is focused on devices that are formally classified as "NAPTs" (Network Address/Port Translators) [RFC2663]. a full description of NAT is out of scope here, so we're just doing the highlights that matter for this port mapping protocol โœจ if you want the whole NAT story, check "Traditional IP Network Address Translator (Traditional NAT)" [RFC3022].

NATs have one or more external IP addresses ๐ŸŒ there's a private network set up behind the NAT. client devices on that private network get private addresses, and they use the private address of the NAT device as their default gateway ๐Ÿงš

so when a packet from any device behind the NAT gets sent to an address on the public Internet, it first passes through the NAT box ๐Ÿ“ฆ the NAT box looks at the source port and address. sometimes a NAT also keeps track of the destination port and address ๐Ÿ‘€ then the NAT creates a mapping from the internal address and internal port to an external address and external port, if a mapping doesn't already exist ๐Ÿ’œ

the NAT box then swaps the internal address and port in the packet for the external entries from the mapping, and sends the packet on to the next gateway ๐Ÿฆ‹

now the reverse: when a packet from any address on the Internet hits the NAT's external side, the NAT looks up the destination address and port (external address and port) in its list of mappings. if there's an entry, it tells you the internal address and port the packet should go to ๐ŸŽฏ the NAT gateway then rewrites the destination address and port with the ones from the mapping, and the packet gets forwarded to those new destination addresses โœจ if the packet didn't match any mapping, it will most likely be dropped. various NATs handle this differently ๐Ÿคทโ€โ™€๏ธ the big takeaway is that if there's no mapping, the NAT doesn't know which internal address the packet should go to ๐Ÿ˜ญ

mappings are usually created automatically, as a result of observing outbound packets ๐Ÿ” there are a few exceptions though. some NATs allow manually created permanent mappings that map an external port to a specific internal IP address and port. that kind of mapping lets incoming connections reach the device with that internal address ๐ŸŽ€ some NATs also have a default mapping, where any inbound packet that doesn't match a more specific mapping gets forwarded to a specified internal address. both types are usually set up manually through some configuration tool ๐Ÿ› ๏ธ and honestly? manual configuration of port mappings is unreasonably onerous for most residential NAT users ๐Ÿ’€

without these manually created inbound port mappings, clients behind the NAT couldn't receive inbound connections ๐Ÿ“ต which is a loss of connectivity compared to the original Internet architecture [ETEAISD]. for anyone who sees that loss as a bad thing, NAT-PMP lets clients act more like a host directly connected to the unrestricted public Internet, with an unrestricted public IPv4 address ๐ŸŒˆ it lets client hosts talk to the NAT gateway to request the creation of inbound mappings on demand ๐Ÿ™Œ once a client has made a NAT mapping to allow inbound connections, it can record its external IPv4 address and external port in a public registry (e.g., the worldwide Domain Name System), or otherwise make it accessible to peers who want to communicate with it ๐Ÿซถ

1.1. Transition to Port Control Protocol

NAT-PMP had almost a decade of useful service ๐Ÿฅณ and the operational experience with NAT-PMP shaped the design of its IETF Standards Track successor, Port Control Protocol (PCP) [RFC6887]. PCP builds on NAT-PMP. it uses the same UDP ports 5350 and 5351, plus a compatible packet format ๐Ÿ” PCP also adds significant enhancements, including IPv6 support, management of outbound mappings, management of firewall rules, full compatibility with large-scale NATs that have a pool of external addresses, error lifetimes, and an extension mechanism for future enhancements ๐Ÿš€ the glow-up is real.

because PCP has these significant enhancements, all existing NAT-PMP implementations are encouraged to migrate to PCP ๐Ÿ’– the version number in the packet header is 0 for NAT-PMP and 2 for PCP, so the packets are easy to tell apart ๐Ÿ”Ž (version number 1 was used by a vendor that shipped products using a protocol that's incompatible with the IETF Standard. so, PCP implementations MUST NOT use version number 1 ๐Ÿ™…โ€โ™€๏ธ no cap.)

for NAT-PMP servers, adding PCP support is simple ๐Ÿง when packets come in, if the version number is 2, the packet is read as a PCP request. the request gets handled, and replies and updates about that mapping get sent in PCP format ๐Ÿ’… if the version number is 0, the existing code handles the request exactly as it already does, and replies and updates about that mapping are sent in NAT-PMP format ๐Ÿ™Œ if the version number is 1 or any other unsupported version, then result code 1 (Unsupported Version) is returned ๐Ÿซ 

now for NAT-PMP clients: they should add PCP support, and should default to sending requests in PCP format. that way clients prefer the newer format whenever they can ๐Ÿ‘‘ if a PCP request gets sent to an old NAT-PMP server that doesn't understand the PCP format, it returns result code 1 (Unsupported Version), and the client should then immediately retry the same request in NAT-PMP format โšก the Unsupported Version reply lets you fail over to NAT-PMP fast, without waiting on timeouts, retransmissions, or other arbitrary delays. it is recommended that clients always try PCP first for every new request, retransmission, and renewal, and only try NAT-PMP in response to an "Unsupported Version" error ๐ŸŽ€

Clients SHOULD NOT record that a given server only speaks NAT-PMP and then default to NAT-PMP for that server ๐Ÿšซ the reason: NAT firmware gets updated, so even a NAT gateway that speaks only NAT-PMP today may be updated to speak PCP tomorrow ๐Ÿ”ฎ never assume the vibes stay the same.

2. Conventions and Terminology Used in This Document ๐Ÿ’œ

the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in "Key words for use in RFCs to Indicate Requirement Levels" [RFC2119] ๐Ÿงšโœจ these are the capitalized requirement words, so read them like the rules they are.

3. Protocol and Packet Format โœจ

okay so this is where the actual packet life begins ๐Ÿฆ‹ NAT-PMP runs over UDP ๐Ÿ’… Every packet starts with an 8-bit version, followed by an 8-bit operation code. Super simple, iconic.

Numbers bigger than one byte (like error values, Seconds Since Start of Epoch, and mapping lifetime) get sent in the traditional IETF network byte order, which means most significant byte first ๐Ÿซถ

Non-numeric stuff bigger than one byte, like the NAT gateway's external IP address, goes in the natural byte order with no byte swapping ๐Ÿ’€ just send it as it is.

This doc specifies version 0 of the protocol. Any NAT-PMP gateway that implements this version and gets a request with a version number other than 0 MUST return result code 1 (Unsupported Version). It also MUST put the highest version it does support (that's 0) in the version field of the response. Not rude, just very correct ๐Ÿ˜ญ

Opcodes 0 to 127 are client requests, and 128 to 255 are the matching server responses. Responses always have a 16-bit result code in network byte order, and zero means success โœจ They also carry a 32-bit unsigned integer for the number of seconds since the NAT gateway was rebooted, or since its port mapping state was otherwise reset.

This protocol SHOULD only be used when the client figures out that its primary IPv4 address is in one of the private IPv4 address ranges from "Address Allocation for Private Internets" [RFC1918]. That covers 10/8, 172.16/12, and 192.168/16 ๐ŸŒธ

Clients always send their NAT-PMP requests to their default gateway, which they learn through DHCP [RFC2131] or something similar. This protocol is built for small home networks with one logical link (subnet), where the default gateway is also the NAT for that network. If the NAT is some other device in a more complicated network, NAT-PMP is not appropriate ๐Ÿ™…โ€โ™€๏ธ


3.1. Requests and Responses

okay so NAT gateways are usually low-cost little devices with limited memory and CPU speed. So to avoid overwhelming them, clients SHOULD NOT issue multiple concurrent requests ๐Ÿงš If a client has several things to ask for (on boot, after waking from sleep, on a new network connection, etc.), it SHOULD queue them up and send them serially, one at a time. Once the gateway answers one request, the client may send the next.

A fast gateway might handle hundreds of requests per second. A slow one that takes around half a second to respond is a different story, so the client SHOULD respect that and let the gateway work at its own pace instead of flooding it with requests faster than it can answer ๐Ÿ“

To figure out the external IPv4 address, or to request a port mapping, a NAT-PMP client sends its request packet to port 5351 of its configured gateway address, then waits 250 ms for a response. If no NAT-PMP response shows up from the gateway after 250 ms, the client retransmits and waits 500 ms. The client SHOULD keep repeating this, with the interval between attempts doubling each time. If, after its ninth attempt (and then waiting 64 seconds), the client still hasn't heard back, it SHOULD conclude that this gateway does not support NAT Port Mapping Protocol, and it MAY log an error message saying so ๐Ÿ“ Also, if the NAT-PMP client gets an "ICMP Port Unreachable" message from the gateway for port 5351, it can skip the remaining retransmissions and conclude right away that the gateway doesn't support NAT-PMP. Speedy ๐Ÿƒโ€โ™€๏ธ

As a performance optimization, the client MAY record this information and use it to stop trying NAT-PMP again and again ๐Ÿ™ˆ but the client should not hang onto that info for too long. Any event that may signal a change of gateway or a change in gateway configuration should make the client throw out what it knew about the gateway's lack of NAT-PMP support and send its next NAT-PMP request normally. Things like a hardware link change, a change of gateway MAC address, a brand new DHCP lease, or receiving a NAT-PMP announcement packet from the gateway all count ๐Ÿ”„

When deleting a port mapping, the client uses the same initial 250 ms timeout, doubling on each successive interval. Clients may choose not to try the full nine times before giving up, though. Why? Because mapping deletion requests are kind of advisory. They're useful for efficiency, but not required for correctness. Client software can crash, power can fail, or a device can get unplugged before it ever sends its deletion request(s), so NAT gateways already have to cope with that case anyway ๐Ÿซ  Because of this, it may be acceptable to retry only once or twice before giving up on deleting port mapping(s). Still, a client SHOULD always send at least one deletion request whenever possible, so less stale state piles up on NAT gateways ๐Ÿงน

A client doesn't need to keep trying to delete a port mapping after the time when that mapping would naturally have expired anyway. Bye bye, mapping ๐Ÿ‘‹


3.2. Determining the External Address

so to find out the external address, the client behind the NAT sends this UDP payload to port 5351 of the configured gateway address:

    0                   1
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Vers = 0      | OP = 0        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

A compatible NAT gateway MUST generate a response that looks like this ๐ŸŽ€

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Vers = 0      | OP = 128 + 0  | Result Code (net byte order)  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Seconds Since Start of Epoch (in network byte order)          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | External IPv4 Address (a.b.c.d)                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

This response tells the client that the NAT gateway implements this version of the protocol, and it hands back the NAT gateway's external IPv4 address ๐ŸŒˆ If the result code is non-zero, the External IPv4 Address field is undefined. It MUST be set to zero on transmission, and it MUST be ignored on reception. Undefined means undefined, babe ๐Ÿ™…โ€โ™€๏ธ

The NAT gateway MUST fill in the Seconds Since Start of Epoch field with the time elapsed since its port mapping table was initialized on startup, or since it was reset for any other reason (see Section 3.6, "Seconds Since Start of Epoch") โฑ๏ธ

Upon receiving a response packet, the client MUST check the source IP address. If that address isn't the address of the gateway the request was sent to, the client MUST silently discard the packet. Main character energy, but for packets ๐Ÿ’…


3.2.1. Announcing Address Changes

okay this part is so good. Upon boot, on acquiring an external IPv4 address, on a subsequent change of the external IPv4 address, on reboot, or on any other event that might mean the NAT mapping state got lost or changed, the NAT gateway MUST send a gratuitous response to the link-local multicast address 224.0.0.1, port 5350. It uses the packet format above, so clients get the external IPv4 address and Seconds Since Start of Epoch ๐Ÿ“ฃ

To survive packet loss, the NAT gateway SHOULD multicast 10 address notifications. The gap between the first two notifications SHOULD be 250 ms, and the gap between each later notification SHOULD double. The Seconds Since Start of Epoch field in each transmission MUST be updated to reflect the time that has passed, so clients don't trigger unnecessary extra mapping renewals (see Section 3.7, "Recreating Mappings on NAT Gateway Reboot") ๐Ÿ”

Upon receiving a gratuitous address announcement packet, the client MUST check the source IP address. If it isn't the address of the client's current configured gateway, the client MUST silently discard the packet. This guards against accidental misconfigurations, like there being more than one NAT gateway active on the network ๐Ÿ›ก๏ธ

If the source IP address is correct, the client checks the Seconds Since Start of Epoch field as described in Section 3.6. If the value is outside the expected plausible range, that means a NAT gateway state loss has happened, and the NAT-PMP client promptly recreates all of its active port mapping leases, as described in Section 3.7, "Recreating Mappings on NAT Gateway Reboot" ๐Ÿ˜ฑ

IMPLEMENTATION NOTE: Earlier implementations of NAT-PMP used UDP port 5351 as the destination for both client requests (address and port mapping) and address announcements. NAT-PMP servers listened on UDP 5351 for client requests, and NAT-PMP clients listened on UDP 5351 for server announcements. However, implementers ran into trouble when a single device was doing both jobs, like a home computer with Internet Sharing turned on. That computer acts as a NAT-PMP server for its DHCP clients, yet it also has to act as a NAT-PMP client to figure out whether it's behind another NAT gateway itself. In principle, some operating systems might let two processes share a single UDP port, but on many platforms that's difficult or even impossible. So, for pragmatic engineering reasons, it's convenient for clients to listen on UDP 5350 and servers to listen on UDP 5351 ๐Ÿง 
IMPLEMENTATION NOTE: A given host may run more than one independent NAT-PMP client at the same time, and address announcements need to be available to all of them. So clients should set the SO_REUSEPORT option or an equivalent, so other processes can also listen on port 5350. Also, implementers have had issues when one or more processes on the same device listen to port 5350 on all addresses. So clients should bind specifically to 224.0.0.1:5350, not to 0.0.0.0:5350 ๐Ÿซถ

3.3. Requesting a Mapping ๐ŸŽ€

okay bestie, making a mapping is super simple ๐Ÿ’… the client sends a UDP packet to port 5351 of the gateway's internal IP address, and it looks like this:

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Vers = 0      | OP = x        | Reserved                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Internal Port                 | Suggested External Port       |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Requested Port Mapping Lifetime in Seconds                    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Opcodes supported:

1 - Map UDP
2 - Map TCP

The Reserved field MUST be set to zero on transmission and MUST be ignored on reception. ๐Ÿซถ Same vibe for the Ports and Lifetime: they go out in the traditional network byte order (i.e., most significant byte first) ๐Ÿงš

The Internal Port is just the local port your client is listening on ๐ŸŒธ

Now the Suggested External Port is where it gets spicy ๐ŸŒถ๏ธ If you want a high-numbered "anonymous" external port, set it to zero, and the gateway picks a high-numbered port of its own choosing โœจ If you'd rather the external port match your internal one (like a web server on port 80 that's dreaming of external port 80 ๐Ÿ’–), put that value in instead. BUT the gateway is not obliged to give you what you suggested, and it might say no for policy reasons (like port 80 being reserved and clients not being allowed to request it) or because someone else already grabbed that port ๐Ÿ˜ญ So some product developers have literally questioned whether this field is even worth having. The real reason it exists is failure recovery. Most low-cost home NAT gateways don't save temporary port mappings to persistent storage, so if the gateway crashes or reboots, all the mappings are gone ๐Ÿ’€ A renewal packet is formatted exactly like an initial mapping request, except the client sets the Suggested External Port to the port the gateway actually assigned, not the one it originally wanted ๐Ÿฆ‹

When a freshly rebooted NAT gateway gets a renewal packet, it just sees an ordinary initial request for a port mapping. The difference is that the Suggested External Port is likely to be one the NAT gateway is willing to allocate, since it handed that port to this client right before the reboot and should presumably be willing to hand it out again ๐Ÿฅน This is what improves the stability of external ports across NAT gateway restarts, which is honestly iconic โœจ

The RECOMMENDED Port Mapping Lifetime is 7200 seconds (two hours) โฐ

After sending the port mapping request, the client waits for the NAT gateway to respond. If after 250 ms the client hasn't received a response from the gateway, the client SHOULD reissue its request as described above in Section 3.1, "Requests and Responses" ๐Ÿ”

The NAT gateway responds with this packet format:

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Vers = 0      | OP = 128 + x  | Result Code                   |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Seconds Since Start of Epoch                                  |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Internal Port                 | Mapped External Port          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Port Mapping Lifetime in Seconds                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

The epoch time, ports, and lifetime are also sent in the traditional network byte order (most significant byte first) ๐Ÿงš

The 'x' in the OP field MUST match what the client requested ๐Ÿ’… Some NAT gateways can't create a UDP port mapping without also creating a matching TCP one (and vice versa), and these gateways MUST NOT implement NAT Port Mapping Protocol until that deficiency is fixed ๐Ÿ™ˆ A NAT gateway that implements this protocol MUST be able to create TCP-only and UDP-only port mappings. If a gateway silently creates a pair of mappings for a client that only asked for one, it could expose that client to inbound UDP packets or inbound TCP connection requests it never asked for and doesn't want ๐Ÿ˜ฌ

While a NAT gateway MUST NOT automatically create mappings for TCP when the client requests UDP (or the other way around), the NAT gateway MUST reserve the companion port so the same client can choose to map it later. For example, if a client requests to map TCP port 80, then as long as the client keeps the lease for that TCP port mapping, another client with a different internal IP address MUST NOT be able to successfully acquire the mapping for UDP port 80. ๐Ÿ›ก๏ธ

The client normally requests the external port that matches its internal port. If that external port isn't available, the NAT gateway MUST return an available external port if possible, or return an error code if no external ports are available ๐Ÿ”

The source address of the packet MUST be used for the internal address in the mapping. This protocol is not intended to let one device behind a NAT create mappings for other devices, bestie ๐Ÿ™…โ€โ™€๏ธ If there are legacy devices that need inbound mappings, a human can still create permanent mappings manually through an administrative interface, just like they do today ๐Ÿงธ

Here's a fun one ๐ŸŽ€ If a mapping already exists for a given internal address and port (whether it was created explicitly using NAT-PMP, implicitly because of an outgoing TCP SYN packet, or manually by a human administrator), and the client requests another mapping for that same internal port (maybe asking for a different external port), then the mapping request should succeed and return the already-assigned external port. This is needed for the case where a client requests a mapping with suggested external port X, gets a mapping with actual external port Y, but the acknowledgment packet gets lost ๐Ÿ˜ญ When the client retransmits, it should get back the same positive acknowledgment that was sent (and lost) the first time. Not the same vibe as a second chance, it's a whole comeback ๐Ÿ’œ

The NAT gateway MUST NOT accept mapping requests destined to the NAT gateway's external IP address or received on its external network interface. Only packets received on the internal interface(s) with a destination address matching the internal address(es) of the NAT gateway should be allowed ๐Ÿšช

The NAT gateway MUST fill in the Seconds Since Start of Epoch field with the time elapsed since its port mapping table was initialized on startup or reset for any other reason (see Section 3.6, "Seconds Since Start of Epoch") โณ

The Port Mapping Lifetime is an unsigned integer in seconds. The NAT gateway MAY reduce the lifetime from what the client requested. The NAT gateway SHOULD NOT offer a lease lifetime greater than the one the client asked for ๐Ÿ“

Upon receiving the response packet, the client MUST check the source IP address, and silently discard the packet if that address isn't the address of the gateway the request was sent to ๐Ÿ‘€

Finally, the client SHOULD begin trying to renew the mapping halfway to expiry time, like DHCP ๐Ÿฅฐ The renewal packet should look exactly the same as a request packet, except that the client SHOULD set the Suggested External Port to what the NAT gateway previously mapped, not what the client originally suggested. As we covered above, this lets the gateway automatically recover its mapping state after a crash or reboot ๐Ÿ‘‘โœจ

3.4. Destroying a Mapping ๐Ÿงน

okay so mappings don't just live forever, bestie ๐Ÿ’… there are a few different ways they get deleted. First up, if a client fails to renew a mapping, the mapping MUST be automatically deleted at the moment its lifetime expires โฐ no lingering, no drama.

Then there's the DHCP situation ๐ŸŽ€ In the super common setup where the gateway device is a combined DHCP server and NAT gateway, when a client's DHCP address lease expires, the gateway device MAY automatically delete any mappings that belonged to that client. Why? Because otherwise a brand new client that gets handed the same IP address could suddenly receive unexpected inbound UDP packets or inbound TCP connection requests it never asked for and definitely does not want ๐Ÿ™ˆ not it!

A client MAY also send an explicit packet to request deletion of a mapping it doesn't need anymore ๐Ÿฆ‹ To do that, it sends a message to the NAT gateway requesting the mapping, with the Requested Lifetime in Seconds set to zero. The Suggested External Port MUST be set to zero by the client on sending, and MUST be ignored by the gateway on reception ๐Ÿ’–

When a mapping gets destroyed successfully because the client asked for the deletion, the NAT gateway MUST send a response packet formatted as defined in Section 3.3, "Requesting a Mapping" ๐ŸŒธ That response MUST contain a result code of 0, the internal port from the deletion request, an external port of 0, and a lifetime of 0. Also, the NAT gateway MUST respond to a request to destroy a mapping that doesn't exist as if the request were successful ๐Ÿซถ This is because the acknowledgment might get lost, and then the client retransmits its request to delete the mapping. In that case, the second request to delete the mapping MUST return the same response packet as the first request, iconic consistency ๐Ÿ‘‘

If the deletion request was unsuccessful, the response MUST contain a non-zero result code and the requested mapping. The lifetime is undefined (it MUST be set to zero on transmission, and MUST be ignored on reception) ๐Ÿคท And if the client tries to delete a port mapping that was manually assigned by some kind of configuration tool, the NAT gateway MUST respond with a "Not Authorized" error, result code 2 ๐Ÿšซ

Heads up, this next part is about TCP connections still hanging around on a mapping that's now gone ๐Ÿ’€

When a mapping is destroyed because its lifetime expired or for any other reason, and the NAT gateway's internal state shows there are still active TCP connections going through that now-defunct mapping, then the NAT gateway SHOULD send appropriately constructed TCP RST (reset) packets to both the local client and the remote peer on the Internet, to terminate that TCP connection ๐Ÿ”ฅ

A client can ask for explicit deletion of all its UDP or TCP mappings by sending the same deletion request to the NAT gateway with the external port, internal port, and lifetime all set to zero ๐Ÿงš A client MAY choose to do this when it first acquires a new IP address, so it protects itself from port mappings a previous owner of that IP address made ๐ŸŒˆ After getting a request like this, the gateway MUST delete all its UDP or TCP port mappings (depending on the opcode). The gateway replies to that deletion request with a response like the ones above, except with the internal port set to zero.

If the gateway can't delete a port mapping, for example because the administrator configured it manually, the gateway MUST still delete as many port mappings as possible, but respond with a non-zero result code. Which result code depends on what caused the failure. And if the gateway manages to delete all the port mappings as requested, it MUST respond with a result code of zero โœจ


3.5. Result Codes ๐ŸŽ€

Here's the full list of result codes that are currently defined, so you know exactly what each number means ๐Ÿ’œ

0 - Success
1 - Unsupported Version
2 - Not Authorized/Refused
       (e.g., box supports mapping, but user has turned feature off)
3 - Network Failure
       (e.g., NAT box itself has not obtained a DHCP lease)
4 - Out of resources
       (NAT box cannot create any more mappings at this time)
5 - Unsupported opcode

If the version in the request is not zero, then the NAT-PMP server MUST return the following "Unsupported Version" error response to the client ๐Ÿ™…โ€โ™€๏ธ

    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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Vers = 0      | OP = 0        | Result Code = 1               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   | Seconds Since Start of Epoch (in network byte order)          |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

If the opcode in the request is 128 or greater, then it isn't a request at all, it's a response, and the NAT-PMP server MUST silently ignore it ๐Ÿคซ Otherwise, if the opcode in the request is less than 128 but isn't a supported opcode (currently 0, 1, or 2), then the entire request MUST be returned to the sender. The top bit of the opcode gets set to show it's a response, and the result code is set to 5 (Unsupported opcode) ๐Ÿ’€

For version 0 and a supported opcode (0, 1, or 2), if the operation fails for some reason (Not Authorized, Network Failure, or Out of resources), then a valid response MUST be sent to the client. The top bit of the opcode is set to indicate it's a response, and the result code is set appropriately. Other fields in the response MUST be set appropriately too. Specifically:

  • Seconds Since Start of Epoch MUST be set correctly
  • The External IPv4 Address should be set to the correct address, or to 0.0.0.0, as appropriate
  • The Internal Port MUST be set to the client's requested Internal Port. This is super important, because the client needs this info to figure out which request failed ๐Ÿ”
  • The Mapped External Port and Port Mapping Lifetime MUST be set appropriately, which means zero if no successful port mapping was created ๐Ÿ“

Should future NAT-PMP opcodes be defined, their error responses MUST similarly be specified so they include enough info to identify which request failed. By design, NAT-PMP messages don't contain any transaction identifiers ๐Ÿ™ˆ All NAT-PMP messages are idempotent and self-describing, so the specs for future NAT-PMP messages need to include enough info that their responses are self-describing too ๐Ÿซถ

Clients MUST be able to properly handle result codes that aren't defined in this document. Undefined result codes MUST be treated as fatal errors of the request ๐Ÿ˜ญ


3.6. Seconds Since Start of Epoch โณ

Every packet the NAT gateway sends includes a Seconds Since Start of Epoch (SSSoE) field ๐Ÿ•ฐ๏ธ If the NAT gateway resets or loses the state of its port mapping table, whether from a reboot, a power failure, or any other reason, it MUST reset its epoch time and start counting SSSoE from zero again ๐Ÿ”„

Whenever a client receives any packet from the NAT gateway, whether it's unsolicited or a response to a client request, the client works out its own conservative estimate of the expected SSSoE value. It does this by taking the SSSoE value from the last packet it received from the gateway and adding 7/8 (87.5%) of the time that has passed on the client's local clock since that packet arrived ๐Ÿงฎ If the SSSoE in the newly received packet is more than 2 seconds less than the client's conservative estimate, the client concludes the NAT gateway has rebooted or otherwise lost its port mapping state. When that happens, the client MUST immediately renew all its active port mapping leases, as described in Section 3.7, "Recreating Mappings on NAT Gateway Reboot" ๐Ÿšจ๐Ÿ’–

3.7. Recreating Mappings on NAT Gateway Reboot โœจ

okay so the NAT gateway MAY save its mappings in persistent storage ๐Ÿ’พ that way, if it gets powered off or rebooted, it still remembers what the port mapping situation of the network was ๐Ÿง 

BUT (and this is important) keeping that state around isn't essential for things to work properly ๐Ÿ™ˆ when the NAT gateway powers on, or wipes its port mapping state because of a config change, it MUST reset the epoch time and re-announce its IPv4 address like we talked about in Section 3.2.1, "Announcing Address Changes" ๐Ÿ“ฃ when clients see that time has apparently gone backwards, that's their cue ๐Ÿšจ they SHOULD immediately send renewal packets to recreate their mappings instead of waiting for the originally scheduled renewal time ๐Ÿƒโ€โ™€๏ธ and if a client misses those announcements for any reason? no worries, it'll still renew at the originally scheduled time and get its mappings back, it just takes a bit longer ๐Ÿข๐Ÿ’•

a mapping renewal packet looks exactly the same as an original mapping request ๐Ÿ‘ฏโ€โ™€๏ธ from the client's point of view, it's a renewal of something that already exists, but from the point of view of the freshly rebooted NAT gateway, it's a brand new mapping request. so iconic ๐Ÿ’…

this self-healing property is literally so important ๐Ÿ˜ญ๐Ÿซถ

the reason the Internet is so reliable is mostly that important state lives in the endpoints, not in the network itself [ETEAISD] ๐ŸŒโœจ think about it: power-cycling an Ethernet switch just causes a brief pause in packets ๐Ÿ”Œ established TCP connections through that switch don't die, they're just delayed for a few seconds ๐Ÿ˜Œ even if a failing switch gets swapped for a new one, as long as the cables get moved over pretty quickly, all the TCP connections that were going through the old switch keep going through the new one, totally unbroken ๐Ÿฆ‹ same deal with IP routers, wireless base stations, and so on ๐Ÿ“ก the one exception is NAT gateways ๐Ÿ’€ the port mapping state is what tells the gateway where to forward inbound packets, so if that state gets lost, connectivity through the NAT gateway breaks ๐Ÿ˜ฑ the fix? let clients notice when the NAT gateway has lost that state and recreate it on demand ๐Ÿช„ that turns hard state in the network into soft state that can be recovered automatically when it's needed ๐Ÿ’–

without that automatic recreation of soft state in the NAT gateway, reliable long-term networking just wouldn't happen ๐Ÿฅฒ the reliability of the Internet doesn't come from building a perfect network where errors never happen ๐Ÿ™…โ€โ™€๏ธ it comes from accepting that in any big enough system, some component somewhere is always failing, and designing mechanisms that can handle those failures and bounce back ๐Ÿ’ช let's make it real with a scenario ๐ŸŽฌ imagine a network security camera with a web interface that accepts incoming connections from web browsers ๐Ÿ“ท this camera uses NAT-PMP (or something similar) to set up an inbound port mapping on the NAT gateway, so clients on the other side of the gateway can reach it ๐ŸŒธ now, this camera could run for weeks, months, or even years ๐Ÿ—“๏ธ during that time, the NAT gateway could lose power or get rebooted โšก the user could upgrade the gateway's firmware, or even swap the whole device for a newer model ๐Ÿ†• the big picture is that if the camera runs long enough, some kind of disruption to the NAT gateway becomes inevitable ๐ŸŒช๏ธ the question isn't whether the gateway loses its port mappings, it's when, and how often โฐ if the camera and devices like it can detect when the gateway has lost its mappings and recreate them automatically, then these disruptions fix themselves and are mostly invisible to the end user ๐Ÿฅฐ but if they can't, and after a gateway reboot the user has to manually reset or reboot every other device on the network too, then those disruptions are very visible to the end user ๐Ÿ˜ฉ this is the part of the design that separates a protocol that keeps working for months or years from one that works great in a quick test but keeps failing in the real world and needs someone to babysit it ๐Ÿ‘‘

when a client renews its port mappings because it got a packet where the Seconds Since Start of Epoch (SSSoE) field shows that a reboot or similar loss of state happened, the client MUST first wait a random amount of time, picked uniformly from the range 0 to 5 seconds ๐ŸŽฒ and only then send its first port mapping request ๐Ÿš€ once the gateway acknowledges that request, the client MAY send its next request, and so on, as fast as the gateway allows ๐ŸŽ๏ธ the requests SHOULD go out serially, one at a time ๐Ÿ‘ฃ the client SHOULD NOT issue multiple concurrent requests ๐Ÿ™…โ€โ™€๏ธ

this section focuses on recreating inbound port mappings after the NAT gateway loses its state, because that's the bigger problem ๐ŸŽฏ losing port mappings for outgoing connections kills the connections that are currently active, but it doesn't stop clients from making new outgoing connections ๐Ÿ™‚ losing inbound port mappings is way worse ๐Ÿ˜ญ it kills every existing inbound connection AND stops any new inbound connections from getting through until the mapping is recreated ๐Ÿ’” so yes, recovering inbound mappings is the priority ๐Ÿ’… that said, clients who want their outgoing connections to survive a NAT gateway reboot can also do it with NAT-PMP ๐ŸŽ€ this works in the common case of a residential NAT gateway with a single, fairly stable external IP address ๐Ÿ  after starting an outbound TCP connection (which makes the NAT gateway set up an implicit port mapping), the client should send the NAT gateway a port mapping request for the source port of that TCP connection ๐Ÿ” the gateway then responds with the external port it allocated for that mapping ๐ŸŽ the client can store that info and use it later to recreate the mapping if it figures out the NAT gateway has lost its mapping state ๐Ÿงš


3.8. NAT Gateways with NAT Function Disabled ๐Ÿ™…โ€โ™€๏ธ

quick reminder: only devices that are currently acting as a NAT gateway should take part in NAT-PMP exchanges with clients ๐Ÿง a network device that can do NAT (and NAT-PMP) but is currently set up not to (say, it's acting as a plain IP router, forwarding packets without changing them) MUST NOT respond to NAT-PMP requests from clients, and it MUST NOT send spontaneous NAT-PMP address-change announcements either ๐Ÿšซ๐Ÿ“ฃ

and it shouldn't even reply to NAT-PMP requests with an error code like 2, "Not Authorized/Refused" ๐Ÿ˜ค that would be super misleading ๐Ÿฅด it would suggest that NAT port mapping is needed on this network for the client to receive inbound connections, and that it's just not available because the admin turned that feature off ๐Ÿ™ƒ

clients also need to avoid making unfounded assumptions ๐Ÿ•ต๏ธโ€โ™€๏ธ for example, assuming that having an IPv4 address in one of the private IPv4 address ranges [RFC1918] means NAT must be in use is a big no ๐Ÿ™…โ€โ™€๏ธ net 10/8 alone has enough addresses to build a private network with millions of hosts and thousands of interconnected subnets, and none of it needs NAT ๐Ÿคฏ plenty of organizations have built private networks like that to use standard TCP/IP tech, and they choose not to connect to the public Internet ๐Ÿฐ NAT-PMP exists to soften some of the damage NAT causes ๐Ÿฉน it would be such an ironic, unwanted side effect if it pushed well-meaning developers to make products that refuse to work on a private network unless they can find a NAT gateway to talk to ๐Ÿ˜ฉ so if a client finds NAT-PMP isn't available on its network, it should not give up ๐Ÿ™Œ it should assume the network may just be a traditional routed IP network with no address translation ๐Ÿ›ฃ๏ธ that assumption might not always be right, but it's way better than wrongly assuming the worst and not even trying normal (non-NAT) IP networking ๐Ÿ’โ€โ™€๏ธ

if a network device that isn't currently acting as a NAT gateway gets UDP packets addressed to port 5351, it SHOULD respond right away with an "ICMP Port Unreachable" message ๐Ÿšฆ that tells the client it doesn't need to keep going with timeouts and retransmissions ๐Ÿ›‘ the client should then assume NAT-PMP isn't available and isn't needed on this network ๐Ÿคทโ€โ™€๏ธ usually, you can get this behaviour just by not having an open socket listening on UDP port 5351 ๐ŸŽฏ


3.9. All Mappings Are Bidirectional ๐Ÿ”„โœจ

all NAT mappings are bidirectional, no matter how they got made: implicitly by an outbound packet, explicitly with NAT-PMP, or configured statically ๐Ÿซถ so when an outbound packet from a particular internal address and port gets translated to an external address and port, replies sent to that external address and port need to get translated back to the matching internal address and port ๐Ÿ“ฌ

the converse is true too ๐Ÿ” when an inbound packet shows up addressed to an external address and port that matches an existing mapping (implicit, explicit, or static), it gets translated to the matching internal address and port and forwarded on ๐Ÿš€ outbound replies from that internal address and port need to be translated to the correct external address and port so the remote peer recognizes them ๐Ÿซก

now here's the tea โ˜• if an outbound UDP reply that matches an existing explicit or static mapping gets treated like a "new" outbound UDP packet instead, and a new dynamic mapping gets made (with a different external address and port), then by the time it reaches the remote peer it won't be recognized as a valid reply ๐Ÿ’€ for TCP, this bug gets caught fast, because every TCP implementation ignores replies with the wrong apparent source address and port ๐Ÿ™…โ€โ™€๏ธ for UDP, it can slip under the radar, because some UDP clients don't bother checking the source address and port of replies ๐Ÿ™ˆ so they'll seem to work some of the time with NAT gateways that put the wrong source address and port in outbound packets ๐Ÿ˜ตโ€๐Ÿ’ซ all NAT gateways MUST ensure that mappings, however they were created, are bidirectional ๐Ÿ’œ


4. UNSAF Considerations ๐Ÿงฉ

the document "IAB Considerations for UNilateral Self-Address Fixing (UNSAF) Across Network Address Translation (NAT)" [RFC3424] covers a bunch of issues when you're working with NATs ๐Ÿ“š it lays out some requirements for any document that tries to work around problems caused by NATs ๐Ÿ› ๏ธ this section is where we address those requirements ๐ŸŽ€

4.1. Scope

okay so this protocol is for TCP and UDP peers that are sitting behind exactly one IPv4 NAT and are cut off from the public Internet ๐Ÿงš These peers have to have access to some form of directory server, because that's where they register the public IPv4 address and port they can be reached at. ๐Ÿ’–

4.2. Transition Plan

bestie, this section is about future-proofing ๐Ÿ”ฎ Any client using this protocol SHOULD implement IPv6 support. If the client supports IPv6 and is running on a device with a global IPv6 address, that IPv6 address SHOULD be preferred over the IPv4 external address learned through this NAT mapping protocol. ๐Ÿซถ If other clients don't have IPv6 connectivity, both the IPv4 and IPv6 addresses SHOULD be registered with whatever directory server is in use. Preference SHOULD be given to IPv6 addresses whenever they're available. โœจ

The iconic part is that by supporting IPv6 and using this protocol for IPv4, vendors can ship products today that work in both scenarios. ๐Ÿ’… As IPv6 gets more widely deployed, clients that follow these recommendations will transparently start using IPv6 with zero drama. ๐Ÿฆ‹

4.3. Failure Cases

Aside from NATs that don't implement this protocol at all, there are a bunch of situations where this protocol may not work. ๐Ÿ˜ญ

4.3.1. NAT behind NAT

ngl this one is a whole saga ๐Ÿ™ˆ Some people's primary IPv4 address, the one their ISP assigned, may itself be a NAT address. Some people also have an external IPv4 address but then double NAT themselves, maybe on purpose and maybe by accident. ๐Ÿ’€ Sure, it might be possible in principle for one NAT gateway to recursively request a mapping from the next one, but this document doesn't push for that and doesn't try to spell out how it would work. ๐ŸŒˆ

Nested NAT port mapping would be a LOT of work to get right, and the end result might not be as useful as we'd hope. Picture an ISP that gives each customer only a single NAT address. That ISP could have just given each customer a single public IPv4 address instead. Or, if the ISP insists on running NAT, it could hand each customer a reasonable number of addresses, enough for every customer device to have its own NAT address straight from the ISP. ๐Ÿ‘‘ But if the ISP instead gives each customer just one NAT address and forces them to run nested NAT to use more than one device, it seems unlikely that this ISP would be generous enough to offer a NAT service that supports NAT-PMP. ๐Ÿ™„

Now supposing an ISP did want to offer NAT service with NAT-PMP so customers could receive inbound connections, it could easily let each client request a reasonable number of DHCP addresses from that gateway. Remember that Net 10/8 [RFC1918] gives you over 16 million addresses, so NAT addresses are not in any way in short supply. ๐Ÿ“ A single NAT gateway with 16 million available addresses is much more likely to run out of packet forwarding capacity before it runs out of internal addresses to hand out. So the ISP could offer single-level NAT with NAT-PMP, and there'd be no need to support nested NAT-PMP at all. ๐Ÿง  Plus, an ISP that really wants its customers to have unhindered access to the Internet, including incoming as well as outgoing connections, has better ways to do it. It could offer real public IPv4 addresses instead of NAT addresses, or offer full IPv6 connectivity, where no mapping or translation is needed at all. ๐ŸŒธ

Note: In the nine years since NAT-PMP was designed, the pool of available IPv4 addresses has run dry, and plenty of ISPs now offer translated IPv4 addresses out of necessity. These ISPs have said they're willing to offer PCP service to their customers. ๐Ÿšจ

4.3.2. NATs with Multiple External IPv4 Addresses

If a NAT maps internal addresses to multiple external addresses, it SHOULD pick one of those external addresses to support for inbound connections. For the purposes of this protocol, it SHOULD act as if that address is its only address. ๐ŸŽ€

4.3.3. NATs and Routed Private Networks

In some cases, a large network may be subnetted. Some sites install a NAT gateway and subnet the private network too. ๐Ÿ™ƒ That subnetting breaks this protocol, because the router address is not necessarily the address of the device doing the NAT. ๐Ÿ’”

Fixing this isn't a high priority. Any site with the resources to set up a configuration like this should also have the resources to add manual mappings or get a range of globally unique addresses. ๐Ÿ’…

Not every NAT supports this protocol. If a client runs behind a NAT that doesn't support it, the software relying on this protocol's functionality may be unusable. ๐Ÿ˜”

4.3.4. Communication between Hosts behind the Same NAT

NAT gateways supporting NAT-PMP should also implement "hairpin translation". ๐Ÿ” Hairpin translation means supporting communication between two local clients served by the same NAT gateway. ๐Ÿงš

Here's the scenario. Device A is listening for incoming connections on internal address and port 10.0.0.2:80. Using NAT-PMP, device A has obtained a mapping to external address and port x.x.x.x:80, and has recorded that external address and port in some kind of public directory. For example, it could have created a DNS SRV record containing this info and recorded it in a publicly accessible DNS server using DNS Dynamic Update [RFC3007]. ๐Ÿ“ Now device B, behind the same NAT gateway as device A, either doesn't know or doesn't care about this, so it looks up device A's DNS SRV record and tries to open a TCP connection to x.x.x.x:80. ๐Ÿ˜ณ The outgoing packets addressed to this public Internet address get sent to the NAT gateway for translation and forwarding. Once the gateway has translated the source address and port number on the outgoing packet, it needs to be smart enough to realize the destination address is actually itself. Then it has to feed the packet back into its packet reception engine, do the destination port mapping lookup, and forward the packet to device A at 10.0.0.2:80. ๐Ÿคฏ Main character gateway behavior, honestly. ๐Ÿ‘‘

4.3.5. Non-UDP/TCP Transport Traffic

Any communication over transport protocols other than TCP and UDP won't be served by this protocol. Examples include Generic Routing Encapsulation (GRE), Authentication Header (AH), and Encapsulating Security Payload (ESP). ๐Ÿšซ

4.4. Long-Term Solution

As IPv6 gets deployed, clients of this protocol that support IPv6 will be able to skip this protocol and the NAT entirely when talking to other IPv6 devices. ๐Ÿฆ‹ To make sure that transition actually happens, any client implementing this protocol SHOULD also implement IPv6, and should only use this solution when IPv6 isn't available to both peers. ๐ŸŒˆ

4.5. Existing Deployed NATs

Existing deployed NATs will not support this protocol. ๐Ÿฅฒ This protocol will only work with NATs that have been upgraded to support it. โญ

5. Security Considerations ๐Ÿ”

As discussed in Section 3.2, "Determining the External Address", only a client on the internal side of the NAT may create port mappings, and it may do so only on its own behalf. ๐Ÿ›ก๏ธ By using IP address spoofing, one client can delete the port mappings of another client. It's also possible for one client to create port mappings on behalf of another client. Where this is a concern, it can be dealt with using IPsec [RFC4301]. ๐Ÿ”’

The multicast announcements described in Section 3.2.1, "Announcing Address Changes", could be spoofed, which could facilitate a denial-of-service attack. ๐Ÿ˜ฑ This makes NAT-PMP unsuitable for use on LANs with large numbers of hosts where one or more of those hosts may be untrustworthy. ๐Ÿšฉ

Another concern is that rogue software running on a local host could create port mappings for unsuspecting hosts, which would make them vulnerable to external attack. ๐Ÿšจ However, it's not clear how realistic this threat model is. Rogue software on a local host could attack those unsuspecting hosts directly, without going through such a convoluted indirect technique. ๐Ÿ™„ This concern is also a little misguided, because it assumes a NAT gateway and a firewall are the same thing. They are not. ๐Ÿ’…

Some people see a NAT blocking inbound connections as a security benefit, and they feel this protocol undermines it. The authors of this document have a different point of view. โœจ Back before NAT became prevalent, every host had a unique public IP address and could communicate with any other host on the Internet without hindrance. (That configuration is still surprisingly common. ๐Ÿคญ) NAT breaks that unhindered connectivity, pushing hosts into second-class status where they can't receive inbound connections. This protocol goes some way toward partially reversing that damage. ๐Ÿฉน The purpose of a NAT gateway should be to let several hosts share a single address, not to also hold those hosts back from communicating freely. ๐ŸŒธ Security is best provided by end-to-end cryptographic security, and/or by explicit firewall functionality, as appropriate. ๐Ÿ” Blocking certain connections should only happen as a result of explicit, intentional firewall policy, not as an accidental side effect of some other technology. ๐Ÿ™…โ€โ™€๏ธ

Still, many users do expect their NAT gateways to work as a kind of firewall, so any NAT gateway implementing this protocol SHOULD have an administrative mechanism to disable it, restoring the pre-NAT-PMP behavior. ๐ŸŽ€

6. IANA Considerations ๐Ÿ“‹

UDP ports 5350 and 5351 have been assigned for use by NAT-PMP, and later by its successor, Port Control Protocol [RFC6887]. ๐Ÿงพ

No further IANA services are required by this document. โœ…

7. Acknowledgments ๐Ÿซถ

The concepts in this document were explored, developed, and implemented with help from Mark Baugher, Bob Bradley, Josh Graessley, Rory McGuire, Rob Newberry, Roger Pantos, John Saxton, Kiren Sekar, Jessica Vazquez, and James Woodyatt. ๐Ÿ’œ

Special credit goes to Mike Bell, the Apple Vice President who recognized the need for a clean, elegant, reliable Port Mapping Protocol, and made the early decision that Apple's AirPort base stations would support NAT-PMP. ๐Ÿ‘‘๐ŸŒˆ

8. Deployment History ๐ŸŽ€

okay so the NAT-PMP glow-up story is giving ๐Ÿฆ‹. In August 2004, NAT-PMP client software first became public through Apple's Darwin Open Source code. Then in April 2005 it started shipping to actual end users with Mac OS X 10.4 Tiger and Bonjour for Windows 1.0, and in June 2005 the protocol got its first public documentation in the original draft version of this document ๐Ÿ“„โœจ.

The NAT-PMP client in Mac OS X 10.4 Tiger and Bonjour for Windows lives inside the mDNSResponder/mdnsd system service ๐Ÿ’…. Here's the vibe: a client advertises a service using Wide Area Bonjour [RFC6763], the machine sits behind a NAT-PMP-capable NAT gateway, and the machine is set up for it. Then mDNSResponder automatically uses NAT-PMP to set up an inbound port mapping, and records the external IPv4 address and port in the global DNS ๐ŸŒ. Existing client software that used the Bonjour programming APIs [Bonjour] got this new NAT traversal power automatically, no extra work needed ๐Ÿ™Œ.

The logic was lowkey genius ๐Ÿง . If client software publishes its info into the global DNS through Wide Area Bonjour, then it's reasonable to expect that the info should actually be usable by whoever looks it up ๐Ÿ”. Recording a private IPv4 address like 10.0.0.2 in the public DNS is likely pointless, because clients on the other side of the NAT gateway can't reach that address ๐Ÿ™ˆ. Now picture a home user with one computer plugged straight into their Cable or DSL modem, with one global IPv4 address and no NAT gateway (super common back then ๐Ÿ•ฐ๏ธ). Publishing that machine's global IPv4 address in the global DNS is useful, because the address is globally reachable โœจ.

Meanwhile, a home user with a NAT gateway sharing one global IPv4 address between several computers loses the ability to receive inbound connections ๐Ÿ˜ญ. That breaks lots of peer-to-peer collaborative apps, like the multi-user text editor SubEthaEdit [SEE] ๐Ÿ’”. For many people, going from one computer with a global IPv4 address to two computers sharing one through NAT meant losing inbound reachability, and nobody wanted that side effect ๐Ÿฅฒ. Automatically creating the needed inbound port mappings helped fix that unwanted side effect of NAT ๐Ÿ’–.

The server side of NAT-PMP is built into Apple's AirPort Extreme, AirPort Express, and Time Capsule wireless base stations, and into the Internet Sharing feature of Mac OS X 10.4 and later ๐Ÿ“ก. Some third-party NAT vendors, like Peplink, offer NAT-PMP in their products too ๐Ÿซถ.

In Mac OS X 10.4 Tiger, the NAT-PMP client got invoked automatically as a side effect of clients requesting Wide Area Bonjour service registrations ๐Ÿช„. Using NAT-PMP without a Wide Area Bonjour service registration meant reaching for a third-party client library ๐Ÿ“š.

In October 2007, Mac OS X 10.5 Leopard added the DNSServiceNATPortMappingCreate API ๐ŸŽ. That made NAT-PMP client functionality directly available, so software could use it alongside other directory and rendezvous mechanisms, not just Wide Area Bonjour DNS Updates ๐ŸŽ‰.

In 2013, NAT-PMP got superseded by the IETF Standards Track Port Control Protocol [RFC6887] ๐Ÿ‘‘. PCP builds on NAT-PMP and uses a compatible packet format, but it levels up with a bunch of major upgrades: IPv6 support, management of outbound mappings, management of firewall rules, full compatibility with large-scale NATs that have a pool of external addresses, error lifetimes, and an extension mechanism for future enhancements ๐ŸŒˆ๐Ÿ”ฅ.


9. Noteworthy Features of NAT Port Mapping Protocol and PCP ๐Ÿ’œ

some readers have asked how NAT-PMP and PCP stack up against other similar solutions, especially the UPnP Forum's Internet Gateway Device (IGD) Device Control Protocol [IGD] ๐Ÿค”.

The answer is the tea โ˜•. The Universal Plug and Play (UPnP) IGD protocol is often used by client devices to create port mappings programmatically, but it's not ideal for that job ๐Ÿ™ƒ. NAT-PMP was explicitly designed for software entities managing their own port mappings. UPnP IGD is more about humans configuring every setting of their gateway through some GUI tool ๐Ÿ–ฅ๏ธ. That difference in emphasis leads to differences in the protocols ๐Ÿ’…. For example, it's reasonable and sensible to make software entities renew their mappings periodically to prove they're still there (kinda like a device renewing its DHCP address lease) ๐Ÿ”„. Requiring the same thing of a human user would be unreasonable ๐Ÿ™…โ€โ™€๏ธ. When a human configures their gateway, they expect it to stay that way until they decide to change it ๐Ÿซ . If they set up a port mapping, they expect it to stay until they decide to delete it ๐Ÿ—‘๏ธ.

Because UPnP IGD is a general administration protocol for every aspect of home gateway configuration, it's a large and complicated collection of protocols ๐Ÿ˜ตโ€๐Ÿ’ซ. We're talking 360 pages of specification spread over 13 separate documents, not counting supporting protocol specs like Simple Service Discovery Protocol (SSDP) and Extensible Markup Language (XML) ๐Ÿ“š๐Ÿ’€. It might be a fine way for humans to configure their home gateways, but it's not especially suited to programmatically creating dynamic port mappings ๐Ÿซถ.

The requirements for a good port mapping protocol, the ones NAT-PMP meets, are outlined below โœจ.

9.1. Simplicity ๐Ÿงธ

Lots of home gateways, and lots of the devices that connect to them, are small, low-cost devices with limited RAM, flash memory, and CPU resources ๐Ÿชซ. Protocols they use should be considerate of this, supporting a small number of simple operations that can be implemented easily with a small amount of code ๐Ÿงฉ. Based on page count of the respective documents alone, NAT-PMP is at least ten times simpler than UPnP IGD ๐Ÿ“‰. Literally the simplest glow-up ๐Ÿ’–.

9.2. Focused Scope ๐ŸŽฏ

The more things a protocol can do, the more chances there are for something it does to get exploited for malicious purposes ๐Ÿ˜ฌ. NAT-PMP is tightly focused on the specific task of creating port mappings ๐ŸŽฏ. If the protocol ever got misused, that focus limits how much mischief could be done with it ๐Ÿ›ก๏ธ.

UPnP IGD allows control over all home gateway configuration settings, so the potential for mischief is way bigger ๐Ÿšจ. For example, a UPnP IGD home gateway accepts messages that tell it to change the DNS server addresses it hands out to clients in its DHCP packets ๐Ÿ˜ฑ. With that, a single piece of malicious web content (like a rogue Flash banner ad on a web page) can make a persistent change to the home gateway's configuration without the user knowing. After that, every DNS request from every local client gets sent to a rogue DNS server ๐Ÿ’€. Criminals can then do all kinds of mischief, like hijacking connections to bank web sites and redirecting them to the criminals' own web servers instead [VU347812] ๐Ÿฆ๐Ÿšซ.

9.3. Efficiency โšก

Beyond low-cost home gateways, a lot of the clients will also be similarly constrained, low-cost devices with limited RAM ๐Ÿช™.

When you implement a NAT-PMP client on a constrained device, it's super helpful to have well-defined bounds on RAM requirements that are fixed and known in advance ๐Ÿ“. For example, when requesting the gateway's external IPv4 address, a NAT-PMP client on Ethernet knows exactly what it needs to receive the reply: 14 bytes for the Ethernet header, 20 bytes for the IPv4 header, 8 bytes for the UDP header, and 12 bytes for the NAT-PMP payload, for a total of 54 bytes ๐Ÿงฎโœจ.

UPnP IGD, on the other hand, uses an XML reply of unbounded size ๐Ÿซ . It's not uncommon for a UPnP IGD device to return an XML document between 4000 and 8000 bytes just to communicate its 4-byte external IPv4 address ๐Ÿคฏ. The protocol spec places no upper bound on how big the XML response can be, so nothing stops the reply from being even larger ๐Ÿ™ƒ. That means UPnP client developers can only guess how much memory they'll need for the XML reply ๐ŸŽฒ. Operational experience suggests 10,000 bytes is usually enough for most UPnP IGD home gateways today, but that's no guarantee that a future UPnP IGD gateway won't send a perfectly legal XML reply much bigger than that ๐Ÿ˜ฐ.

On top of that, because the XML reply is too big to fit in a single UDP packet, UPnP IGD has to use a TCP connection, which adds the overhead of TCP connection setup and teardown ๐Ÿงฑ.

Discovering a UPnP IGD home gateway's external IPv4 address goes through these steps:

  • SSDP transaction to discover the TCP port to use, and the "URL" of the XML document to fetch from the gateway. Following the SSDP specification, this is 3 multicast requests, eliciting 9 unicast responses.
  • HTTP GET request to get the device description. Typically, 16 packets: 3 for TCP connection setup, 9 packets of data exchange, and a 4-packet FIN-ACK-FIN-ACK sequence to close the connection.
  • HTTP POST to request the external IPv4 address. Typically, 14 packets: 3 for TCP connection setup, 7 packets of data exchange, and a 4-packet FIN-ACK-FIN-ACK sequence to close the connection.

To grab the external IPv4 address, NAT-PMP takes a 2-packet UDP exchange (44-byte request, 54-byte response) ๐Ÿƒโ€โ™€๏ธ๐Ÿ’จ. The same thing using UPnP IGD takes 42 packets and thousands of bytes ๐Ÿ˜ค.

Similarly, UPnP IGD's HTTP POST request for a port mapping is typically a 14-packet exchange, compared with NAT-PMP's 2-packet UDP exchange ๐Ÿ”ฅ.

9.4. Atomic Allocation Operations ๐ŸŽ€

okay so NAT-PMP got some of its best ideas from DHCP, which is literally the most reliable protocol ever ๐Ÿซถ DHCP lets a client ask for a specific IP address, and if that address is already taken, the server just hands out a different free one instead. no drama, no crash, just a new address ๐Ÿ’…

NAT-PMP does the same thing with ports. If a client asks for a particular external port and another client is already using it, the NAT-PMP server quietly assigns some other free external port. the gateway knows which ports are free, so it does the picking. iconic behaviour โœจ

UPnP IGD does NOT do this ๐Ÿ’€ If a UPnP IGD client asks for an external port that's already allocated, one of two things happens.

Some UPnP IGD home gateways just silently overwrite the old mapping with the new one ๐Ÿ˜ญ The previous client suddenly loses connectivity. If that client renews its mapping, it overwrites the new one right back, and the two clients end up fighting over the same external port forever, and neither one ever gets reliable connectivity. not it ๐Ÿ™ˆ

Other IGD home gateways return a "Conflict" error when the port is in use. at least the client finds out what happened, but nobody tells it what to do ๐Ÿฅฒ The gateway actually knows which ports are free, but instead of picking one for the client, it makes the client (which has no clue) keep guessing until it gets lucky. this is mild while not many clients use UPnP IGD, but it gets worse and worse as more clients on the network ask for port mappings. ๐Ÿ“‰

It gets even messier with the emerging policy of giving each client its own pre-assigned port range. say a client has TCP port range 63488-64511, and its UPnP IGD client wants TCP port 80. If it tries successive incrementing ports until one works, it'll have to issue 63,409 requests before it succeeds. 63,409 requests just to get port 80?? ๐Ÿ˜ฉ no thank you ๐ŸŒธ

9.5. Garbage Collection ๐Ÿ—‘๏ธ

okay so any system that runs for a long time (like a home gateway should) needs to not let garbage pile up forever. if it does, it runs out of memory and dies ๐Ÿ’€ nobody wants that, bestie ๐ŸŽ€

NAT-PMP handles this the same way DHCP does with IP addresses: it leases an external port to a client for a finite amount of time ๐Ÿฆ‹ The client has to renew the port mapping before it expires, or it gets reclaimed, just like an unrenewed DHCP address. so if a laptop gets abruptly disconnected from the network without getting the chance to delete its port mappings, the NAT gateway reclaims them once they aren't renewed. clean ๐Ÿงนโœจ

In principle, UPnP IGD is supposed to let clients specify a lifetime on port mappings. but a Google search for "UPnP NewLeaseDuration" shows that in practice basically every client uses <NewLeaseDuration>0</NewLeaseDuration> to ask for an infinite lease ๐Ÿ˜ญ and the protocol has no way for the NAT gateway to say no to that infinite lease and make the client renew at reasonable intervals. no cap, that's a big problem ๐Ÿ™ˆ

It gets worse. anecdotal evidence says that if a client asks for a lease that isn't zero, some IGD home gateways ignore the request, fail in other ways, or even crash completely ๐Ÿ’€ So as a client implementer, you'd be well advised not to request a lease other than zero, unless you're into suffering the support costs and bad publicity of tons of people complaining that your device brought down their entire network. just saying ๐Ÿซ 

Here's the tea ๐Ÿต None of the early UPnP IGD clients requested port mapping leases, so lots of UPnP IGD home gateway vendors never tested that feature. they got away with shipping gateways where it was buggy or didn't exist at all. and because there are so many buggy UPnP IGD gateways already out there, client writers wisely stick to the well-trodden path of only requesting infinite leases. then, since there are now few (if any) clients asking for non-zero leases, home gateway vendors have little incentive to spend resources building a feature nobody uses. it's a whole loop ๐Ÿ”

So this unfortunate result of how UPnP IGD was developed and deployed means that, in practice, it has no usable port mapping lease facility today. when a UPnP IGD home gateway runs for a long time, it has no good way to avoid piling up an unbounded number of stale port mappings ๐Ÿ“š๐Ÿ’€

9.6. State Change Announcements ๐Ÿ“ฃ

okay so most home gateways get their external interface address through DHCP, and with DHCP there's no guarantee that a UPnP IGD home gateway's external IPv4 address stays the same ๐Ÿ˜ฌ some ISPs even change their customers' IPv4 address every 24 hours (maybe to make it harder for people to "run a server" at home). ๐Ÿ™ƒ

What this means is that if the gateway's external IPv4 address changes, it needs to tell its clients, so they can make any updates they need to global directory information. for example, they might do a Dynamic DNS update to refresh their address record ๐ŸŒโœจ

When a NAT-PMP gateway's external IPv4 address changes, it broadcasts announcement packets to tell clients about it. UPnP IGD doesn't do this ๐Ÿ’…

9.7. Soft State Recovery ๐Ÿงš

okay so when any network runs long enough, devices are going to fail, get rebooted, suffer power outages, or lose state for other reasons ๐Ÿ˜ฉ a home gateway that runs long enough will probably have one of these incidents eventually. after it loses state, it has no record of the port mappings it created, and the clients get a loss of connectivity as a result ๐Ÿ’”

NAT-PMP has a fix for this, the "Seconds Since Start of Epoch" mechanism ๐Ÿ™Œ After a reboot or other state loss, a NAT-PMP gateway broadcasts announcement packets giving its external IPv4 address, with the Seconds Since Start of Epoch field reset so it starts counting from zero again. when a NAT-PMP client sees packets from its gateway where the gateway's notion of time has apparently gone backwards compared to the client's, the client knows the gateway has probably lost state. so it immediately recreates its mappings and gets connectivity back. main character recovery arc ๐Ÿฆธโ€โ™€๏ธ๐Ÿ’–

UPnP IGD has no equivalent mechanism ๐Ÿฅฒ

9.8. On-Path NAT Discovery ๐Ÿ›ค๏ธ

okay so for any given host, it's only useful to request NAT port mappings from the NAT gateway that the host's packets are actually flowing through ๐ŸŽฏ a NAT port mapping is a request for packets to be translated in a certain way, and the gateway can only do that translation if it's really forwarding inbound and outbound packets for that host. makes sense, right? ๐Ÿง 

This is why NAT-PMP sends its requests to the host's default router, since that's the device forwarding (and possibly translating) inbound and outbound packets for that host. (In a larger network with multiple hops between a host and its NAT gateway, some other mechanism would need to be used to discover the correct on-path NAT for a host. that's possible, but it's outside the scope of this document ๐Ÿงญ)

UPnP IGD, on the other hand, doesn't limit itself to on-path NATs ๐Ÿ™ƒ It uses a multicast SSDP query and uses ANY device it finds on the local network that claims UPnP IGD capability, whether or not any inbound or outbound traffic is actually flowing through it. over the past few years this led to a ton of bug reports sent to Apple with the general vibe of: "Port Mapping doesn't work on my Mac and that's a bug because everything else on my network says UPnP IGD is working fine." ๐Ÿ˜ญ

Upon investigation, it always turned out that: (i) these people had NAT gateways that either didn't support port mapping requests or had that capability disabled, and (ii) for some reason they also had some other old NAT device still connected to their network, and those other NAT devices were advertising UPnP IGD capability even though they weren't the active NAT gateway for the network. ๐Ÿซ  This led to UPnP IGD clients falsely reporting that they were "working fine", while only the Mac correctly reported that it couldn't make any useful port mappings. it's giving misinformation, honestly ๐Ÿ’€

In lots of cases, the people reporting this "bug" had devices like game consoles on their home network that had been reporting that UPnP IGD was "working fine" for years ๐ŸŽฎ yet during all those years they had never once successfully received any inbound network packet or connection. the irony is that, for these people reporting bugs to Apple, UPnP IGD "working fine" was indistinguishable from UPnP IGD doing nothing useful at all ๐Ÿ™ˆ It was only when Back to My Mac [RFC6281] started reporting that it couldn't make any functional port mappings that these people found out they had never had any working port mappings on their NAT gateway. ๐Ÿ˜ฑ๐Ÿ’…

10. References ๐Ÿ“š

10.1. Normative References ๐Ÿซถ

[RFC1918]  Rekhter, Y., Moskowitz, B., Karrenberg, D., de Groot, G.,
           and E. Lear, "Address Allocation for Private Internets",
           BCP 5, RFC 1918, February 1996.

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119, March 1997.

10.2. Informative References ๐Ÿ’œ

[Bonjour]  Apple "Bonjour" <http://developer.apple.com/bonjour/>.

[ETEAISD]  J. Saltzer, D. Reed and D. Clark: "End-to-end arguments in
           system design", ACM Trans. Comp. Sys., 2(4):277-88,
           November 1984.

[IGD]      UPnP Standards "Internet Gateway Device (IGD) Standardized
           Device Control Protocol V 1.0", November 2001,
           <http://www.upnp.org/standardizeddcps/igd.asp>.

[RFC2131]  Droms, R., "Dynamic Host Configuration Protocol", RFC
           2131, March 1997.

[RFC2663]  Srisuresh, P. and M. Holdrege, "IP Network Address
           Translator (NAT) Terminology and Considerations", RFC
           2663, August 1999.

[RFC3007]  Wellington, B., "Secure Domain Name System (DNS) Dynamic
           Update", RFC 3007, November 2000.

[RFC3022]  Srisuresh, P. and K. Egevang, "Traditional IP Network
           Address Translator (Traditional NAT)", RFC 3022, January
           2001.

[RFC3424]  Daigle, L., Ed., and IAB, "IAB Considerations for
           UNilateral Self-Address Fixing (UNSAF) Across Network
           Address Translation", RFC 3424, November 2002.

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

[RFC6281]  Cheshire, S., Zhu, Z., Wakikawa, R., and L. Zhang,
           "Understanding Apple's Back to My Mac (BTMM) Service", RFC
           6281, June 2011.

[RFC6763]  Cheshire, S. and M. Krochmal, "DNS-Based Service
           Discovery", RFC 6763, February 2013.

[RFC6887]  Wing, D., Ed., Cheshire, S., Boucadair, M., Penno, R., and
           P. Selkirk, "Port Control Protocol (PCP)", RFC 6887, April
           2013.

[SEE]      SubEthaEdit, <http://www.codingmonkeys.de/subethaedit/>.

[VU347812] United States Computer Emergency Readiness Team
           Vulnerability Note VU#347812,
           <http://www.kb.cert.org/vuls/id/347812>.

Authors' Addresses ๐Ÿ–‹๏ธ

Stuart Cheshire
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
USA

EMail: cheshire@apple.com

Marc Krochmal
Apple Inc.
1 Infinite Loop
Cupertino, CA 95014
USA

EMail: marc@apple.com

And that's the whole spec, bestie! ๐ŸŒˆโœจ we made it ๐Ÿ‘‘๐Ÿฆ‹

๐Ÿ“ฆ where this page comes from