From 48d97dc2433953592b9d6d3d4a69626b4bac5f93 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Fri, 10 Dec 2021 03:19:01 -0500 Subject: [PATCH 1/5] Add details for how to set up TURN behind NAT Signed-off-by: Andrew Ferrazzutti --- docs/turn-howto.md | 95 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/docs/turn-howto.md b/docs/turn-howto.md index e6812de69e6b..6577fdd39030 100644 --- a/docs/turn-howto.md +++ b/docs/turn-howto.md @@ -15,8 +15,8 @@ The following sections describe how to install [coturn](TURN->TURN->client flows work allowed-peer-ip=10.0.0.1 @@ -129,26 +144,84 @@ This will install and start a systemd service called `coturn`. We recommend that you only try to set up TLS/DTLS once you have set up a basic installation and got it working. + NB: If your TLS certificate was provided by Let's Encrypt, TLS/DTLS will + not work with any Matrix client that uses Chromium's WebRTC library (such + as Element Android). See [this case](https://github.com/vector-im/element-android/issues/1533) for more details. + 1. Ensure your firewall allows traffic into the TURN server on the ports you've configured it to listen on (By default: 3478 and 5349 for TURN traffic (remember to allow both TCP and UDP traffic), and ports 49152-65535 for the UDP relay.) -1. We do not recommend running a TURN server behind NAT, and are not aware of - anyone doing so successfully. +1. If your TURN server is behind a NAT, the NAT gateway must have an external, + publicly-reachable IP address. You must configure coturn to advertise that + address to connecting clients: + + ``` + external-ip=YOUR_NAT_IP + ``` - If you want to try it anyway, you will at least need to tell coturn its - external IP address: + If your NAT gateway's external addresses include both an IPv4 and IPv6 + address, it is recommended to configure coturn to advertise all of them. In + this case, each configuration line must also specify the internal IPs of + your TURN server (i.e. the addresses assigned to them within the NAT): ``` - external-ip=192.88.99.1 + external-ip=EXTERNAL_NAT_IPv4_ADDRESS/INTERNAL_TURNSERVER_IPv4_ADDRESS + external-ip=EXTERNAL_NAT_IPv6_ADDRESS/INTERNAL_TURNSERVER_IPv6_ADDRESS ``` - ... and your NAT gateway must forward all of the relayed ports directly - (eg, port 56789 on the external IP must be always be forwarded to port - 56789 on the internal IP). + When advertising an external IPv6 address, ensure that the firewall and + network settings of the system running your TURN server are configured to + accept IPv6 traffic. + + Your NAT gateway must forward all of the relayed ports directly (eg, port + 56789 on the external IP must always be forwarded to port 56789 on the + internal IP). If your NAT server runs Linux (and you have administrative + rights to it), port forwarding may be applied with the following `iptables` + rules: + + ```sh + # Enable forwarding from the NAT gateway to your subnet + # Based on https://wiki.debian.org/OpenVPN#Forward_traffic_to_provide_access_to_the_Internet + iptables -A FORWARD -i $EXTERNAL_INTERFACE_NAME -o $INTERNAL_INTERFACE_NAME -m state --state ESTABLISHED,RELATED -j ACCEPT + iptables -A FORWARD -s $INTERNAL_INTERFACE_IPv4_SUBNET -o $EXTERNAL_INTERFACE_NAME -j ACCEPT + ip6tables -A FORWARD -s $INTERNAL_INTERFACE_IPv6_SUBNET -o $EXTERNAL_INTERFACE_NAME -j ACCEPT + iptables -t nat -A POSTROUTING -s $INTERNAL_INTERFACE_IPv4_SUBNET -o $EXTERNAL_INTERFACE_NAME -j SNAT --to-source $EXTERNAL_NAT_IPv4_ADDRESS + ip6tables -t nat -A POSTROUTING -s $INTERNAL_INTERFACE_IPv6_SUBNET -o $EXTERNAL_INTERFACE_NAME -j SNAT --to-source $EXTERNAL_NAT_IPv6_ADDRESS + + # forward coturn ports + iptables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p tcp -m multiport --dports 3478,3479,5349,5350 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv4_ADDRESS + iptables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p udp -m multiport --dports 3478,3479,5349,5350,49152:65535 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv4_ADDRESS + iptables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p tcp -m multiport --dports 5222,5269 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv4_ADDRESS + + # same, but for ipv6 + ip6tables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p tcp -m multiport --dports 3478,3479,5349,5350 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv6_ADDRESS + ip6tables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p udp -m multiport --dports 3478,3479,5349,5350,49152:65535 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv6_ADDRESS + ip6tables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p tcp -m multiport --dports 5222,5269 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv6_ADDRESS + ``` + + For this to work, the NAT server must be configured to forward IPv4/IPv6 + traffic. To check if forwarding is enabled, run + `cat /proc/sys/net/ipv4/ip_forward` and `cat /proc/sys/net/ipv6/conf/all/forwarding` + and confirm they both print `1`. If not, they may be set at runtime like so: + + ```sh + echo 1 > /proc/sys/net/ipv4/ip_forward + echo 1 > /proc/sys/net/ipv6/conf/all/forwarding + ``` + + To apply these settings persistently, add/uncomment these lines in + `/etc/sysctl.conf`, then run `sysctl -p`: + + ``` + net.ipv4.ip_forward=1 + net.ipv6.conf.all.forwarding=1 + ``` - If you get this working, let us know! + (The `all` in any of the the IPv6 paths/settings mentioned above may be + substituted for the name of any specific network interface that must + forward traffic.) 1. (Re)start the turn server: From 9d9fd178daa7b3b7114ba73aa34e9b1ebfadeac2 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Fri, 10 Dec 2021 03:39:39 -0500 Subject: [PATCH 2/5] Add changelog file Signed-off-by: Andrew Ferrazzutti --- changelog.d/11553.doc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/11553.doc diff --git a/changelog.d/11553.doc b/changelog.d/11553.doc new file mode 100644 index 000000000000..810ba1692861 --- /dev/null +++ b/changelog.d/11553.doc @@ -0,0 +1 @@ +Add details for how to configure a TURN server when behind a NAT. Contibuted by @AndrewFerr. From 49f3b40a0224c98c69b252b29d6eeca0f7bed3f1 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Fri, 17 Dec 2021 00:52:16 -0500 Subject: [PATCH 3/5] Condense and improve NAT comments - Remove out-of-scope comments - Make minor corrections & clarifications - Add troubleshooting advice for NAT setups Signed-off-by: Andrew Ferrazzutti --- docs/turn-howto.md | 87 ++++++++++++++-------------------------------- 1 file changed, 26 insertions(+), 61 deletions(-) diff --git a/docs/turn-howto.md b/docs/turn-howto.md index 6577fdd39030..555a2b065d9c 100644 --- a/docs/turn-howto.md +++ b/docs/turn-howto.md @@ -119,6 +119,7 @@ This will install and start a systemd service called `coturn`. denied-peer-ip=240.0.0.0-255.255.255.255 # special case the turn server itself so that client->TURN->TURN->client flows work + # this should be one of the turn server's listening IPs allowed-peer-ip=10.0.0.1 # consider whether you want to limit the quota of relayed streams per user (or total) to avoid risk of DoS. @@ -138,16 +139,12 @@ This will install and start a systemd service called `coturn`. pkey=/path/to/privkey.pem ``` - In this case, replace the `turn:` schemes in the `turn_uri` settings below + In this case, replace the `turn:` schemes in the `turn_uris` settings below with `turns:`. We recommend that you only try to set up TLS/DTLS once you have set up a basic installation and got it working. - NB: If your TLS certificate was provided by Let's Encrypt, TLS/DTLS will - not work with any Matrix client that uses Chromium's WebRTC library (such - as Element Android). See [this case](https://github.com/vector-im/element-android/issues/1533) for more details. - 1. Ensure your firewall allows traffic into the TURN server on the ports you've configured it to listen on (By default: 3478 and 5349 for TURN traffic (remember to allow both TCP and UDP traffic), and ports 49152-65535 @@ -158,70 +155,30 @@ This will install and start a systemd service called `coturn`. address to connecting clients: ``` - external-ip=YOUR_NAT_IP + external-ip=EXTERNAL_NAT_IPv4_ADDRESS ``` - If your NAT gateway's external addresses include both an IPv4 and IPv6 - address, it is recommended to configure coturn to advertise all of them. In - this case, each configuration line must also specify the internal IPs of - your TURN server (i.e. the addresses assigned to them within the NAT): + You may optionally limit the TURN server to listen only on the local + address that is mapped by NAT to the external address: ``` + listening-ip=INTERNAL_TURNSERVER_IPv4_ADDRESS external-ip=EXTERNAL_NAT_IPv4_ADDRESS/INTERNAL_TURNSERVER_IPv4_ADDRESS - external-ip=EXTERNAL_NAT_IPv6_ADDRESS/INTERNAL_TURNSERVER_IPv6_ADDRESS - ``` - - When advertising an external IPv6 address, ensure that the firewall and - network settings of the system running your TURN server are configured to - accept IPv6 traffic. - - Your NAT gateway must forward all of the relayed ports directly (eg, port - 56789 on the external IP must always be forwarded to port 56789 on the - internal IP). If your NAT server runs Linux (and you have administrative - rights to it), port forwarding may be applied with the following `iptables` - rules: - - ```sh - # Enable forwarding from the NAT gateway to your subnet - # Based on https://wiki.debian.org/OpenVPN#Forward_traffic_to_provide_access_to_the_Internet - iptables -A FORWARD -i $EXTERNAL_INTERFACE_NAME -o $INTERNAL_INTERFACE_NAME -m state --state ESTABLISHED,RELATED -j ACCEPT - iptables -A FORWARD -s $INTERNAL_INTERFACE_IPv4_SUBNET -o $EXTERNAL_INTERFACE_NAME -j ACCEPT - ip6tables -A FORWARD -s $INTERNAL_INTERFACE_IPv6_SUBNET -o $EXTERNAL_INTERFACE_NAME -j ACCEPT - iptables -t nat -A POSTROUTING -s $INTERNAL_INTERFACE_IPv4_SUBNET -o $EXTERNAL_INTERFACE_NAME -j SNAT --to-source $EXTERNAL_NAT_IPv4_ADDRESS - ip6tables -t nat -A POSTROUTING -s $INTERNAL_INTERFACE_IPv6_SUBNET -o $EXTERNAL_INTERFACE_NAME -j SNAT --to-source $EXTERNAL_NAT_IPv6_ADDRESS - - # forward coturn ports - iptables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p tcp -m multiport --dports 3478,3479,5349,5350 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv4_ADDRESS - iptables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p udp -m multiport --dports 3478,3479,5349,5350,49152:65535 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv4_ADDRESS - iptables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p tcp -m multiport --dports 5222,5269 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv4_ADDRESS - - # same, but for ipv6 - ip6tables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p tcp -m multiport --dports 3478,3479,5349,5350 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv6_ADDRESS - ip6tables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p udp -m multiport --dports 3478,3479,5349,5350,49152:65535 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv6_ADDRESS - ip6tables -t nat -A PREROUTING -i $EXTERNAL_INTERFACE_NAME -p tcp -m multiport --dports 5222,5269 -j DNAT --to-destination $INTERNAL_TURNSERVER_IPv6_ADDRESS ``` - For this to work, the NAT server must be configured to forward IPv4/IPv6 - traffic. To check if forwarding is enabled, run - `cat /proc/sys/net/ipv4/ip_forward` and `cat /proc/sys/net/ipv6/conf/all/forwarding` - and confirm they both print `1`. If not, they may be set at runtime like so: + If your NAT gateway is reachable over both IPv4 and IPv6, you may + configure coturn to advertise each available address. When doing so, + each configuration line must also specify the internal IPs of your + TURN server (i.e. the addresses assigned to them within the NAT): - ```sh - echo 1 > /proc/sys/net/ipv4/ip_forward - echo 1 > /proc/sys/net/ipv6/conf/all/forwarding ``` - - To apply these settings persistently, add/uncomment these lines in - `/etc/sysctl.conf`, then run `sysctl -p`: - - ``` - net.ipv4.ip_forward=1 - net.ipv6.conf.all.forwarding=1 + external-ip=EXTERNAL_NAT_IPv4_ADDRESS/INTERNAL_TURNSERVER_IPv4_ADDRESS + external-ip=EXTERNAL_NAT_IPv6_ADDRESS/INTERNAL_TURNSERVER_IPv6_ADDRESS ``` - (The `all` in any of the the IPv6 paths/settings mentioned above may be - substituted for the name of any specific network interface that must - forward traffic.) + When advertising an external IPv6 address, ensure that the firewall and + network settings of the system running your TURN server are configured to + accept IPv6 traffic. 1. (Re)start the turn server: @@ -289,9 +246,6 @@ connecting". Unfortunately, troubleshooting this can be tricky. Here are a few things to try: - * Check that your TURN server is not behind NAT. As above, we're not aware of - anyone who has successfully set this up. - * Check that you have opened your firewall to allow TCP and UDP traffic to the TURN ports (normally 3478 and 5349). @@ -307,6 +261,17 @@ Here are a few things to try: Try removing any AAAA records for your TURN server, so that it is only reachable over IPv4. + * If your TURN server is behind a NAT: + + * double-check that your NAT gateway is correctly forwarding all TURN + ports to the NAT-internal address of your TURN server. If advertising + both IPv4 and IPv6 external addresses, ensure that the NAT is forwarding + both IPv4 and IPv6 traffic to the IPv4 and IPv6 internal addresses of your + TURN server. When in doubt, remove AAAA records for your TURN server and + configure coturn to advertise only IPv4 addresses. + + * ensure that your TURN server uses the NAT gateway as its default route. + * Enable more verbose logging in coturn via the `verbose` setting: ``` From 091127606131f56918660e93be88f52d5b5c69d1 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Tue, 21 Dec 2021 02:07:53 -0500 Subject: [PATCH 4/5] Address some feedback Signed-off-by: Andrew Ferrazzutti --- docs/turn-howto.md | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/turn-howto.md b/docs/turn-howto.md index 555a2b065d9c..d6b56b825d73 100644 --- a/docs/turn-howto.md +++ b/docs/turn-howto.md @@ -15,7 +15,7 @@ The following sections describe how to install [coturn]( Date: Thu, 23 Dec 2021 10:15:24 +0000 Subject: [PATCH 5/5] minor tweak to add `normally` --- docs/turn-howto.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/turn-howto.md b/docs/turn-howto.md index d6b56b825d73..e32aaa1850d6 100644 --- a/docs/turn-howto.md +++ b/docs/turn-howto.md @@ -262,7 +262,7 @@ Here are a few things to try: * If your TURN server is behind NAT: * double-check that your NAT gateway is correctly forwarding all TURN - ports (3478 & 5349 for TCP & UDP TURN traffic, and 49152-65535 for the UDP + ports (normally 3478 & 5349 for TCP & UDP TURN traffic, and 49152-65535 for the UDP relay) to the NAT-internal address of your TURN server. If advertising both IPv4 and IPv6 external addresses via the `external-ip` option, ensure that the NAT is forwarding both IPv4 and IPv6 traffic to the IPv4 and IPv6