This document targets two audiences:
- LLMs/agents: quickly understand project structure, entry points, run flow, configuration, and risks.
- Human developers/operators: follow the steps to build, configure, start, and verify the service.
turn-rs is a TURN/STUN server implemented in Rust for WebRTC NAT traversal and media relay. It focuses on high performance and low configuration cost, and provides optional gRPC management APIs, Prometheus metrics, and Hook callbacks.
- TURN/STUN protocol support with TCP/UDP transport.
- Long-term credential mechanism with static users and hook-based dynamic auth.
- Optional gRPC management API and Prometheus metrics exporter.
- Multi-interface listeners and external address announcement.
- Runtime entry: src/main.rs
- Library entry: src/lib.rs
- Service and session logic: src/service
- Protocol handling and codecs: src/codec
- Transport providers (UDP/TCP): src/server/provider
- Config and logging: src/config.rs, src/logger.rs
- gRPC API and client SDK: sdk/protos/server.proto, sdk/src/lib.rs
- Sample config: turn-server.toml
- Docs entry: docs/README.md
This section explains how the server is organized internally and how the main data flow works.
-
src/main.rs loads config, initializes logging, and builds the Tokio runtime.
-
src/lib.rs
start_server()constructsStatistics, aHandler, and aService, then spawns:
- transport servers (UDP/TCP) via src/server
- optional Prometheus exporter via src/prometheus.rs
- optional gRPC API via src/api.rs
- src/service: TURN service core, shared state, and routing glue.
Serviceholds realm, interfaces, session manager, and handler, and creates per-connection routers.ServiceHandlerdefines the hooks the protocol layer uses for auth and lifecycle callbacks.- src/service/routing.rs parses STUN/TURN messages and dispatches by method.
- src/service/session: Session state, allocation, permissions, and channel bindings.
Identifier(source + interface) is the primary session key.SessionManagerowns sessions, port mappings, permissions, and channel relay tables.Sessiontracks authentication state, nonce, allocated port, channels, permissions, and expiry.- src/service/session/ports.rs provides
PortAllocatorandPortRange.
- src/server: Transport orchestration and cross-protocol forwarding.
- src/server/mod.rs
start_server()spawns TCP/UDP listeners per configured interface and aborts all servers if any one exits. - src/server/switch.rs
Switchmaps each sessionIdentifierto an internal channel for forwarding relayed packets between sockets; missing destinations are dropped silently. - src/server/buffer.rs provides a global memory pool (
Buffer) backed by a lock-freecrossbeam_queue::ArrayQueuewith a background task that shrinks idle buffers to avoid leaks.
- src/server/provider: Transport abstraction and server loop.
- src/server/provider/mod.rs defines the
ProviderServer/ProviderStreamtraits andServerOptions.ProviderServer::startbinds sockets, spawns per-connection tasks, routes packets, applies TCP channel-data padding, drives stats reporting, and handles idle timeout. - src/server/provider/udp.rs implements
UdpServer/UdpSession(a single shared socket demultiplexed into per-peer channels). - src/server/provider/tcp.rs implements
TcpServerwith an optional TLS (MaybeSslStream) accept path.
- src/handler.rs: Implements
ServiceHandler.
- Auth flow: static credentials -> static auth secret -> optional Hook
GetPassword. - Lifecycle events: allocation, channel bind, permission create, refresh, destroy (sent to Hook service when enabled).
- src/api.rs: gRPC management API and Hook client implementation.
TurnServiceexposes GetInfo/GetSession/GetSessionStatistics/DestroySession.RpcHooksServicemaintains a client + buffered event channel to the external Hook service.- The protobuf definitions and generated types now live in the
turn-server-sdkcrate; this module consumes them viasdk::protos::*.
- src/codec: STUN/TURN codec and crypto.
- Decoder differentiates STUN messages vs. ChannelData.
- Message encoder/decoder handles attributes, integrity, and fingerprint.
cryptocontains HMAC and password derivation helpers.
- src/statistics.rs: Per-session counters and reporting.
StatisticsReporteraggregates per-session bytes/packets and error counts.- Integrates with Prometheus metrics when enabled.
- src/prometheus.rs: HTTP metrics endpoint.
- Exposes
/metrics, tracks global + per-transport counts and allocated sessions.
- sdk:
turn-server-sdkworkspace crate (gRPC client/server utilities).
- Owns sdk/protos/server.proto and its generated types (built via sdk/build.rs).
- Provides
TurnServiceclient,TurnHooksServer, and password-generation helpers for integrators. - Consumed by the main binary through the
apifeature; published independently for external clients.
- Long-term credentials are the primary auth model; Hook auth is optional and pluggable.
- Port allocation is a pre-sized bitset allocator for fast random relay port selection.
- Session tables are pre-sized HashMaps for performance under load.
- Router validates peer addresses against local interfaces by default to reduce abuse risk.
- Transport loop is unified with the
ProviderServer/ProviderStreamtraits, but TCP/UDP sockets have their own implementations. - Read buffers come from a global, self-shrinking memory pool (
server::buffer::Buffer) to reduce allocation pressure on the hot path. - The
Switchdoes not require relay sends to succeed: if a destination session is gone, the packet is dropped and the entry is reclaimed.
- Download the binary from GitHub Releases for your platform.
- Prepare a config file (see turn-server.toml).
- Start the server:
turn-server --config ./turn-server.tomlInstall the Rust toolchain, then run in the project root:
cargo build --releaseThe binary will be in the target/release directory.
The config file uses TOML. Full reference: docs/configure.md.
server.*defines reachability and transport surfaces:server.interfacessupports multi-NIC and multi-transport (udp/tcp) listeners,listenbinds the local address, andexternaladvertises the public address to clients behind NAT or load balancers.server.port-rangelimits relay port allocation,server.max-threadscaps runtime workers, andserver.realmis a key input for long-term credential auth.server.interfaces.idle-timeoutreclaims idle connection resources. Note:server.interfaces.mtuis deprecated and no longer affects relaying; it is retained only for config compatibility.- TLS is enabled per surface: data plane via
server.interfaces.ssl.*(TCP transport only), management plane viaapi.ssl.*, and metrics plane viaprometheus.ssl.*. This lets you secure exposed endpoints while keeping internal ones lightweight. - Auth strategy is defined by
auth.*:auth.static-credentialsprovides local static users,auth.static-auth-secretenables TURN REST-style shared secrets; for dynamic auth, combineauth.enable-hooks-authwithhooks.*so an external Hook service can provide passwords and handle session events. Priority is static users first, then shared secret, then Hooks. hooks.*enables external integrations for dynamic auth and lifecycle callbacks (allocation, refresh, destroy, and more).hooks.max-channel-sizeandhooks.timeoutcontrol backpressure and timeouts so Hooks do not impact the main data path.api.*enables the gRPC management interface for querying server info, session state, statistics, and destroying sessions.prometheus.*exposes Prometheus metrics (requires theprometheusfeature at build time).log.*controls observability output:log.levelsets verbosity,log.stdoutfits container or systemd aggregation, andlog.file-directoryenables local log retention.
Basic command:
turn-server --config ./turn-server.tomlFor Linux systemd service, see docs/start-the-server.md.
Docker image is published on GitHub Packages. Pull and mount your config:
docker pull ghcr.io/mycrl/turn-server:latest
# Override the default config path inside the container
# Default path: /etc/turn-server/config.tomlSee docs/install.md for details.
You can reduce the binary by compiling with specific features:
- udp: UDP transport (default on)
- tcp: TCP transport
- ssl: TLS support
- api: gRPC management API
- prometheus: metrics exporter
Example:
cargo build --release --no-default-features --features udp,tcpThe following section explains how these capabilities work and what they provide, for readers unfamiliar with TURN ecosystems.
Purpose: allow external systems to query server status, inspect sessions, collect stats, and destroy sessions.
Protocol and fields: sdk/protos/server.proto. Core RPCs:
GetInfo: returns software info, uptime, listening interfaces, port capacity, and allocated ports.GetSession: query a session byid, returns username, permissions, channels, allocated port, and expiry.GetSessionStatistics: per-session bytes/packets and error packet counts.DestroySession: terminate a session byid.
Enablement and security:
- This endpoint has no TLS or auth by default. If exposed beyond a trusted network, enable
api.ssl.*. - Bind address is configured by
api.listen(default 127.0.0.1:3000). - Timeouts are configured by
api.timeout.
Purpose: dynamic authentication and event callbacks. At specific moments, turn-rs calls the external Hook service. The external service can decide whether to allow access and can record or integrate lifecycle events.
Protocol and fields: sdk/protos/server.proto. Two categories:
- Dynamic authentication
GetPassword: server asks for the password used to compute TURN message integrity.- Request includes
username,realm, andalgorithm(MD5orSHA256). - Response returns
passwordas bytes.
- Event callbacks
OnAllocatedEvent: relay allocation completed.OnChannelBindEvent: channel bound.OnCreatePermissionEvent: permission created.OnRefreshEvent: allocation refresh/extend.OnDestroyEvent: session destroyed.
Enablement and behavior:
- Hook address is configured by
hooks.endpoint, with TLS viahooks.ssl.*. auth.static-credentialstakes priority over Hook auth.- If
auth.static-auth-secretis configured, the server skips Hook password lookups. hooks.timeoutcontrols request timeouts;hooks.max-channel-sizelimits event buffering.
Typical use cases:
- Integrate with your account system for dynamic auth (temporary tickets, internal SSO).
- Record session lifecycle metrics for auditing or risk analysis.
- log.level controls log verbosity.
- log.stdout enables or disables stdout logs.
- log.file-directory writes logs to a daily file.
- prometheus.listen enables the metrics endpoint (requires
prometheusfeature).
- gRPC management endpoint has no auth/TLS by default; enable
api.ssl.*or keep it in a trusted network. - Protect certificates, private keys, and shared secrets with filesystem permissions.
- Unit/integration tests:
cargo test- Benchmarks (optional):
cargo bench- Update config: edit turn-server.toml and restart the service.
- Multi-interface: add multiple entries under server.interfaces with distinct listen/external.
- NAT environment: set external to a public reachable address so clients receive correct candidates.
- WebRTC TURN relay
- High-throughput media forwarding with stable long-lived connections
- Full coturn feature parity
- Complex auth systems without a deployable Hook service
- Entry logic is in src/main.rs and src/service.
- Config structs are in src/config.rs; update docs/configure.md and turn-server.toml when adding fields.
- gRPC API changes must update sdk/protos/server.proto and regenerate the
turn-server-sdktypes (sdk/build.rs). - Transport changes are in src/server/provider; shared forwarding/buffer logic is in src/server/switch.rs and src/server/buffer.rs.