# Security Implications of Relay Servers in iroh: Authentication, TLS, and Trust Boundaries

> Discover the security implications of iroh relay servers. Explore access control, metadata exposure, and transport layer hardening in this crucial iroh component.

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

---

**Iroh relay servers function as optional middle-boxes that forward encrypted traffic during NAT traversal without accessing payload contents, meaning their security implications center strictly on access control enforcement, metadata exposure risks, and transport layer hardening.**

The n0-computer/iroh repository implements a peer-to-peer networking stack where relay servers bridge connections through symmetric NATs and restrictive firewalls. While these servers facilitate connectivity by relaying packets, they remain outside the cryptographic trust boundary, requiring careful configuration of authentication mechanisms and transport security to prevent unauthorized use and metadata leakage.

## The Trust Boundary and Confidentiality Model

Relay servers in iroh are explicitly **not** confidentiality boundaries. The iroh protocol encrypts all payloads end-to-end, ensuring relay operators cannot decrypt traffic traversing their infrastructure. However, relays are **trusted for routing** and can observe connection metadata including source and destination IP addresses, port numbers, and the specific **Relay URL** used.

Deploying a relay with the default **AllowAll** access control—which is defined in [`iroh-relay/src/server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server.rs)—permits any client knowing the server URL to establish connections. For public deployments, this default creates an open relay vulnerable to abuse, as the server will forward packets for any unauthorized peer that discovers the endpoint.

## Authentication and Authorization Controls

The security posture hinges on the **AccessControl** trait defined in [`iroh-relay/src/server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server.rs) at lines 285-311. This trait governs authorization during the connection handshake, allowing deployers to replace `AllowAll` with token-based, allow-list, deny-list, or HTTP-backed authentication schemes.

The test suite demonstrates a production-ready pattern called **TokenAccess** in [`iroh-relay/tests/runtime_auth.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/tests/runtime_auth.rs) (lines 51-98). This implementation uses a mutable token store that validates credentials during the `on_connect` phase, rejecting requests that present invalid or revoked tokens.

```rust
use iroh_relay::server::{RelayConfig, ServerConfig, Server, Access, AccessControl};
use iroh_base::RelayUrl;
use std::net::Ipv4Addr;
use std::sync::Arc;
use tokio::sync::Mutex;

#[derive(Debug, Default)]
struct TokenAccess(Mutex<std::collections::HashMap<String, ()>>);

#[iroh_relay::server::async_trait]
impl AccessControl for TokenAccess {
    async fn on_connect(&self, req: &iroh_relay::server::ClientRequest) -> Access {
        match req.auth_token() {
            Some(tok) if self.0.lock().await.contains_key(&tok) => Access::Allow,
            _ => Access::Deny { reason: Some("invalid token".into()) },
        }
    }
}

let mut relay_cfg = RelayConfig::new((Ipv4Addr::LOCALHOST, 0));
relay_cfg.access = Arc::new(TokenAccess::default());
let mut server_cfg = ServerConfig::default();
server_cfg.relay = Some(relay_cfg);

let server = Server::spawn(server_cfg).await?;

```

## Runtime Token Revocation

For dynamic security policies, the `TokenAccess` pattern supports runtime revocation without service restarts. When administrators remove a token from the internal allow-list, the server automatically evicts all active connections that authenticated with that credential, preventing stale sessions from persisting.

```rust
let access: Arc<TokenAccess> = /* Arc from server config */;

access.0.lock().await.insert("secure-token-123".into(), ());

// Revocation immediately disconnects all clients using this token
access.0.lock().await.remove("secure-token-123");

```

## TLS Configuration and Server Identity

To prevent man-in-the-middle attacks on the control channel, relays must enable **TLS** via `RelayConfig.tls` as configured in [`iroh-relay/src/server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server.rs) (lines 121-140). The server presents an X.509 certificate—either self-signed or issued by a provider like Let's Encrypt—that clients validate before establishing the relay tunnel. This ensures attackers cannot impersonate the relay server to intercept metadata or redirect traffic.

## Metadata Exposure and DNS Security

While payloads remain encrypted, the relay infrastructure observes traffic patterns and endpoint metadata. To prevent accidental leakage of internal network topology through DNS resolution, iroh’s **RelayUrl** type documented in [`iroh-base/src/relay_url.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/relay_url.rs) (lines 14-18) enforces fully qualified domain names ending with a dot. This prevents the resolver from appending local search domains, which could expose internal hostnames to external DNS infrastructure.

An attacker controlling a relay could force all traffic through their server (by blocking direct hole-punching attempts), gaining access to timing and volume metadata even without decrypting payloads. Proper **AccessControl** configuration mitigates this by restricting which clients may use a given relay.

## Denial-of-Service Protections

Production deployments must configure resource limits to prevent exhaustion attacks. The `RelayConfig.limits` field and `key_cache_capacity` setting defined in [`iroh-relay/src/server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server.rs) (lines 141-144) provide rate-limiting and memory cap controls. These constraints restrict how many connections or resources a single malicious client can consume, protecting server availability for legitimate peers.

## Configuring Secure Client Endpoints

When establishing connectivity, applications can specify trusted relay mappings to avoid falling back to untrusted public infrastructure. The endpoint builder in [`iroh/src/endpoint.rs`](https://github.com/n0-computer/iroh/blob/main/iroh/src/endpoint.rs) accepts custom relay configurations via `RelayMode::Custom`.

```rust
use iroh::endpoint::{Builder, RelayMode};
use iroh_relay::client::RelayMap;

let relay_url: RelayUrl = "https://relay.example.com.".parse().unwrap();
let relay_map = RelayMap::new(relay_url);
let endpoint = Builder::new()
    .relay_mode(RelayMode::Custom(relay_map))
    .spawn().await?;

```

## Summary

- **Relay servers do not decrypt payloads**—they handle encrypted packets only, preserving end-to-end confidentiality.
- **Default AllowAll is unsafe**—production relays must implement the `AccessControl` trait from [`iroh-relay/src/server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server.rs) to prevent unauthorized use.
- **Runtime revocation works**—the `TokenAccess` pattern in [`iroh-relay/tests/runtime_auth.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/tests/runtime_auth.rs) demonstrates dynamic token invalidation.
- **TLS is mandatory**—configure `RelayConfig.tls` (lines 121-140) to prevent man-in-the-middle attacks on the control channel.
- **Use fully qualified DNS names**—follow the `RelayUrl` guidance in [`iroh-base/src/relay_url.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-base/src/relay_url.rs) to prevent internal hostname leakage.
- **Enable rate limiting**—tune `RelayConfig.limits` and `key_cache_capacity` (lines 141-144) to mitigate denial-of-service risks.

## Frequently Asked Questions

### Do relay servers decrypt my traffic in iroh?

No. Relay servers only forward encrypted packets and cannot access plaintext payload contents. The iroh protocol maintains end-to-end encryption between peers, meaning relays are trusted for routing but remain untrusted for data confidentiality.

### What happens if I run a relay with default settings?

The default **AllowAll** access control permits any client knowing the relay URL to forward traffic through your server. This creates an open relay vulnerable to bandwidth abuse and metadata harvesting. You must replace this with a strict `AccessControl` implementation before public deployment.

### How do I revoke access to a relay without restarting it?

Implement a token-based `AccessControl` similar to `TokenAccess` in [`iroh-relay/tests/runtime_auth.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/tests/runtime_auth.rs). By storing tokens in a mutex-protected collection wrapped in an `Arc`, you can remove entries at runtime, causing the server to immediately disconnect all clients authenticated with the revoked token.

### Can a compromised relay server read my data?

No, because payloads are end-to-end encrypted. However, a compromised relay can observe metadata such as IP addresses, connection timing, and traffic volume. It could also refuse to forward packets or attempt man-in-the-middle attacks if **TLS** is not enforced via `RelayConfig.tls`.