How devices find each other across the internet — from first principles, with live demos.
Your home network probably has a phone, a laptop, maybe a smart TV, a tablet, a game console. Each one talks to the internet. But your Internet Service Provider gave your household just one public IP address.
So how does a reply from Netflix know to reach the TV and not your laptop? That's the job of your router — and the trick it uses is called Network Address Translation, or NAT.
Let's watch it work.
▸ Try clicking each device. Watch how the router rewrites the source address before the packet leaves your network.
Every outbound packet gets its return address rewritten. Your device's private IP (like 192.168.1.5) becomes the router's public IP plus a port number the router picks. The server never sees your private address — it just sees the router.
The router's secret weapon is a simple table. Every time a device sends a packet out, the router creates an entry: "private IP:port → public IP:assigned port → destination." When a reply comes back, it looks up the assigned port to figure out which device to forward it to.
Let's build a NAT table from scratch.
▸ Try creating several connections. Notice how each one gets a unique external port — that's the only thing distinguishing these devices from the outside.
From the server's perspective, all it sees is 203.0.113.50:48721 or 203.0.113.50:48722. It has absolutely no idea there are multiple devices behind that IP. The port is the only differentiator — and the mapping between port and device is known only to the router.
This works beautifully for outbound connections. Your laptop asks for a webpage, the router tracks it, the reply flows back. Simple.
But there's a catch.
What happens if someone on the internet wants to reach your laptop without your laptop sending anything first?
They send a packet to your public IP. It arrives at your router. The router looks up the destination port in its NAT table… and finds nothing. No device ever created a mapping for that port. So the router does the only sensible thing: it drops the packet.
Try it yourself.
▸ First, try sending to any port — watch it get dropped. Then click "laptop sends out" to create a mapping, and try that port again.
This is exactly why peer-to-peer connections are hard. If your friend wants to connect to your Minecraft server, their packet arrives at your router, and the router says: "I have no idea who this is for." Dropped.
Both players are behind NATs. Both routers are dropping unsolicited packets. Neither side can reach the other. It's a standoff.
So how do we trick it?
Before two peers can connect, each needs to know a crucial piece of information: their own external address. From behind a NAT, you can't see what IP and port the outside world sees — your device only knows its private IP.
The solution is almost embarrassingly simple. You send a packet to a public server, and the server tells you what address the packet came from. It's like calling someone and asking: "Hey, what number showed up on your caller ID?"
This is called STUN — Session Traversal Utilities for NAT. Let's watch it work.
▸ Watch the packet go out, get rewritten by NAT, and the STUN server reflect the external address back.
The STUN server does almost nothing — it just mirrors your packet's source address back to you. But now you know something you couldn't know before: what you look like from the outside.
This is the first ingredient of the trick. Both peers learn their external IP:port via STUN. Now they need a way to share this info with each other.
Here's where it gets clever. We know that sending a packet out creates a NAT mapping. And we know that once a mapping exists, packets coming in to that port will be forwarded. So what if both peers send packets to each other at the same time?
The process works in five steps. Let's walk through each one.
▸ Step through each phase. Pay attention to how each outbound packet "punches a hole" in its own NAT — and how the other peer's packet eventually finds that hole.
The magic moment is step 4. Peer A's packet arrives at NAT B, and for the first time, there's a mapping waiting for it — because Peer B just sent a packet to Peer A, which created that mapping. The hole has been punched.
Once the first packet makes it through in each direction, both NATs have active mappings. The peers can now talk directly — no middleman, no relay. Just two devices, across the internet, as if the NATs weren't there.
Hole punching doesn't always work. It depends on how strict each router's NAT is. There are several types, and each one is more paranoid than the last.
▸ Toggle between NAT types. Watch how each one applies stricter rules about which incoming packets it allows through.
Full Cone is the most relaxed: once a mapping exists, anyone can send packets to that external port. Hole punching works easily.
Address-Restricted adds a check: the incoming packet's source IP must match the IP the mapping was created for. You can only receive from IPs you've already sent to.
Port-Restricted goes further: both the IP and the port must match. Hole punching still works because both peers send to each other's exact endpoint.
Symmetric NAT is the killer. It assigns a different external port for every destination. So the port that the STUN server sees is not the same port that Peer B would see. The address you learned from STUN is useless — the peer can't predict which port to send to.
When hole punching fails, there's a fallback: a TURN server (Traversal Using Relays around NAT). This is just a public server that both peers connect to, which relays packets between them. It always works, but adds latency and costs bandwidth — the traffic goes through a middleman instead of flowing directly.
Every time you make a video call, play an online game, or use a VPN, this machinery is running under the hood. Here's the decision tree that systems like WebRTC use:
WebRTC — the technology behind Google Meet, Discord voice chat, and screen sharing — uses exactly this process. It's called ICE (Interactive Connectivity Establishment): try direct first, then STUN + hole punch, then fall back to TURN relay.
Tailscale and WireGuard take a similar approach for VPN connections. Tailscale's coordination servers act as the rendezvous point, and they implement hole punching automatically. When it works, your VPN traffic flows directly between devices. When it doesn't, it routes through relay servers they call DERP (Designated Encrypted Relay for Packets).
Game servers usually skip the complexity entirely — they use a public server with a known address. That's why you port-forward for Minecraft: you're creating a permanent NAT mapping so players can find your machine. Services like Playit.gg and Ngrok create a tunnel from your machine to a public relay, avoiding port forwarding at the cost of routing everything through their infrastructure.