Relay server (TURN)¶
Pure P2P connections sometimes can't be established due to firewall / NAT issues on one or all users' ends. To address those issues and bypass the most recalcitrant firewalls, one or more TURN (Traversal Using Relay NAT) servers can be used.
Drovio Server supports two ways of providing relays, that you can set with
webrtc.turn_provider.type in settings.conf:
type |
Relays | Credentials |
|---|---|---|
shared_secret (default) |
Your own coturn servers | Computed locally from a shared secret |
cloudflare |
Cloudflare Realtime TURN | Requested from the Cloudflare API |
Running your own coturn server keeps every relayed packet on the infrastructure you control and lets you control the ports and protocols being opened. Cloudflare removes the machine to install, patch and monitor. Both ways are covered below.
Existing deployments
shared_secret is the default: a deployment that does not declare
turn_provider at all keeps behaving exactly as before.
Run your own coturn¶
We use coturn (github.com/coturn/coturn) for our TURN servers, as most vendors do (Slack, Zoom…). Coturn also works as a STUN server to answer basic "what is my public IP address" queries.
Dedicated machine
We don't recommend deploying a TURN server on the same machine where Drovio Server is deployed, for security and performance reasons.
Install on Debian¶
Coturn is packaged for Debian (Debian 13 comes with the ~latest version) and runs on x64 as well as on arm64; the commands below are the same on both. Step by step, on a freshly installed Debian 13 machine:
- Uncomment
TURNSERVER_ENABLED=1and save. - Open the config file (see Configure coturn below):
Install on RHEL¶
Coturn is available through EPEL on RHEL 9 and 10. Step by step:
# Enable EPEL (RHEL 9 example; adjust the URL for your version)
sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf install coturn
Then open the config file (see Configure coturn below):
Configure coturn¶
Edit turnserver.conf as follows:
Listening and network:
listening-portandtls-listening-portshould be set to80and443instead of the default ports, to bypass most firewalls.listening-ip= public IP, or the private IP if you are behind a NAT (e.g. AWS EC2).relay-ip= same aslistening-ip.external-ip= the public IP, only whenlistening-ipis a private address behind a NAT.min-port=49152andmax-port=65535: the UDP port range coturn allocates for relay traffic. Open this range in your firewall for UDP.
Authentication:
fingerprintshould be uncommented.static-auth-secret=MySeCrEt: replace with a long random string. This is the shared secret between Drovio Server and coturn.realm=turn.example.com: replace; does not need to resolve to anything.stale-nonce=600should be uncommented.
Bandwidth:
max-bps: maximum bytes per second per session. Comment it out to leave it unlimited, or set it to at least the max bitrate configured insettings.conf(webrtc.service_quality.maximum). Note thatmax-bpsis in bytes per second whilewebrtc.service_quality.maximumis in kbits per second (default is 10 Mbps, i.e. 1,250,000 bytes/s).
TLS (optional, for TURNS support):
certandpkeypaths should point to your certificate and private key. If you do not need TURNS, skip this and use port80only when referring to this server (see Configure Drovio Server).- Set
cipher-listto"ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS:!AESCCM". no-tlsv1andno-tlsv1_1should be uncommented.
Security hardening:
no-multicast-peersshould be uncommented.allow-loopback-peersmust stay commented (loopback is denied by default since coturn 4.5.2).no-tcp-relayshould be uncommented: Drovio uses UDP relay only, disabling TCP relay reduces the attack surface.denied-peer-ip=0.0.0.0/8,denied-peer-ip=10.0.0.0/8,denied-peer-ip=172.16.0.0/12,denied-peer-ip=192.168.0.0/16,denied-peer-ip=127.0.0.0/8: prevents relayed traffic from reaching private or loopback networks.no-software-attributeshould be uncommented (hides the coturn version from responses).no-rfc5780,no-stun-backward-compatibilityandresponse-origin-only-with-rfc5780should be uncommented. These disable legacy STUN features that are not needed and reduce exposure.
You may also want to isolate the server in its own network / VPC.
CLI:
cli-ip=127.0.0.1,cli-port=5766,cli-password=myclipassword: change the CLI password. This is useful to check connected peers by runningtelnet localhost 5766, entering the password, thenps. Do not expose the CLI port externally.
Save, then restart coturn:
Your relay / TURN (and STUN) server is now up and running.
Configure Drovio Server¶
Back on your Drovio Server instance:
Look for webrtc, then replace turn_servers_secret with the static-auth-secret
value set above and adapt the config below to your needs, making sure to replace
the turn.example.com URL with the URL or IP of your coturn machine:
"webrtc": {
"turn_servers_secret": "MySeCrEt",
"turn_servers_auth_timeout": 300,
"ice_servers": [
{ "url": "stun:turn.example.com:443" },
{ "url": "turn:turn.example.com:443" },
{ "url": "turn:turn.example.com:443?transport=tcp" },
{ "url": "turns:turn.example.com:443" }
],
"service_quality": {
"minimum": 1000,
"maximum": 10000
}
}
- The first entry is STUN (only replies to "what is my IP address?" requests).
- The second is the classic 443 UDP TURN (without the TLS layer).
- The third is 443 TCP TURN (without the TLS layer).
- The fourth is 443 UDP TURNS (extra TLS layer).
This should work with most recalcitrant firewalls. The webrtc section is applied
live, so there is nothing to restart: the new relays are picked up within a few
seconds.
Use Cloudflare Realtime TURN¶
Cloudflare Realtime TURN is a managed relay service: there is no machine to install, patch or monitor and each participant is served by the Cloudflare location closest to them. Cloudflare bills the relayed traffic, refer to their pricing page for current rates.
Create a TURN key¶
- Open the Cloudflare dashboard, then Realtime → TURN.
- Create a TURN key and note its Key ID and API token. The token is displayed once.
Point Drovio Server at Cloudflare¶
On your Drovio Server instance:
Look for webrtc, set turn_provider to cloudflare and list Cloudflare's
relays in ice_servers:
"webrtc": {
"turn_provider": {
"type": "cloudflare",
"cloudflare": {
"key_id": "<your key id>",
"api_token": "<your api token>",
"ttl": 86400
}
},
"ice_servers": [
{ "url": "stun:stun.cloudflare.com:3478" },
{ "url": "turn:turn.cloudflare.com:3478?transport=udp" },
{ "url": "turn:turn.cloudflare.com:3478?transport=tcp" },
{ "url": "turns:turn.cloudflare.com:443?transport=tcp" }
],
"service_quality": {
"minimum": 1000,
"maximum": 10000
}
}
turn_servers_secret and turn_servers_auth_timeout are ignored while type is
cloudflare. Leave them in place: setting type back to shared_secret restores
your coturn setup without any other change.
Like the rest of the webrtc section, this is applied live and you don't have to
restart Drovio Server.
Credential lifetime¶
ttl is how long in seconds a credential sent to a client remains valid.
- Cloudflare refuses credentials living longer than 48 hours. Larger values get capped.
- Drovio Server renews its credential halfway through that lifetime.
- A client asks for a credential once when it opens a connection and never
again. A
ttlshorter than your longest meeting takes the relay down mid-session. Keep the default unless you have a reason not to.
If Cloudflare cannot be reached while renewing, Drovio Server keeps serving the credential it already holds until it really expires and logs the failure.
Firewall reach¶
Cloudflare answers UDP only on port 3478. Its port 443 is TCP only, wrapped in TLS
(turns:). A participant behind a firewall that allows nothing but outbound 443
therefore falls back to a TCP relay. That adds latency and copes less well with
packet loss than UDP.
If you have a restrictive firewall that only allows port 443 and performance matters, you may want to run your own coturn server with UDP port 443.
Verify the relay server¶
Adding ice=relay to the query string of a web client URL forces every
connection of that session through a relay, in any browser.
- Open the Drovio app and sign in.
- Use the bolt icon to start an instant meeting.
- Copy then paste the invite link into a browser and append
?ice=relayto it. - Proceed, enter a display name (don't "start the app instead", stay in the web browser) and proceed again.
- You should see your own screen, mirrored when viewing the shared screen.
If all you get is a loading spinner, the relay is not reachable or its credentials are refused.
The browser console also displays a warning, The url forces every connection
through the TURN server, which confirms the parameter was applied correctly.