Key Modules in the iroh Repository: A Complete Architectural Breakdown

The iroh repository is organized around the endpoint module for peer-to-peer connectivity, address_lookup for DNS and PKARR-based discovery, tls and protocol for QUIC encryption, with supporting infrastructure in iroh-relay, iroh-dns-server, and shared primitives in iroh-base.

The iroh networking stack provides a Rust-based framework for building peer-to-peer applications over QUIC. Understanding the key modules in the iroh repository is essential for developers integrating custom protocols, running infrastructure, or optimizing connection performance. This guide maps the crate structure to specific source files in the n0-computer/iroh codebase and demonstrates how the modules interact during a typical connection lifecycle.

Core Client-Side Modules

Endpoint (iroh/src/endpoint/mod.rs)

The endpoint module forms the primary public API. It exposes the Endpoint struct, which manages node identity, connection establishment, and stream multiplexing. In iroh/src/endpoint/mod.rs, the Endpoint::builder() method configures relay selection via RelayMode and initializes the QUIC stack with custom TLS handlers. The Connection type, returned by Endpoint::connect(), provides open_bi() and open_uni() methods for stream creation.

Address Resolution (iroh/src/address_lookup/)

Before connecting, an EndpointId must resolve to reachable addresses. The address_lookup directory contains multiple strategies:

Both implement the AddressLookup trait, returning a relay URL and direct addresses.

TLS and Protocol Handlers

QUIC connections rely on the tls module (iroh/src/tls/mod.rs) for certificate verification, providing TlsConnector and TlsAcceptor wrappers. The protocol module (iroh/src/protocol/mod.rs) defines the custom iroh relaying protocol through the Protocol and Message types, handling frame encoding for relayed traffic.

Observability and Diagnostics

Metrics (iroh/src/metrics.rs)

Runtime observability is handled by the metrics module, exposing Prometheus-compatible counters through the Metrics and ConnectionMetrics structs. These track connection establishment latency, throughput, and relay utilization as implemented in iroh/src/metrics.rs.

Network Reporting (iroh/src/net_report/mod.rs)

The optional net_report feature provides path quality analysis. NetReportConfig configures probe behavior, while the Probe struct measures relay latency and NAT traversal success rates, enabling dynamic path selection. The implementation resides in iroh/src/net_report/mod.rs.

Infrastructure and Server Components

Relay Server (iroh-relay/)

The iroh-relay crate contains the server-side implementation for traffic forwarding. In iroh-relay/src/server/http_server.rs, the RelayServer type accepts TLS-protected QUIC sessions and routes encrypted payloads between peers. Client-side relay configuration uses RelayMap and RelayConfig from iroh/src/relay_map.rs.

DNS Services (iroh-dns-server/ and iroh-dns/)

Discovery infrastructure includes the iroh-dns crate, which provides DnsResolver utilities in iroh-dns/src/dns.rs for client-side queries. The iroh-dns-server crate implements the publishing side, with DnsServer and HttpApi defined in iroh-dns-server/src/server.rs, serving TXT records for endpoint discovery.

Shared Primitives and Testing

iroh-base (iroh-base/src/lib.rs)

Cryptographic primitives and identifiers live in iroh-base. This crate defines EndpointId, PublicKey, SecretKey, and RelayUrl types used across the entire ecosystem, ensuring type safety between crates without circular dependencies. The definitions are centralized in iroh-base/src/lib.rs.

Benchmarking (iroh/bench/src/lib.rs)

Performance validation occurs in iroh-bench, located at iroh/bench/src/lib.rs, which implements throughput and latency benchmarks for connection setup and data transfer.

How the Modules Interact During Connection

When Endpoint::connect() is invoked, the following sequence executes:

  1. Resolution: The endpoint queries its configured AddressLookup (defaulting to DnsAddressLookup) to resolve the target EndpointId to a RelayUrl and direct addresses.
  2. Relay Negotiation: If direct connection fails, the endpoint establishes a QUIC connection to the relay using TlsConnector from the tls module, negotiating the custom Protocol defined in iroh/src/protocol/mod.rs.
  3. Hole Punching: Simultaneously, the endpoint attempts NAT traversal for direct peer-to-peer connectivity.
  4. Stream Establishment: Once connected, the Connection type exposes open_bi() and open_uni() methods for application data.
  5. Telemetry: Throughout the lifecycle, Metrics counters update, and optional NetReport probes collect path quality data.

Practical Code Examples

Creating a Client Endpoint

#[cfg(with_crypto_provider)]
async fn simple_client() -> n0_error::Result<()> {
    // Create an endpoint bound to the default "number 0" preset.
    let ep = iroh::Endpoint::bind(iroh::endpoint::presets::N0).await?;

    // Connect to a remote endpoint (replace with a real EndpointId).
    let remote_id = "VQ6X...".parse::<iroh::EndpointId>()?;
    let conn = ep.connect(remote_id, b"my-alpn").await?;

    // Open a bi-directional stream and exchange a hello message.
    let (mut send, mut recv) = conn.open_bi().await?;
    send.write_all(b"hello").await?;
    send.finish().await?;

    let reply = recv.read_to_end(usize::MAX).await?;
    println!("remote said: {}", String::from_utf8_lossy(&reply));
    Ok(())
}

This example uses the endpoint, address_lookup (via defaults), tls, and protocol modules as defined in iroh/src/lib.rs.

Configuring Custom DNS Lookup

use iroh::address_lookup::DnsAddressLookup;
use iroh::endpoint::Builder;

#[cfg(with_crypto_provider)]
async fn custom_dns_lookup() -> n0_error::Result<()> {
    // Build a DNS lookup that uses the staging domain.
    let dns_lookup = DnsAddressLookup::builder("iroh-staging.example".into()).build();

    // Attach the lookup to the endpoint builder.
    let ep = Builder::new()
        .address_lookup(dns_lookup)
        .bind()
        .await?;

    Ok(())
}

The lookup implementation lives in iroh/src/address_lookup/dns.rs.

Running a Relay Server

use iroh_relay::RelayServer;
use std::net::SocketAddr;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Listen on a UDP port for QUIC connections.
    let addr: SocketAddr = "[::]:443".parse()?;
    let server = RelayServer::bind(addr).await?;
    println!("Relay listening on {}", addr);
    server.serve().await?;
    Ok(())
}

Core server logic is located in iroh-relay/src/server/http_server.rs.

Summary

Frequently Asked Questions

What is the entry point for creating connections in iroh?

The Endpoint struct in iroh/src/endpoint/mod.rs serves as the primary entry point. Use Endpoint::bind() or Endpoint::builder() to configure a node, then call Endpoint::connect() with a target EndpointId and ALPN protocol identifier to establish peer-to-peer sessions.

How does iroh resolve peer addresses without a central coordinator?

The address_lookup module supports decentralized discovery. By default, it uses DnsAddressLookup to query DNS TXT records, but can be configured to use PkarrAddressLookup for PKARR-based resolution. Both strategies are implemented in iroh/src/address_lookup/dns.rs and iroh/src/address_lookup/pkarr.rs respectively.

Can I run my own relay server instead of using the default infrastructure?

Yes. The iroh-relay crate provides the RelayServer type, which you can bind to a UDP socket using RelayServer::bind() as shown in iroh-relay/src/server/http_server.rs. This allows complete control over traffic forwarding while maintaining compatibility with iroh clients.

Where are the cryptographic types like EndpointId and PublicKey defined?

These primitives reside in the iroh-base crate, specifically in iroh-base/src/lib.rs. This separation prevents circular dependencies between the client, relay, and DNS components while ensuring type consistency across the networking stack.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →