# What Is the n0-Computer/iroh Protocol? A Deep Dive into QUIC-Based P2P Networking

> Discover the n0-computer/iroh protocol, a QUIC-based P2P network stack. It uses public keys for identity, automatic authentication, NAT traversal, and encrypted relays.

- Repository: [number zero/iroh](https://github.com/n0-computer/iroh)
- Tags: deep-dive
- Published: 2026-06-23

---

**The n0-computer/iroh protocol is a peer-to-peer networking stack built on QUIC that uses public keys for endpoint identity, enabling automatic mutual authentication without a central PKI while providing built-in NAT traversal and encrypted relay fallback.**

The n0-computer/iroh protocol serves as the network layer for the iroh library, a Rust-based toolkit for building distributed applications. By leveraging QUIC (defined in IETF RFC 9000) and eliminating traditional certificate authorities, it creates a secure, globally routable network where every peer is identified by its cryptographic public key.

## Identity and Authentication via Public Keys

Instead of relying on domain names or centralized certificate authorities, the n0-computer/iroh protocol derives identity directly from cryptography. Every `Endpoint` holds a `SecretKey`, and its corresponding public key becomes the `EndpointId`. This ID functions as the TLS certificate's subject during the handshake, as implemented in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) (lines 24-31).

This design provides **automatic mutual authentication**—both endpoints verify each other's public keys during the TLS handshake without requiring a separate PKI infrastructure. The `EndpointId` serves as both the identity and the address, making peers globally routable regardless of their underlying IP addresses.

## QUIC Transport and Protocol Selection

The protocol uses the **noq** QUIC implementation from the `noq` crate for transport. When establishing connections, the library configures TLS with the endpoint's secret key and registers Application-Layer Protocol Negotiation (ALPN) strings to identify supported protocols.

In [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) (lines 1170-1190), the `connect_with_opts` method creates a QUIC client configuration that negotiates these ALPNs during the handshake. Each application protocol is identified by a specific ALPN string (such as `b"/iroh/echo/1"`), allowing a single endpoint to multiplex multiple protocols over one QUIC connection.

## Protocol Routing with the Router

Incoming connections are dispatched through the `Router`, which maps ALPN strings to user-defined handlers. The `ProtocolHandler` trait, defined in [`iroh/src/protocol.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/protocol.rs) (lines 27-45), requires implementers to handle incoming `Connection` objects.

To register a protocol, developers use `Router::builder(endpoint).accept(ALPN, handler).spawn()`, creating a clean separation between transport concerns and application logic. This architecture allows endpoints to simultaneously support multiple protocols—such as file transfer, chat, and streaming—over a single network port.

## Connection Establishment: Hole-Punching and Relay Fallback

The n0-computer/iroh protocol implements sophisticated NAT traversal to establish direct connections between peers behind firewalls. After the QUIC handshake completes, peers attempt direct UDP communication via **hole-punching**. If this fails, the connection falls back to a relay server (the "home relay") without dropping the encrypted session.

Relays forward encrypted packets addressed to an `EndpointId` but cannot decrypt payload data, as all traffic remains encrypted under QUIC/TLS. The address discovery mechanism uses Pkarr/DNS to publish an endpoint's public addresses and relay information under its `EndpointId`, allowing peers to resolve IDs to reachable sockets before connecting. This logic is handled in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) (lines 1840-1865) via the `addr` and `watch_addr` methods.

## Zero-RTT Performance Optimization

For latency-sensitive applications, the protocol supports 0-RTT (Zero Round Trip Time) data transmission. The `ProtocolHandler::on_accepting` method, documented in [`iroh/src/protocol.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/protocol.rs) (lines 28-44), allows handlers to take control of a connection before the handshake fully completes. This enables servers to begin processing requests immediately, reducing connection latency to a single packet round trip.

## Security Model

The security architecture rests on three pillars:

- **Public-key authentication**: No certificate authorities are required; peers authenticate via cryptographic signatures exchanged during the TLS handshake.
- **End-to-end encryption**: All traffic is encrypted under QUIC/TLS, including when traversing relay servers.
- **Relay privacy**: Relay servers only forward encrypted packets and cannot read payload data or identify the ultimate destination beyond the `EndpointId`.

## Practical Implementation Example

The following example demonstrates the canonical echo protocol, showing how to create endpoints, register protocols, and establish connections:

```rust
use iroh::{
    Endpoint,
    endpoint::{presets, Connection},
    protocol::{AcceptError, ProtocolHandler, Router},
};

const ALPN: &[u8] = b"/iroh/echo/1";

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Accepting side
    let server = Endpoint::bind(presets::N0).await?;
    let router = Router::builder(server.clone())
        .accept(ALPN, Echo)
        .spawn();

    // Connecting side
    let client = Endpoint::bind(presets::N0).await?;
    let conn = client.connect(server.addr(), ALPN).await?;
    let (mut send, mut recv) = conn.open_bi().await?;
    send.write_all(b"Hello, iroh!").await?;
    send.finish()?;
    let reply = recv.read_to_end(1024).await?;
    assert_eq!(&reply, b"Hello, iroh!");

    // Cleanup
    router.shutdown().await?;
    server.close().await;
    client.close().await;
    Ok(())
}

#[derive(Debug, Clone)]
struct Echo;

impl ProtocolHandler for Echo {
    async fn accept(&self, connection: Connection) -> Result<(), AcceptError> {
        let (mut send, mut recv) = connection.accept_bi().await?;
        tokio::io::copy(&mut recv, &mut send).await?;
        send.finish()?;
        connection.closed().await;
        Ok(())
    }
}

```

To customize relay behavior, configure the endpoint builder:

```rust
let endpoint = Endpoint::builder(presets::N0)
    .relay_mode(RelayMode::Custom(custom_map))
    .bind()
    .await?;

```

For 0-RTT support, implement the `on_accepting` method:

```rust
impl ProtocolHandler for MyZeroRtt {
    async fn on_accepting(&self, accepting: Accepting) -> Result<Connection, AcceptError> {
        let conn = accepting.into_0rtt().await?;
        Ok(conn)
    }

    fn accept(&self, _connection: Connection) -> impl Future<Output = Result<(), AcceptError>> + Send {
        async { Ok(()) }
    }
}

```

## Summary

- **Public-key identity**: The n0-computer/iroh protocol uses `EndpointId` (derived from `SecretKey`) as the TLS certificate subject, eliminating the need for certificate authorities.
- **QUIC-based transport**: Built on the `noq` crate with ALPN-based protocol multiplexing handled by the `Router` in [`iroh/src/protocol.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/protocol.rs).
- **Automatic NAT traversal**: Attempts direct hole-punching first, then falls back to encrypted relay servers without compromising security.
- **Address discovery**: Uses Pkarr/DNS to publish and resolve endpoint addresses under the public key identity.
- **Extensible architecture**: New protocols are implemented via the `ProtocolHandler` trait and registered with specific ALPN strings.

## Frequently Asked Questions

### What transport protocol does the n0-computer/iroh protocol use?

The protocol is built on **QUIC** (IETF RFC 9000), using the `noq` Rust implementation. This provides stream multiplexing, congestion control, and built-in TLS encryption at the transport layer.

### How does iroh handle peers behind NATs or firewalls?

The protocol first attempts **hole-punching** to establish direct UDP paths after the QUIC handshake. If direct connection fails, it transparently falls back to **relay servers** that forward encrypted packets without decrypting them, ensuring connectivity even when both peers are behind restrictive NATs.

### What is the purpose of ALPN strings in iroh?

Application-Layer Protocol Negotiation (ALPN) strings identify specific protocols running over the QUIC connection. The `Router` in [`iroh/src/protocol.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/protocol.rs) uses these strings to dispatch incoming connections to the appropriate `ProtocolHandler` implementations, enabling multiple protocols to share a single endpoint.

### How does iroh ensure security without a central certificate authority?

Security relies on **public-key cryptography** rather than centralized trust. Each endpoint generates its own `SecretKey`, and the corresponding public key becomes the `EndpointId`. During the TLS handshake, peers mutually authenticate by verifying these public keys, creating a trust model where identity is self-certified and globally unique.