Security Considerations for Running a Private iroh Relay Server: Complete Hardening Guide
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 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 stores certificate and private key paths. Always specify a client CA certificate to enforce mTLS verification.
// 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 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. 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. 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 supports built-in rate limiting to prevent denial-of-service attacks. Configure limits via the builder pattern to reject excessive CONNECT attempts.
// 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 for anomalous traffic patterns.
QUIC Protocol Security
The QUIC listener implementation in 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) 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. 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 should execute as a dedicated, non-root user. Configure systemd or your init system to drop privileges after binding to the port.
# 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. 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
TlsConfiginiroh-relay/src/tls.rsto restrict client access and protect the control plane. - Protect certificate files with
chmod 600permissions 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
RelayQuicConfigto 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. Additionally, implement token-based authentication via the key_cache module in 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. 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 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →