Skip to main content

Relay Server

The TURN relay server provides media relay for cairn peers that cannot establish direct connections due to symmetric NATs or restrictive firewalls. It implements RFC 8656.

What the TURN Relay Does

  • Relays traffic when direct P2P connection fails (symmetric NAT, corporate firewalls, carrier-grade NAT)
  • Standard TURN protocol over UDP, with optional TLS support
  • End-to-end encrypted -- the relay forwards ciphertext and cannot read message content
  • Automatic fallback -- clients attempt direct connection first and fall back to relay only when needed

Docker Deployment

docker run -d \
-p 3478:3478/udp \
-p 443:443 \
-p 8080:8080 \
-e CAIRN_RELAY_REST_SECRET=your-api-secret \
-e CAIRN_RELAY_TLS_CERT=/certs/cert.pem \
-e CAIRN_RELAY_TLS_KEY=/certs/key.pem \
-v /path/to/certs:/certs:ro \
ghcr.io/moukrea/cairn-relay

For development (no TLS, static credentials):

docker run -d \
-p 3478:3478/udp \
-e CAIRN_RELAY_CREDENTIALS=user1:pass1 \
ghcr.io/moukrea/cairn-relay

Configuration Reference

All options can be set via CLI flags or environment variables.

FlagEnvironment VariableDefaultDescription
--listen-addrCAIRN_RELAY_LISTEN_ADDR0.0.0.0:3478TURN UDP listen address
--port-rangeCAIRN_RELAY_PORT_RANGE49152-65535Relay port range (format: start-end)
--credentialsCAIRN_RELAY_CREDENTIALS--Static credentials (format: user:pass, comma-separated)
--rest-secretCAIRN_RELAY_REST_SECRET--Shared secret for REST API credential provisioning
--tls-certCAIRN_RELAY_TLS_CERT--TLS certificate path (for TURN-over-TLS)
--tls-keyCAIRN_RELAY_TLS_KEY--TLS private key path
--tls-addrCAIRN_RELAY_TLS_ADDR0.0.0.0:443TLS listen address
--api-addrCAIRN_RELAY_API_ADDR127.0.0.1:8080REST API listen address
--realmCAIRN_RELAY_REALMcairnTURN realm
--turn-uriCAIRN_RELAY_URIauto-generatedTURN URI advertised in REST API responses

TLS

Provide PEM certificate and key files for TURN-over-TLS on port 443. This is recommended for production to ensure signaling data is protected in transit, even though application data is already end-to-end encrypted.

Credential Management

Static Credentials

Set credentials directly via environment variable:

CAIRN_RELAY_CREDENTIALS="user1:pass1,user2:pass2"

Dynamic Credentials via REST API

When CAIRN_RELAY_REST_SECRET is configured, the relay exposes a REST API for dynamic TURN credential provisioning.

Request:

curl -H "Authorization: Bearer your-api-secret" \
"http://127.0.0.1:8080/credentials?ttl=600"

Response:

{
"username": "1709312345:cairn-temp",
"password": "base64-hmac-credential",
"ttl": 600,
"uris": ["turn:relay.example.com:3478"]
}

Credentials are time-limited (default TTL: 3600 seconds). The REST API uses constant-time comparison for Bearer token authentication.

Client-Side Configuration

Point your cairn nodes at your relay server:

use cairn_p2p::{CairnConfig, create};

let config = CairnConfig {
turn_server: Some("turn:relay.example.com:3478".into()),
turn_username: Some("user1".into()),
turn_password: Some("pass1".into()),
..CairnConfig::default()
};
let node = create(config)?;
node.start().await?;