webrtc-direct
Crate for connecting a Browser to a Server directly using WebRTC without requiring a TLS cert / domain name from the Server or requiring intermediary TURN servers.
Why
Traditional WebRTC requires signaling servers and TURN relays. This is centralized infrastructure which creates single points of failure.
Using webrtc-direct a browser can directly connect to any server that publishes its IP and fingerprint. This makes it practical to build decentralized P2P networks where browsers talk directly to nodes without depending on external services.
How it works
Based on libp2p WebRTC Direct
- The server generates a DTLS key and derives a SHA-256 fingerprint from its certificate
- The fingerprint is shared with the client (embedded in HTML, fetched from an endpoint, hardcoded)
- The browser constructs an SDP offer locally, generates the SDP answer itself using the server IP + fingerprint, and initiates a direct DTLS connection
- The server uses ICE lite (no candidate gathering) and accepts the connection on a single UDP port
- A negotiated DataChannel (ID 0) opens without any channel negotiation signaling needed
Crates
| Crate | Description |
|---|---|
webrtc-direct-server |
WebRTC server |
webrtc-direct-client |
Browser WASM client |
webrtc-direct-protocol |
Shared protocol |
Quick start
Server (native Rust)
use ;
use SocketAddr;
async
Client (browser WASM)
use ;
use SocketAddr;
// server_fingerprint_hex: obtained from the server (for example fetched from an HTTP endpoint or embedded inside the HTML)
let addr: SocketAddr = .into;
let fingerprint = from_hex;
let raw = connect.await.unwrap;
let client = new;
client.send.unwrap;
let response = client.recv.await.unwrap;
Full working example
See example/ for a complete runnable echo demo with server, WASM client, and browser frontend. To run:
&&
Requirements
- Rust 1.85+ (edition 2024)
- For the client:
wasm-pack,wasm32-unknown-unknowntarget
License
MIT