Every tunnel endpoint needs an address and a port that the other side can reach, and a router you do not administer is the usual reason that requirement fails. The interesting part is not that tricks exist, but that each one depends on a property of a mapping table you cannot see from the client. Two of those properties decide almost everything: how a mapping gets created, and whether it accepts packets from an address the inside never contacted. Sort the environment by those properties and the workarounds stop being folklore.

The mapping table decides everything

Network address translation keeps a table in which an internal address and port are recorded against a public address and port. Replies that match a record are translated back, and a packet arriving from outside with no matching record has no destination at all. That single behaviour explains why a listener behind the router is unreachable from the internet. It also explains why the first packet in each direction has to originate inside.

Look at the table from the router's side and the workarounds become obvious: either something creates a permanent entry, something creates a temporary one and keeps it fresh, or the traffic never takes that path at all. The rest of this article is those three cases in order. Nothing here depends on a vendor feature beyond what the table records.

What the rendezvous service can and cannot do

UDP hole punching uses the outbound record as a temporary opening rather than defeating the filter. Both peers contact a rendezvous service, which learns each public endpoint and reports the other side's endpoint back. Then both send toward each other, and each outbound packet creates or refreshes the record that lets the reply in. The ordering is what makes it work, and the ordering is also what makes it fragile: a peer that sends before the other side has created its record is simply dropped, while a retry a moment later succeeds. The service itself carries no VPN traffic, so its only leverage is the timing it coordinates.

Mapping behaviour decides the rest, and RFC 4787 names the three shapes: endpoint-independent, address-dependent, and address-and-port-dependent. Under the last of those, the port a peer must target changes with every destination, so prediction stops being reliable. That is where the technique meets its dead ends, because carrier-grade NAT and a strict corporate firewall both remove the predictability the scheme needs, and no amount of retrying brings it back.

Keepalives, reboots and the endpoint that moves

A punched path is a flow rather than a listener, so whatever runs on top of it has to survive change. It must keep the mapping alive with periodic traffic, notice when the public endpoint moves, and re-establish after the router reboots or the address is reassigned. Mesh VPN products put that logic in their own control plane, while a plain server leaves it to you. Keepalives help only while the same mapping survives, and they cost battery on a mobile client, which is why an aggressive interval is not free.

A laptop that sleeps for an hour usually comes back on a different public endpoint. Whatever re-establishes the path has to run again from the inside, which puts the same requirement back on the client.

Three ways around a missing forward

The first way asks the router to create the entry itself, through UPnP IGD, NAT-PMP or PCP, when the feature exists and is switched on. The second hands the traffic to a relay with a public address, which always works and always costs bandwidth plus a different trust boundary. The third inverts the direction: the internal host opens an outbound tunnel to a public server and everything else rides inside it.

[Peer]
PublicKey = 6yGj3kQ2wVb8sTn1pLx4dRc7hZa9mKf2uYe5oNq0iXw=
Endpoint = relay.corp.internal:51820
PersistentKeepalive = 25
AllowedIPs = 10.44.0.0/24

A relay endpoint makes that trade visible in the client configuration, where the endpoint is a relay rather than a peer's own address. Persistent keepalive keeps the mapping warm, and the allowed prefixes decide what the client may send across it. A reverse tunnel from the internal host is the same idea with a different owner, and it needs no NAT change at all. Each of the three removes the inbound requirement without defeating a firewall that blocks unsolicited traffic by design, because the traffic still starts inside.

Match the workaround to who owns the router

If you administer the router, a static UDP forward is simpler to audit than any punching scheme and fails in ways you can see. If you do not, find out whether the vendor offers a relay or a hosted control plane, and whether policy would allow using one. If neither is available, the remaining choices are a reverse tunnel or accepting that the endpoint is not reachable from outside. Recording which one you used matters more than it sounds, because the options differ in who can observe the traffic and what happens when a third party changes something.

Note whether the path you ended up with was direct or relayed, since that single fact predicts both latency and failure behaviour. RFC 4787 remains the reference for the mapping behaviour underneath all of it, and reading its mapping section is faster than testing three workarounds in sequence. The table does not care which option you chose; it only records what the next packet is allowed to do.

Zvinyorwa zvakafanana