# How to Use iroh for Peer-to-Peer Communication

> Learn how to use iroh for peer-to-peer communication with its Rust library. iroh handles NAT traversal, encryption, and connection multiplexing for simple P2P applications.

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

---

**Yes, iroh is explicitly designed for peer-to-peer communication, offering a Rust library that manages NAT traversal, encrypted QUIC streams, and connection multiplexing through a simple `Endpoint` API.**

The `n0-computer/iroh` repository provides a production-ready stack for peer-to-peer communication built directly on the QUIC transport protocol. By abstracting complex networking challenges like hole punching and relay fallback behind the `Endpoint` type, iroh enables developers to establish direct connections between peers even across restrictive firewalls and NATs, handling encryption and stream management automatically.

## How iroh Enables Peer-to-Peer Communication

Iroh achieves reliable peer-to-peer connectivity through a layered architecture that combines QUIC transport with intelligent NAT traversal. The system balances direct connections with relay fallback to guarantee connectivity in any network environment.

### The Endpoint Abstraction

At the core of iroh's P2P capabilities is the **`Endpoint`** struct, implemented in [[`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs#L888). An `Endpoint` represents a local iroh node that can both dial other peers and accept incoming connections. It manages the underlying QUIC socket, cryptographic identity, and connection state, exposing QUIC streams that are cheap to create and can be bidirectional or unidirectional.

### NAT Traversal and Relay Fallback

When direct connectivity fails, iroh uses a sophisticated fallback mechanism documented in [[`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs#L97-L110). Endpoints initially register with a *home* **relay server** that forwards encrypted traffic based on the peer's `EndpointId`. Simultaneously, the endpoints attempt **hole punching** (described in [[`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs#L66-L73)) to establish a direct path. If successful, the connection automatically migrates from the relay to the direct path, removing the relay from the data path entirely.

### Encryption and Identity Management

All peer-to-peer communication in iroh uses **TLS-wrapped QUIC**, as implemented in [[`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs#L81-L90). Each endpoint generates a long-term `SecretKey`/`PublicKey` pair, where the public key serves as the `EndpointId`. This provides built-in authentication and encryption without requiring certificate authorities or manual TLS configuration, ensuring all P2P traffic remains end-to-end encrypted.

### Address Discovery

Iroh supports flexible peer discovery through the **address lookup** system defined in [[`iroh/src/address_lookup.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/address_lookup.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/address_lookup.rs). This optional DNS-based service allows peers to publish their `RelayUrl` and direct addresses, enabling connection establishment using only the target's `EndpointId` rather than hardcoding network addresses.

## Implementing P2P Connections with iroh

The following examples demonstrate practical peer-to-peer communication patterns using iroh's `Endpoint` API. These examples require the `with_crypto_provider` feature to be enabled in your [`Cargo.toml`](https://github.com/n0-computer/iroh/blob/main/Cargo.toml).

### Dialing a Remote Peer

To initiate a peer-to-peer connection, bind a local endpoint and connect to a remote address using the `Endpoint::connect` method:

```rust
#[cfg(with_crypto_provider)]
async fn connect_to_peer(addr: iroh::EndpointAddr) -> n0_error::Result<()> {
    use iroh::{Endpoint, endpoint::presets};

    // Create a local endpoint bound to the default relay.
    let ep = Endpoint::bind(presets::N0).await?;

    // Open a QUIC connection to the remote peer using ALPN protocol negotiation.
    let conn = ep.connect(addr, b"my-alpn").await?;

    // Open a bidirectional stream and send data.
    let (mut send, mut recv) = conn.open_bi().await?;
    send.write_all(b"hello").await?;
    send.finish().await?;
    
    // Read the response.
    let reply = recv.read_to_end(1024).await?;
    println!("Received: {:?}", String::from_utf8_lossy(&reply));

    // Graceful shutdown.
    conn.close(0u8.into(), b"done");
    ep.close().await;
    Ok(())
}

```

This pattern follows the implementation guidance in [[`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs#L84-L93), using `Endpoint::bind` with the `N0` preset for public relay connectivity, then negotiating a connection with application-level protocol identification via ALPN.

### Accepting Incoming Connections

To receive peer-to-peer connections, configure an endpoint with supported ALPN identifiers and use the `accept` method:

```rust
#[cfg(with_crypto_provider)]
async fn accept_connections() -> n0_error::Result<()> {
    use iroh::{Endpoint, endpoint::presets};

    // Build an endpoint that listens for specific application protocols.
    let ep = Endpoint::builder(presets::N0)
        .alpns(vec![b"my-alpn".to_vec()])
        .bind()
        .await?;

    // Wait for an incoming P2P connection.
    let conn = ep.accept().await?.await?;

    // Accept a bidirectional stream and echo the payload.
    let (mut send, mut recv) = conn.accept_bi().await?;
    let data = recv.read_to_end(1024).await?;
    send.write_all(&data).await?;
    send.finish().await?;

    // Wait for close and cleanup.
    conn.closed().await;
    ep.close().await;
    Ok(())
}

```

As shown in [[`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs#L100-L108), the `Endpoint::builder` pattern allows configuration of supported ALPNs before binding, ensuring the endpoint only accepts connections for specific application protocols.

### Configuring Custom Address Resolution

For environments requiring custom discovery mechanisms, iroh supports pluggable address lookup:

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

let builder = Builder::default()
    .address_lookup(DnsAddressLookup::new())
    .bind()
    .await?;

```

This configuration, referencing the patterns in [[`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs#L62-L70), enables DNS-based resolution of peer addresses rather than embedding relay URLs directly in the connection code.

## Key Source Files and Architecture

Understanding these core source files helps navigate iroh's peer-to-peer implementation:

- **[[`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)** – High-level library overview documenting QUIC transport, relay behavior, hole punching, and public API usage patterns.
- **[[`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs)** – Implementation of the `Endpoint` struct, connection lifecycle management, and stream handling APIs.
- **[[`iroh/src/address_lookup.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/address_lookup.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/address_lookup.rs)** – Pluggable address resolution traits and DNS-based lookup implementations.
- **[[`iroh-base/src/endpoint_addr.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/endpoint_addr.rs)](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/endpoint_addr.rs)** – Type definitions for `EndpointAddr`, representing composite peer addresses (relay + direct).
- **[[`iroh-base/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/lib.rs)** – Core primitive re-exports including `EndpointId`, `PublicKey`, and `RelayUrl`.
- **[[`iroh-relay/src/server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server.rs)](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server.rs)** – Reference implementation of the relay server used for NAT traversal fallback.
- **[[`iroh-dns/src/endpoint_info.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/endpoint_info.rs)](https://github.com/n0-computer/iroh/blob/main/iroh-dns/src/endpoint_info.rs)** – DNS publishing helpers for endpoint information distribution.

## Summary

- **Iroh provides native peer-to-peer communication** through the `Endpoint` abstraction, handling both connection initiation and acceptance over QUIC.
- **Automatic NAT traversal** combines hole punching with relay fallback, ensuring connectivity even when both peers are behind firewalls.
- **Built-in encryption** uses TLS-wrapped QUIC with Ed25519 keys, providing authenticated and encrypted P2P streams without manual certificate management.
- **Flexible addressing** supports direct connections, relay-mediated connections, and pluggable discovery services via the address lookup system.
- **Stream multiplexing** allows multiple bidirectional or unidirectional streams over a single P2P connection, enabling efficient application protocol design.

## Frequently Asked Questions

### Does iroh require central servers for peer-to-peer communication?

No, iroh does not require central servers for operation, though it can utilize relay servers for NAT traversal. According to the implementation in [[`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs#L66-L73), relay servers act only as temporary encrypted packet forwarders during the initial handshake or when hole punching fails. Once direct connectivity is established, traffic migrates to the peer-to-peer path, and the relay is no longer involved in data transmission.

### What cryptographic protections does iroh provide for P2P connections?

Iroh uses **TLS 1.3 wrapped QUIC** with Ed25519 key pairs for all peer-to-peer communication. As implemented in [[`iroh/src/lib.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/lib.rs#L81-L90), each endpoint generates a `SecretKey` and corresponding `PublicKey` (used as the `EndpointId`), providing mutual authentication and end-to-end encryption without requiring certificate authorities or manual TLS configuration.

### How does iroh handle connection migration when network conditions change?

Iroh leverages QUIC's native connection migration capabilities combined with its own path validation logic. When a direct path becomes available after initial relay-mediated connection, the library automatically migrates the connection to the direct path. If the direct path fails, the connection can fall back to the relay without dropping the application-level session, maintaining P2P communication continuity across network changes.

### Can iroh connect to peers using only an ID without knowing their IP address?

Yes, when combined with the address lookup system documented in [[`iroh/src/address_lookup.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/address_lookup.rs)](https://github.com/n0-computer/iroh/blob/main/iroh/src/address_lookup.rs), iroh can resolve a peer's `EndpointId` to connection addresses through DNS or other discovery mechanisms. This allows applications to initiate peer-to-peer connections knowing only the cryptographic identity of the target peer, abstracting away dynamic IP addresses and NAT mappings.