Browser vendors migrated the web from http to https in the mid-2010s. That 's' adds encryption via TLS, which is great.
However, https also adds:
WebRTC Direct restores the freedom to talk to cryptographic identities instead of just those with authority-controlled names.
ufrag it sees in the incoming STUN request. No signalling.
/certhash/… is the SHA-256 of the server's
self-signed TLS cert (verified during DTLS, no CA required), and
/p2p/12D3Koo… is the server's libp2p identity, proven via
a Noise XX handshake inside the first data channel.
Everything above removes authority requirements from the server. But the browser app itself is still hosted somewhere — in this case on GitHub Pages — which requires https, which requires a CA-signed cert for a registered domain. That's the last authority-controlled link in the chain between you and the server.
A Chromium extension build of the same app loads from
chrome-extension://<id>/: trusted at
install time rather than by a public CA. Build it yourself
with npm run build:extension in the
web/ directory and load
dist-extension/ as an unpacked extension. Now
neither the page nor its connection to the server depends
on a domain registrar or a certificate authority.
The transport is the point; this demo bolts two example services onto it, both speaking libp2p stream protocols.
/chat/1.0.0) — a public
bulletin plus end-to-end encrypted direct messages. Each
client's DM key is signed by their libp2p identity, so the
server can route messages but can't read or forge DMs.
/eth-rpc/1.0.0) — the
server proxies JSON-RPC calls to curated public endpoints for
Ethereum, Arbitrum, Optimism, Base, and Polygon; the browser
renders a small live explorer from the responses. The server
sees your queries; the public RPC endpoints only see the
server's IP.
/certhash/..., alongside its IP, UDP port, and libp2p peer ID.No domain. No certificate authority. No signalling relay. If the multiaddr reached you intact, the connection cannot be intercepted.
Needs Node.js 22+. Clone this repo, then:
cd server
npm install
npm start
The server prints one listen multiaddr per reachable network interface. Each looks like:
/ip4/192.168.1.50/udp/41108/webrtc-direct/certhash/uEi.../p2p/12D3Koo...
On first run the server writes its peer key, TLS cert
(200-year lifespan), and picked UDP port into
state.json. Every piece of the multiaddr — IP,
port, certhash, peer ID — stays identical across restarts. If
the saved port is already taken on a later start, the server
errors out rather than silently breaking the saved multiaddr.
WebRTC Direct is just UDP underneath. The browser must be able to reach the server's UDP port directly, so pick the address that matches where you are:
127.0.0.1 line.192.168.x.x, 10.x.x.x).