Skip to content

Instantly share code, notes, and snippets.

@maxidorius
Last active June 20, 2024 17:48
Show Gist options
  • Save maxidorius/2b0acc2e707ae9a2d6d0267026a1024f to your computer and use it in GitHub Desktop.
Save maxidorius/2b0acc2e707ae9a2d6d0267026a1024f to your computer and use it in GitHub Desktop.
Working config for VoIP in Matrix: synapse + coturn

This configuration is provided AS-IS and as an example/reference for those who do not find a working configuration for themselves. It is not always kept up to date and no support is provided.

Assuming:

  • Your Matrix domain: example.org
  • Your TURN domain (arbitrary): turn.example.org
  • Your Public IP: 1.2.3.4
  • Your Private IP for the box hosing the services: 10.11.12.13
  • A shared secret between synapse and coturn: ThisIsASharedSecret-ChangeMe
  • You want Firefox compatiblity (TURNS only is not supported)

synapse

homeserver.yaml:

## Turn ##

# The public URIs of the TURN server to give to clients
turn_uris:
  - "turns:turn.example.org?transport=udp"
  - "turns:turn.example.org?transport=tcp"
  - "turn:turn.example.org?transport=udp"
  - "turn:turn.example.org?transport=tcp"

# The shared secret used to compute passwords for the TURN server
turn_shared_secret: "ThisIsASharedSecret-ChangeMe"

# How long generated TURN credentials last
turn_user_lifetime: "1h"

coturn

turnserver.conf:

syslog

lt-cred-mech
use-auth-secret
static-auth-secret=ThisIsASharedSecret-ChangeMe
realm=example.org

cert=/etc/letsencrypt/live/turn.example.org/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.org/privkey.pem

no-udp
external-ip=1.2.3.4
min-port=64000
max-port=65535

Firewall

Allow ports:

  • TCP 3478
  • UDP 3478
  • TCP 3479
  • UDP 3479
  • TCP 5349
  • UDP 5349
  • UDP 64000 to 65535
@steadfasterX
Copy link

@maxidorius : thanks! simple and straight forward!
I have a public IP (so no NAT involved) and the following ruleset works fine for me:

image
(ofc with adjusted min and max ports within turnserver.conf)

note: RFC5766 does not mention port 3479 and is not needed imho.
also I specified only the both "turns:" addresses within "turn_uris" so left out the unencrypted ones.

other then that a great quick tut, thanks again :)

@GeoffLedak
Copy link

Thank you so much for this. After going through several different guides and getting nowhere, this worked perfectly.

@weiss
Copy link

weiss commented Jan 14, 2022

Just for the record:

As for 3479, it is a RFC requirement to have the +1 port usable, so following the RFC on that. Is there an updated RFC on that front I missed maybe?

Yes that's no longer used, the reasoning is explained in RFC 5389.

That means that some data is not encrypted sadly.

As has been mentioned above, WebRTC streams are end-to-end encrypted, so TLS doesn't offer additional security for this use case. Clients will usually prefer UDP to minimize latency. Offering TLS as a fallback (on port 443) can help clients circumvent restrictive firewalls (which try to block everything but HTTPS), though.

Also note that even in the case where your client does use a TLS connection to the TURN server, the server always talks unencrypted UDP to the peer (it works in an asymmetric manner, I maintain a TURN server myself and have a quick protocol overview that tries to explain these things on the website).

@lixxdee
Copy link

lixxdee commented Jan 21, 2022

Hi all. after a long and tedious setup of coturn, this configuration actually worked with TLS. However, sometimes these lines reason: TLS/TCP socket buffer operation error (callback) in the logs confuse me. Can you comment on them somehow? And how to fix them?
I managed to avoid this error in the logs, by adding inturnserver.conf to the configuration no-tlsv1_2, and I didn’t see error in logs anything, but i think and it seems that my connection was not secure in terms of TLS.

@weiss
Copy link

weiss commented Jan 21, 2022

a long and tedious setup of coturn

Gives me another chance for embedded marketing! I think configuration and logging are way more straightforward with eturnal 😄

sometimes these lines reason: TLS/TCP socket buffer operation error (callback) in the logs confuse me. Can you comment on them somehow?

You typically see those when the TLS connection wasn't closed cleanly. Unfortunately, this log line alone isn't enough to understand the actual problem. The full log line also mentions a session ID. You could grep the log for that ID to check for earlier messages related to the same session in order to track down at what point the connection was closed. Two possible causes are: (1) The client closed the connection during the initial handshake, e.g. because certificate verification failed or it was unhappy with TLS parameters/ciphers. (2) TURN relaying actually worked fine, and the client just didn't close the session cleanly. This can happen during normal operation, in which case it wouldn't be a problem at all.

it seems that my connection was not secure in terms of TLS.

Do you mean the client doesn't use TLS if you disable TLSv1.2, or do you mean it falls back to earlier TLS versions? Either may be true, the log output should tell you. However, as I explained above, TLS has no security advantage in this context anyway, and can add significant latency, which is the reason UDP is usually used for (end-to-end encrypted) media streaming.

@maxidorius
Copy link
Author

maxidorius commented Jan 21, 2022

However, as I explained above, I would personally suggest keeping UDP (and unencrypted TCP) enabled anyway. Using TLS has no security advantage in this context, and can add significant latency, which is the reason UDP is usually used for (end-to-end encrypted) media streaming.

@weiss and to everyone who would advise another configuration than the one of this gist, please keep in mind that the reason it was posted in the first place is that people were struggling to find a working setup.

As pointed out by @GeoffLedak:

Thank you so much for this. After going through several different guides and getting nowhere, this worked perfectly.

Or @lixxdee

Hi all. after a long and tedious setup of coturn, this configuration actually worked with TLS.

I'm always happy to consider updating this gist but only if it doesn't work anymore. That certain ports or some RFC may not be needed is good to know, but ultimately irrelevant to the point: other guides never worked for me. They didn't work for others who landed here. But this works as stated several times. There are many stacks, software and network configurations out there, everyone mileage may vary. Why is this working and others don't? I don't know. I'm a pragmatic person and I want to help others, so here is simply what works for me.

If you actually do have a working setup that is different than this one and just works out of the box (that's the magic bit), feel free to create a gist of your own!

@weiss
Copy link

weiss commented Jan 21, 2022

@maxidorius, my comments weren't meant to be a criticism of the setup you suggested above. Setting up TURN can be non-trivial indeed, and I totally appreciate your approach of publishing something that 'just works'.

I'm always happy to consider updating this gist but only if it doesn't work anymore.

I think problems such as missing STUN support or suboptimal latency can be somewhere in between "works" and "doesn't work", in the sense that things could work better (at least for some users), and admins might not be aware of that, as it's not obvious when testing the setup.

feel free to create a gist of your own!

I just figured it might be helpful for others to clarify some questions/assumptions made in comments above, e.g. about the relevance of enforcing TLS in this context. But I take it you don't find this useful, so I'll refrain from further comments. Sorry!

@maxidorius
Copy link
Author

@weiss Don't worry, I didn't think you were criticizing anything here, far from it! But to be precise here, I found in my own experience that non-working guides/howto/advices don't work because they:
a) Are not given as a whole
b) Are not given complete

While I can only be happy and humbled by the fact this gist is still alive and receiving comments after more than 2 years, I do not want to end up in a situation where any of the two points given above become true. Ideally for the comments as well.

So It's great people are giving feedback and advice on how to do it better, but if you do then please also share a configuration that is

  • Whole: All configs that relate to it, the same way I give the coturn, synapse and firewall configs
  • Complete: Give all of the relevant config, not just the changed bits

And I'm sure you can see how my advice "feel free to create a gist of your own!" fits there: you can literally copy/paste it, change whatever you feel is better, test it out on a server, then put a link here. I would be more than happy to include it into the gist itself under a new section!
Vague comments are what made me write this gist, so let's try not to fall into the same issues again :)

Finally: thanks for your input, I would love to see another working config that has your points taken into account. I might use it for myself as well, who knows!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment