# How Iroh Relay Servers Work: NAT Traversal and Encrypted Traffic Forwarding

> Discover how Iroh relay servers enable NAT traversal and encrypted traffic forwarding when direct connections fail. Learn their essential role in the Iroh network.

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

---

**Iroh relay servers are optional, always-on nodes that sit between Iroh endpoints and forward encrypted traffic when direct peer-to-peer connections fail due to symmetric NATs or restrictive firewalls.**

Iroh is an open-source distributed systems toolkit maintained by n0-computer that prioritizes direct connectivity, but when NAT traversal fails, the **Iroh relay server** provides a reliable fallback path. According to the n0-computer/iroh source code, the relay implementation lives in the `iroh-relay` crate and operates as a standalone binary designed to coordinate connections without compromising end-to-end encryption.

## What Are Iroh Relay Servers?

**Iroh relay servers** act as intermediaries that maintain persistent connections to Iroh endpoints, forwarding encrypted data only when direct peer-to-peer links cannot be established. These servers do not handle plaintext payloads; they merely relay opaque encrypted frames between matched endpoint pairs. The implementation resides in the `iroh-relay` crate, specifically within the `iroh::relay::server` module imported in [`iroh-relay/src/main.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/main.rs).

The relay server's responsibilities are strictly limited to four core functions: accepting inbound client connections over HTTP, HTTPS, or QUIC; enforcing configurable access control policies; exchanging endpoint metadata such as public IP addresses and QUIC ports; and bidirectionally forwarding encrypted traffic between paired streams.

## Core Architecture and Components

The relay binary delegates functionality across distinct modules that handle configuration, transport encryption, access verification, and data forwarding.

### CLI and Configuration Layer

The entry point in [`iroh-relay/src/main.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/main.rs) parses command-line flags and TOML configuration files to build a `relay::ServerConfig` structure. The key function `build_relay_config(cfg)` constructs this configuration, which the CLI then passes to the server constructor:

```rust
let relay_config = build_relay_config(cfg).await?;
let mut relay = relay::Server::spawn(relay_config).await?;

```

Configuration options include bind addresses, TLS settings, and access control policies sourced from [`iroh-relay.toml`](https://github.com/n0-computer/iroh/blob/main/iroh-relay.toml).

### Transport and TLS Implementation

The server supports both HTTP/HTTPS and QUIC protocols, with TLS handling implemented in [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs). This module manages certificate loading, supporting manual certificates, self-signed development certificates, or automatic LetsEncrypt provisioning. QUIC address discovery binds to `tls.quic_bind_addr`, while HTTPS listens on `tls.https_bind_addr` and plain HTTP (development only) binds to `http_bind_addr`.

### Access Control System

Access control is implemented through the `dyn AccessControl` trait, with logic residing in [`iroh-relay/src/main.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/main.rs) and token extraction handled in [`src/server/client.rs`](https://github.com/n0-computer/iroh/blob/main/src/server/client.rs). The system supports five distinct modes:

- **AllowAll** permits any connection.
- **Allowlist** or **Denylist** check against known endpoint IDs.
- **SharedToken** validates bearer tokens from headers or URL query parameters.
- **Http** delegates authorization to an external HTTP endpoint by sending the `X-Iroh-Endpoint-Id` header and expecting a `true` response.

### Relay Engine and Stream Management

The core forwarding logic lives in [`iroh-relay/src/server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server.rs), which spawns the HTTP and QUIC listeners and manages client state through [`src/server/clients.rs`](https://github.com/n0-computer/iroh/blob/main/src/server/clients.rs). When two endpoints successfully authenticate, the server creates a pair of `Stream` objects defined in [`src/server/streams.rs`](https://github.com/n0-computer/iroh/blob/main/src/server/streams.rs) that handle bidirectional frame forwarding between the matched clients.

## Connection Flow and Data Relay Process

The relay server follows a strict lifecycle when establishing and maintaining connections between endpoints.

1. **Startup**: The binary reads [`iroh-relay.toml`](https://github.com/n0-computer/iroh/blob/main/iroh-relay.toml) (or uses defaults), loads TLS certificates via the TLS module, and binds to the configured addresses.

2. **Client Authentication**: An Iroh endpoint connects with a `ClientRequest` containing its `EndpointId` and optional authentication token.

3. **Policy Enforcement**: The server invokes the configured `AccessControl` implementation to validate the connection attempt.

4. **Endpoint Pairing**: Once two endpoints are authenticated and matched, the server creates bidirectional `Stream` pairs in [`src/server/streams.rs`](https://github.com/n0-computer/iroh/blob/main/src/server/streams.rs) to forward encrypted frames between them.

5. **Metrics Collection**: If compiled with the `metrics` feature, counters for connections, bytes transferred, and rejections are incremented and exposed via [`src/server/metrics.rs`](https://github.com/n0-computer/iroh/blob/main/src/server/metrics.rs) on a separate Prometheus-compatible endpoint.

## Security Model and Encryption

**Iroh relay servers** are designed with a security-first architecture that maintains end-to-end encryption while providing connectivity fallback. The relay operates on a zero-knowledge principle regarding payload content, forwarding only opaque encrypted frames that it cannot decrypt or inspect.

The server enforces TLS for all QUIC address discovery and HTTPS traffic, with optional but recommended LetsEncrypt integration for automatic certificate management. Access control is fully pluggable, allowing operators to restrict relay usage to known endpoint IDs, token-based authentication, or external authorization services. Metrics and relay traffic are isolated on separate ports to prevent information leakage.

## Development and Configuration Examples

To run a local relay server for development, use the development mode flag which disables TLS and binds to port 3340:

```bash
cargo run -p iroh-relay -- --dev

```

This command sets `dangerous_http_only = true` in the configuration, allowing plain HTTP connections for local testing.

For production deployments requiring authentication, configure a shared token in [`iroh-relay.toml`](https://github.com/n0-computer/iroh/blob/main/iroh-relay.toml):

```toml
access.shared_token = ["my-secret-token"]

```

Clients must then include the token in the `Authorization: Bearer my-secret-token` header or append `?token=my-secret-token` to the connection URL.

## Summary

- **Iroh relay servers** provide NAT traversal fallback by forwarding encrypted traffic between endpoints when direct peer-to-peer connections fail.
- The implementation in the `iroh-relay` crate separates concerns across [`src/main.rs`](https://github.com/n0-computer/iroh/blob/main/src/main.rs) (CLI), [`src/server.rs`](https://github.com/n0-computer/iroh/blob/main/src/server.rs) (core logic), [`src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/src/tls.rs) (encryption), and [`src/server/streams.rs`](https://github.com/n0-computer/iroh/blob/main/src/server/streams.rs) (data forwarding).
- Access control is pluggable, supporting static lists, shared tokens, and external HTTP authorization via the `AccessControl` trait.
- The relay maintains end-to-end encryption, handling only opaque encrypted frames and exposing no plaintext data to the server operator.
- Development mode (`--dev`) enables rapid local testing without TLS certificates, while production deployments support LetsEncrypt and custom authentication schemes.

## Frequently Asked Questions

### Do Iroh relay servers see my data?

No. According to the n0-computer/iroh source code, **Iroh relay servers** forward only opaque encrypted frames between endpoints. The relay operates as a dumb pipe that cannot decrypt the payload, ensuring end-to-end encryption remains intact between the communicating peers.

### What is the difference between Iroh relays and STUN/TURN servers?

While STUN servers help endpoints discover their public IP addresses and TURN servers relay media as a fallback, **Iroh relay servers** specifically handle the `iroh::relay` protocol. They exchange endpoint metadata including QUIC addresses and forward encrypted application data, whereas TURN typically handles raw UDP packets for WebRTC. The relay server is optimized for the Iroh protocol stack and maintains persistent HTTP/QUIC connections rather than temporary allocations.

### How do I deploy a production Iroh relay server?

Production deployments require configuring TLS certificates via [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs), either through manual certificate files or LetsEncrypt integration. You must specify `tls.https_bind_addr` and `tls.quic_bind_addr` in your configuration, implement appropriate `AccessControl` policies in the server configuration, and optionally enable the `metrics` feature for monitoring. The server runs as the `iroh-relay` binary with a custom [`iroh-relay.toml`](https://github.com/n0-computer/iroh/blob/main/iroh-relay.toml) configuration file.

### When does Iroh use a relay versus a direct connection?

Iroh endpoints attempt direct peer-to-peer connections first using NAT traversal techniques. The **Iroh relay server** serves as a fallback mechanism only when symmetric NATs, restrictive firewalls, or other network conditions prevent direct UDP hole punching from succeeding. Endpoints maintain persistent connections to known relays so they can rapidly fallback if direct paths become unavailable during a session.