What Is the iroh API? A Complete Guide to Peer-to-Peer Networking in Rust
The iroh API is a Rust library that provides a high-level, peer-to-peer networking stack built on QUIC, abstracting away hole-punching, relay fallback, address discovery, and TLS-based authentication behind ergonomic types like Endpoint and Builder.
The iroh API serves as the public interface for the n0-computer/iroh repository, enabling Rust applications to establish secure, direct connections between devices across the internet without manual firewall configuration or complex infrastructure management. It exposes a concise set of methods that handle the underlying complexities of modern peer-to-peer communication while maintaining type safety and performance.
Core Concepts of the iroh API
Endpoint
The Endpoint is the central object representing a local iroh node. According to the source code in iroh/src/lib.rs (lines 82-86), it owns the cryptographic key pair, manages socket bindings, handles address lookup, and controls the QUIC transport layer. All network operations flow through this type.
Builder Pattern
Configuration follows a fluent Builder API defined in iroh/src/endpoint.rs (lines 22-30). This pattern allows you to set secret keys, ALPN protocols, relay modes, and custom transports before calling bind() to initialize the endpoint.
Identity and Authentication
Each node is identified by an EndpointId (also referred to as PublicKey), which represents the public portion of the node's secret key. As documented in iroh/src/lib.rs (lines 84-90), this identifier serves as both the network identity and the basis for TLS authentication, eliminating the need for traditional certificate authorities.
Relay Infrastructure
When direct connectivity fails, the API falls back to RelayUrl endpoints. The default configuration uses the "number 0" relay (see iroh/src/lib.rs lines 96-103), though custom relays can be specified via the builder to handle traffic forwarding when direct paths are unavailable.
Address Lookup Services
The API supports optional address discovery mechanisms like DNS-based PKARR, documented in iroh/src/lib.rs (lines 60-70). These services publish an EndpointId alongside reachable addresses, allowing peers to connect using only the cryptographic identifier without knowing IP addresses beforehand.
QUIC Streams
Once connected, applications communicate through lightweight QUIC streams. The stream API in iroh/src/lib.rs (lines 36-44) provides bidirectional (open_bi) and unidirectional (open_uni) variants that are inexpensive to create and can be multiplexed arbitrarily over a single connection.
How the iroh API Establishes Connections
The connection process implemented in the iroh API follows a specific sequence that combines multiple networking techniques:
-
Endpoint Construction – Calling
Endpoint::builder(preset).bind().awaitcreates aBuilder, applies a configuration preset (e.g.,presets::N0), and binds sockets plus QUIC configuration. The logic inBuilder::bind(iroh/src/endpoint.rslines 24-30) generates aSecretKeyautomatically if none is supplied. -
Relay Discovery – If a direct address is unknown, the endpoint contacts its home relay (default "number 0" as described in
iroh/src/lib.rslines 97-104). The relay forwards encrypted packets based on the remoteEndpointIduntil a direct path is established. -
Hole-Punching – After the initial relay-mediated handshake, both endpoints attempt direct UDP connectivity via hole-punching techniques. As noted in
iroh/src/lib.rs(lines 66-73), successful hole-punching causes traffic to switch to the direct path, removing the relay from the data path. -
TLS Authentication – Each endpoint authenticates the other by verifying the peer's public key (the
EndpointId). According toiroh/src/lib.rs(lines 81-89), no traditional client/server certificates are used; the secret key of each endpoint serves as both identity and TLS key material. -
Stream Creation – With the QUIC connection ready, applications open streams via
Connection::open_biorConnection::open_uni. These methods, referenced iniroh/src/lib.rs(lines 36-44), create inexpensive streams that can be opened at any time during the connection lifetime.
Working with the iroh API: Code Examples
Basic Endpoint Workflow
This example demonstrates creating an endpoint, connecting to a remote peer, and exchanging data over a bidirectional stream:
// 1️⃣ Build and bind an endpoint (using the default N0 preset)
let ep = iroh::Endpoint::builder(iroh::endpoint::presets::N0)
.alpns(vec![b"my-alpn".to_vec()]) // accept this ALPN
.bind()
.await?; // ← binds sockets, creates QUIC config
// 2️⃣ Connect to a remote peer (you need the remote EndpointId)
let remote_addr = iroh::EndpointAddr::from_parts(
remote_endpoint_id, // the peer’s public key
None, // optional RelayUrl
vec![]); // optional direct IPs
let conn = ep.connect(remote_addr, b"my-alpn").await?;
// 3️⃣ Open a bidirectional stream and exchange data
let (mut send, mut recv) = conn.open_bi().await?;
send.write_all(b"ping").await?;
send.finish()?; // finish sending side
let reply = recv.read_to_end(64).await?;
assert_eq!(&reply, b"pong");
// 4️⃣ Gracefully shut down
conn.close(0u32.into(), b"bye");
ep.close().await;
Address Lookup with PKARR
This example shows how to enable DNS-based address discovery, allowing peers to find each other without sharing IP addresses:
use iroh::endpoint::presets::N0;
use iroh::address_lookup::DnsAddressLookup;
// Build an endpoint that publishes its ID via DNS (pkarr) and discovers peers
let ep = iroh::Endpoint::builder(N0)
.address_lookup(DnsAddressLookup::default()) // enable DNS-based lookup
.bind()
.await?;
The address_lookup service publishes the endpoint's EndpointId together with any discovered external addresses, allowing other peers to dial using only the cryptographic identifier.
Key Source Files in the iroh API
Understanding the repository structure helps when navigating the iroh API implementation:
iroh/src/lib.rs– Re-exports the public API (Endpoint,RelayUrl, etc.) and contains the high-level documentation describing architecture and usage patterns.iroh/src/endpoint.rs– Implementation ofEndpoint, itsBuilder, connection logic, and public methods includingconnect,accept, andadd_external_addr.iroh/src/socket/*.rs– Low-level transport and path-selection code handling IP transports, relay transports, and custom transport implementations.iroh-base/src/lib.rs– Core types includingEndpointId,PublicKey,SecretKey, andRelayUrl.iroh-dns/src/lib.rs– DNS resolver used for relay hostnames and PKARR address lookup services.iroh-relay/src/*– Relay server and client implementation that forwards encrypted traffic when direct connectivity fails.
Summary
- The iroh API provides a Rust-native interface for peer-to-peer networking over QUIC, exposing high-level abstractions like
EndpointandBuilder. - Identity is cryptographic: Nodes use
EndpointId(public keys) for both addressing and TLS authentication, eliminating certificate management overhead. - Automatic connectivity: The API handles complex network traversal via relay fallback (
RelayUrl) and automatic hole-punching, as implemented iniroh/src/lib.rslines 66-104. - Ergonomic configuration: The
Builderpattern iniroh/src/endpoint.rsenables fluent setup of ALPN protocols, relay modes, and address lookup services. - Lightweight streams: QUIC streams are inexpensive to create and multiplex, accessible via
Connection::open_biandConnection::open_uni.
Frequently Asked Questions
What transport protocol does the iroh API use?
The iroh API uses QUIC as its underlying transport protocol, providing built-in encryption, multiplexing, and congestion control. This is implemented through the Endpoint type in iroh/src/lib.rs, which manages the QUIC configuration and socket bindings.
How does the iroh API handle devices behind NAT or firewalls?
The iroh API automatically handles NAT traversal through a combination of relay fallback and hole-punching. When direct connectivity fails, traffic routes through a default or custom RelayUrl (as documented in iroh/src/lib.rs lines 96-103). Simultaneously, both endpoints attempt UDP hole-punching to establish a direct path, switching traffic away from the relay once successful.
What is the relationship between EndpointId and TLS certificates?
In the iroh API, the EndpointId (a public key) serves as the TLS identity. According to iroh/src/lib.rs (lines 81-89), each endpoint uses its secret key to generate TLS key material during the handshake. Peers authenticate each other by verifying that the presented public key matches the expected EndpointId, eliminating the need for traditional X.509 certificate chains.
Can I use custom relay servers with the iroh API?
Yes, the iroh API supports custom relay servers. While the default preset uses the "number 0" relay, you can configure alternative RelayUrl endpoints through the Builder API in iroh/src/endpoint.rs. This allows deployment of private relay infrastructure or selection of geographically closer relay nodes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →