DEV Community

Aniket Misra
Aniket Misra

Posted on

The Dark Art of UDP Hole Punching: How to Build a Serverless Web

If you want to build a truly decentralized application—one that doesn't rely on AWS, Vercel, or a centralized RPC node—you immediately run into a brick wall of network physics.

You want User A to talk directly to User B.
The problem? Neither of them has a public IP address.

Because we ran out of IPv4 addresses decades ago, ISPs placed almost every consumer device on earth behind a NAT (Network Address Translation) router. NAT is a one-way mirror. You can send outbound requests to a public server, and the router will allow the response back in. But if an external device tries to initiate a connection with you, the NAT drops the packet immediately. It assumes it is hostile.

This single piece of hardware killed the peer-to-peer internet.

To build a sovereign, serverless application layer (like what Holepunch and Pear are doing), you have to bypass the NAT. You have to trick the router into letting inbound traffic through. This technique is called UDP Hole Punching.

Here is the architectural deep dive into how it works, and how modern cryptographic routing makes it scalable.


1. The Mechanics of the "Hole Punch"

Unlike TCP, which requires a rigid 3-way handshake, UDP is connectionless. It just fires raw datagrams into the void.

When your laptop sends a UDP packet to an external server, your NAT router intercepts it, temporarily maps your local IP/port to its public IP/port, and adds a record to its State Table. For the next 30 to 60 seconds, it leaves a "hole" open. If any UDP packet hits that specific public port, the NAT assumes it is a valid response and forwards it to your laptop.

If Alice and Bob are both behind strict NATs, they cannot ping each other. But if they coordinate, they can exploit the state table.

  1. The Signaling Phase: Alice and Bob both connect to a third-party relay to discover their own respective public IP addresses and ports.
  2. The Simultaneous Strike: Alice fires a UDP packet directly at Bob's public IP. Bob fires a UDP packet directly at Alice's public IP.
  3. The Rejection: Alice's first packet hits Bob's router and gets instantly dropped, because Bob's router hasn't opened a hole yet.
  4. The Breakthrough: But when Alice fired that packet, her router opened a hole, expecting a response from Bob's IP. A millisecond later, Bob's packet arrives at Alice's router. Because the IP and port match the state table, the router lets it through.

The hole is punched. Alice and Bob now have a direct, peer-to-peer data stream.

[Alice's Laptop] ──► (Local Port 3000)
       │
 [Alice's NAT] ────► Opens Hole: Public IP A, Port 50000 
       │ 
       ▼ (Direct UDP Stream) ▲
       │                     │
 [Bob's NAT] ◄─────► Opens Hole: Public IP B, Port 60000
       │
[Bob's Laptop] ◄─── (Local Port 4000)
Enter fullscreen mode Exit fullscreen mode

2. The Holepunch Architecture: Cryptographic Routing

In traditional WebRTC architecture, the "Signaling Phase" requires centralized infrastructure: STUN servers (to find your public IP) and TURN servers (to relay traffic if hole punching fails). If you use STUN/TURN, you are back to relying on centralized cloud providers.The brilliance of the Holepunch stack (and its underlying engine, Bare) is that it throws out STUN and TURN entirely. Instead, it uses HyperDHT, a Kademlia-based Distributed Hash Table. In this architecture, your public cryptographic key is your IP address.

1.When Alice boots her application, she joins the DHT. The decentralized nodes in the DHT naturally observe her public IP and port, effectively doing the job of a STUN server without corporate ownership.

2.She announces her 32-byte public key (ed25519) to the swarm.
3.When Bob wants to connect, he doesn't query a DNS server. He searches the DHT for Alice's public key.
4.The DHT nodes coordinate the UDP hole punch. Once the connection is established, Alice and Bob perform a Noise IK handshake to generate a direct, end-to-end encrypted tunnel.

Visit documentation

3. The Code: Bare-Metal P2P

Because Holepunch uses the Bare runtime (stripping away Node.js's heavy HTTP server legacy), establishing this encrypted, serverless connection takes mere lines of code.

Here is what establishing a serverless, hole-punched P2P connection looks like using hyperdht:
Alice (The Target):

import DHT from 'hyperdht'

const node = new DHT()
const keyPair = DHT.keyPair() // Cryptographic identity

const server = node.createServer(socket => {
  console.log('Direct encrypted P2P stream established!')

  // The socket is a standard duplex stream. 
  // No server required.
  process.stdin.pipe(socket).pipe(process.stdout)
})

await server.listen(keyPair)
console.log('Listening on Public Key:', keyPair.publicKey.toString('hex'))
Enter fullscreen mode Exit fullscreen mode

Bob (The Dialer):

import DHT from 'hyperdht'

const node = new DHT()
const alicePubKey = Buffer.from('<ALICE_PUBLIC_KEY_HEX>', 'hex')

// The DHT locates Alice, orchestrates the UDP hole punch, 
// and establishes the Noise IK encrypted tunnel natively.
const socket = node.connect(alicePubKey)

socket.on('open', () => {
  console.log('Punched through NAT. Connected to Alice.')
})

process.stdin.pipe(socket).pipe(process.stdout)
Enter fullscreen mode Exit fullscreen mode

The Unstoppable Web

By utilizing UDP hole punching and a cryptographic DHT, you remove the ultimate single point of failure in modern architecture: the data center.

You cannot DDoS a network where every user is dynamically routing traffic. You cannot de-platform an application that has no static IP to block. When we talk about true decentralization, it isn't just about putting a financial ledger on a blockchain; it is about reclaiming the physical routing layer of the internet.

Top comments (0)