# Security Considerations for Running a Private iroh Relay Server: Complete Hardening Guide

> Secure your private iroh relay server with our hardening guide. Learn TLS, mTLS, rate limiting, and least privilege to prevent attacks and protect peer traffic.

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

---

**Running a private iroh relay server requires hardening TLS configuration, enforcing mutual TLS authentication, implementing rate limiting, and operating with least-privilege principles to prevent denial-of-service attacks and unauthorized access while maintaining the relay's inability to decrypt peer traffic.**

The iroh relay server from the n0-computer/iroh repository forwards encrypted traffic between peers without accessing clear-text payloads, but the surrounding infrastructure requires careful hardening to prevent abuse. This guide examines critical security considerations derived from the iroh-relay source code, covering TLS implementation, authentication mechanisms, network exposure controls, and operational best practices.

## Hardening TLS and Mutual Authentication

The relay implements its own TLS layer in [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs) to protect the control plane. You must enable **Mutual TLS (mTLS)** to ensure only authorized clients can register and request relay connections.

### Configuring RelayConfig with mTLS

The `RelayConfig` struct in [`iroh-relay/src/relay_map.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/relay_map.rs) stores certificate and private key paths. Always specify a client CA certificate to enforce mTLS verification.

```rust
// Example: creating a RelayConfig with mTLS
let tls_cfg = TlsConfig::from_files(
    "/etc/iroh/relay-cert.pem",
    "/etc/iroh/relay-key.pem",
    Some("/etc/iroh/client-ca.pem"), // client CA for mTLS
)?;

```

### File Permissions for Certificate Keys

Certificate files must be readable only by the relay process. Store TLS material with restricted permissions (e.g., `chmod 600`) and verify the `RelayConfig` paths point to directories inaccessible to other users.

## Authentication and Token Management

The relay validates **relay tokens** defined in [`iroh-relay/src/client.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/client.rs) to authorize client connections. These tokens are short-lived and signed with secrets managed by the `key_cache` module.

### Relay Token Validation

Tokens are verified against secrets stored in [`iroh-relay/src/key_cache.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/key_cache.rs). Never hard-code the signing secret; load it from a protected file or environment variable at startup.

### Secret Rotation Strategy

Implement regular rotation of the relay secret. If the secret is compromised, attackers can forge valid tokens. When rotating, remember that existing client tokens become invalid immediately and must be re-issued.

## Network Exposure and Rate Limiting

By default, the relay binds to `0.0.0.0` on a configurable port defined in [`iroh-relay/src/defaults.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/defaults.rs). Exposing this service requires strict firewall rules and application-layer rate limiting.

### Firewall Configuration

Use `iptables`, cloud security groups, or equivalent to restrict inbound TCP and UDP traffic to the specific ports used (commonly QUIC 443 or your custom configuration). Limit connections to known IP ranges when possible.

### Built-in Rate Limiting

The `RelayService` in [`iroh-relay/src/server/http_server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server/http_server.rs) supports built-in rate limiting to prevent denial-of-service attacks. Configure limits via the builder pattern to reject excessive `CONNECT` attempts.

```rust
// Enable rate limiting (10 requests per second per client)
let server = RelayService::builder()
    .config(tls_cfg)
    .rate_limit(10, Duration::from_secs(1))
    .build()
    .await?;

```

### OS-Level Resource Constraints

Combine application rate limiting with OS-level controls. Set `ulimit -n` to prevent file descriptor exhaustion and monitor `RelayMetrics` from [`iroh-relay/src/server/metrics.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server/metrics.rs) for anomalous traffic patterns.

## QUIC Protocol Security

The QUIC listener implementation in [`iroh-relay/src/quic.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/quic.rs) handles UDP traffic and requires tuning to prevent amplification attacks.

### Stream and Packet Limits

Configure `RelayQuicConfig` (defined in [`iroh-relay/src/relay_map.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/relay_map.rs)) to set conservative maximum concurrent streams and enforce maximum packet sizes. This reduces the risk of amplification attacks using malformed QUIC packets.

## Logging and Audit Security

Proper logging ensures visibility without leaking sensitive material.

### Structured Log Configuration

The `RelayService` emits structured logs from [`iroh-relay/src/server/http_server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server/http_server.rs). Configure log rotation using `logrotate` or similar tools to prevent disk exhaustion.

### Preventing Secret Leakage

Audit logging configurations to ensure relay tokens and private keys are never written to log files. Log entries should identify clients by safe identifiers, not by authentication credentials.

## Operational Hardening

Running the relay with minimal privileges reduces the attack surface from local system compromise.

### Running as Non-Root User

The binary entry point in [`iroh-relay/src/main.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/main.rs) should execute as a dedicated, non-root user. Configure systemd or your init system to drop privileges after binding to the port.

```bash

# Systemd unit snippet – run as non‑root user, drop privileges

[Service]
User=iroh-relay
Group=iroh-relay
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
ReadWritePaths=/var/log/iroh-relay
ReadOnlyDirectories=/etc/iroh
ExecStart=/usr/local/bin/iroh-relay --config /etc/iroh/relay.toml

```

### Container Security

When deploying via Docker, use a minimal base image and drop all capabilities with `--cap-drop ALL`. Mount TLS certificates as read-only volumes and ensure the container runtime user matches the non-root service user.

## Maintenance and Disaster Recovery

Long-term security requires dependency management and backup strategies.

### Dependency Management

The relay depends on `quinn` for QUIC and `hyper`/`axum` for HTTP handling, as defined in the repository's [`Cargo.toml`](https://github.com/n0-computer/iroh/blob/main/Cargo.toml). Monitor CVE databases and update dependencies regularly to patch vulnerability disclosures.

### Backup and Key Rotation

Store backups of the TLS private key and relay secret in a secure vault. Loss of the private key requires re-issuing all client certificates, while loss of the relay secret invalidates all existing tokens.

## Summary

- **Enable mTLS** via `TlsConfig` in [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs) to restrict client access and protect the control plane.
- **Protect certificate files** with `chmod 600` permissions and store them in paths readable only by the relay process.
- **Implement rate limiting** using `RelayService::builder()` to prevent DoS attacks on the HTTP API.
- **Configure QUIC limits** in `RelayQuicConfig` to mitigate amplification attacks through packet size restrictions.
- **Run as non-root** using systemd capabilities or container security contexts to minimize system exposure.
- **Rotate secrets regularly** and store backups in secure vaults to maintain operational continuity.

## Frequently Asked Questions

### Does the iroh relay server decrypt peer traffic?

No. The relay server forwards encrypted traffic between peers without accessing clear-text payloads. According to the `iroh-relay` source code, the relay acts as a packet forwarder for the QUIC and encrypted streams, ensuring the server cannot perform man-in-the-middle attacks on the data plane.

### How do I prevent unauthorized clients from connecting to my private relay?

Enable **Mutual TLS (mTLS)** by configuring a client CA certificate in `TlsConfig::from_files()` as implemented in [`iroh-relay/src/tls.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/tls.rs). Additionally, implement token-based authentication via the `key_cache` module in [`iroh-relay/src/key_cache.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/key_cache.rs) to validate short-lived relay tokens from clients.

### What rate limits should I configure for a production iroh relay?

Start with conservative limits such as 10 requests per second per client using `RelayService::builder().rate_limit()`, as shown in [`iroh-relay/src/server/http_server.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/server/http_server.rs). Combine this with OS-level limits on file descriptors (`ulimit -n`) and monitor `RelayMetrics` to adjust thresholds based on legitimate traffic patterns.

### How do I securely rotate the relay secret without dropping connections?

Rotation of the relay secret stored in [`iroh-relay/src/key_cache.rs`](https://github.com/n0-computer/iroh/blob/main/iroh-relay/src/key_cache.rs) immediately invalidates existing tokens. To avoid dropping connections, implement a grace period where both old and new secrets are valid temporarily, or schedule rotation during maintenance windows when clients can re-authenticate with new tokens.