From 59e37105e8a79df6c35f543c3d0922297d129d38 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Tue, 19 Mar 2019 10:24:39 +0200 Subject: [PATCH] Add TLS support to Coturn --- CHANGELOG.md | 23 +++++++++++++++ docs/prerequisites.md | 2 +- group_vars/matrix-servers | 16 ++++++++-- roles/matrix-coturn/defaults/main.yml | 7 +++++ roles/matrix-coturn/tasks/setup_coturn.yml | 29 +++++++++++++++++-- .../systemd/matrix-coturn.service.j2 | 10 +++++++ .../templates/turnserver.conf.j2 | 12 ++++++++ setup.yml | 2 +- 8 files changed, 95 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31d25995..3112657b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,26 @@ +# 2019-03-19 + +## TLS support for Coturn + +We've added TLS support to the Coturn TURN server installed by the playbook by default. +The certificates from the Matrix domain will be used for the Coturn server. + +This feature is enabled by default for new installations. +To make use of TLS support for your existing Matrix server's Coturn, make sure to rebuild both Coturn and Synapse: + +```bash +ansible-playbook -i inventory/hosts setup.yml --tags=setup-coturn,setup-synapse,start +``` + +People who have an extra firewall (besides the iptables firewall, which Docker manages automatically), will need to open these additional firewall ports: `5349/tcp` (TURN over TCP) and `5349/udp` (TURN over UDP). + +People who build their own custom playbook from our roles should be aware that: + +- the `matrix-coturn` role and actually starting Coturn (e.g. `--tags=start`), requires that certificates are already put in place. For this reason, it's usually a good idea to have the `matrix-coturn` role execute after `matrix-nginx-proxy` (which retrieves the certificates). + +- there are a few variables that can help you enable TLS support for Coturn. See the `matrix-coturn` section in [group_vars/matrix-servers](./group_vars/matrix-servers). + + # 2019-03-12 ## matrix-nginx-proxy support for serving the base domain diff --git a/docs/prerequisites.md b/docs/prerequisites.md index 23cb19b3..66c7c2b2 100644 --- a/docs/prerequisites.md +++ b/docs/prerequisites.md @@ -12,6 +12,6 @@ - properly configured DNS records for `` (details in [Configuring DNS](configuring-dns.md)) -- some TCP/UDP ports open. This playbook configures the server's internal firewall for you. In most cases, you don't need to do anything special. But **if your server is running behind another firewall**, you'd need to open these ports: `80/tcp` (HTTP webserver), `443/tcp` (HTTPS webserver), `3478/tcp` (STUN over TCP), `3478/udp` (STUN over UDP), `8448/tcp` (Matrix Federation API HTTPS webserver), the range `49152-49172/udp` (TURN over UDP). +- some TCP/UDP ports open. This playbook configures the server's internal firewall for you. In most cases, you don't need to do anything special. But **if your server is running behind another firewall**, you'd need to open these ports: `80/tcp` (HTTP webserver), `443/tcp` (HTTPS webserver), `3478/tcp` (TURN over TCP), `3478/udp` (TURN over UDP), `5349/tcp` (TURN over TCP), `5349/udp` (TURN over UDP), `8448/tcp` (Matrix Federation API HTTPS webserver), the range `49152-49172/udp` (TURN over UDP). When ready to proceed, continue with [Configuring DNS](configuring-dns.md). diff --git a/group_vars/matrix-servers b/group_vars/matrix-servers index 949dc246..45d25178 100755 --- a/group_vars/matrix-servers +++ b/group_vars/matrix-servers @@ -93,6 +93,14 @@ matrix_coturn_enabled: true matrix_coturn_turn_external_ip_address: "{{ ansible_host }}" +matrix_coturn_tls_enabled: true +matrix_coturn_tls_cert_path: "{{ matrix_ssl_config_dir_path }}/live/{{ matrix_server_fqn_matrix }}/fullchain.pem" +matrix_coturn_tls_key_path: "{{ matrix_ssl_config_dir_path }}/live/{{ matrix_server_fqn_matrix }}/privkey.pem" +matrix_coturn_container_additional_volumes: + - src: "{{ matrix_ssl_config_dir_path }}" + dst: "{{ matrix_ssl_config_dir_path }}" + options: ro + ###################################################################### # # /matrix-coturn @@ -351,11 +359,15 @@ matrix_synapse_email_smtp_require_transport_security: false matrix_synapse_email_notif_from: "Matrix <{{ matrix_mailer_sender_address }}>" matrix_synapse_email_riot_base_url: "https://{{ matrix_server_fqn_riot }}" +# Even if TURN doesn't support TLS (it does by default), +# it doesn't hurt to try a secure connection anyway. matrix_synapse_turn_uris: | {{ [ - 'turn:' + matrix_server_fqn_matrix + ':3478?transport=udp', - 'turn:' + matrix_server_fqn_matrix + ':3478?transport=tcp', + 'turns:' + matrix_server_fqn_matrix + '?transport=udp', + 'turns:' + matrix_server_fqn_matrix + '?transport=tcp', + 'turn:' + matrix_server_fqn_matrix + '?transport=udp', + 'turn:' + matrix_server_fqn_matrix + '?transport=tcp', ] if matrix_coturn_enabled else [] diff --git a/roles/matrix-coturn/defaults/main.yml b/roles/matrix-coturn/defaults/main.yml index 7edd559b..b70c4058 100644 --- a/roles/matrix-coturn/defaults/main.yml +++ b/roles/matrix-coturn/defaults/main.yml @@ -38,3 +38,10 @@ matrix_coturn_allowed_peer_ips: [] matrix_coturn_denied_peer_ips: [] matrix_coturn_user_quota: null matrix_coturn_total_quota: null + +# To enable TLS, you need to provide paths to certificates. +# Paths defined in `matrix_coturn_tls_cert_path` and `matrix_coturn_tls_key_path` are in-container paths. +# Files on the host can be mounted into the container using `matrix_coturn_container_additional_volumes`. +matrix_coturn_tls_enabled: false +matrix_coturn_tls_cert_path: ~ +matrix_coturn_tls_key_path: ~ diff --git a/roles/matrix-coturn/tasks/setup_coturn.yml b/roles/matrix-coturn/tasks/setup_coturn.yml index 88a35618..619ed378 100644 --- a/roles/matrix-coturn/tasks/setup_coturn.yml +++ b/roles/matrix-coturn/tasks/setup_coturn.yml @@ -61,15 +61,40 @@ immediate: yes permanent: yes with_items: - - '3478/tcp' # STUN - - '3478/udp' # STUN + - '3478/tcp' + - '3478/udp' + - '5349/tcp' + - '5349/udp' - "{{ matrix_coturn_turn_udp_min_port }}-{{ matrix_coturn_turn_udp_max_port }}/udp" # TURN when: "matrix_coturn_enabled and ansible_os_family == 'RedHat'" +# This may be unnecessary when more long-lived certificates are used. +# We optimize for the common use-case though (short-lived Let's Encrypt certificates). +# Reloading doesn't hurt anyway, so there's no need to make this more flexible. +- name: Ensure periodic reloading of matrix-coturn is configured for SSL renewal (matrix-coturn-reload) + cron: + user: root + cron_file: matrix-coturn-ssl-reload + name: matrix-coturn-ssl-reload + state: present + hour: 4 + minute: 20 + day: "*/5" + job: /bin/systemctl reload matrix-coturn.service + when: matrix_coturn_enabled and matrix_coturn_tls_enabled + + # # Tasks related to getting rid of Coturn (if it was previously enabled) # +- name: Ensure matrix-coturn-ssl-reload cronjob removed + cron: + user: root + cron_file: matrix-coturn-ssl-reload + state: absent + when: "not matrix_coturn_enabled or not matrix_coturn_tls_enabled" + - name: Check existence of matrix-coturn service stat: path: "/etc/systemd/system/matrix-coturn.service" diff --git a/roles/matrix-coturn/templates/systemd/matrix-coturn.service.j2 b/roles/matrix-coturn/templates/systemd/matrix-coturn.service.j2 index 5cf569c2..b2d909f2 100644 --- a/roles/matrix-coturn/templates/systemd/matrix-coturn.service.j2 +++ b/roles/matrix-coturn/templates/systemd/matrix-coturn.service.j2 @@ -9,15 +9,19 @@ After={{ service }} Type=simple ExecStartPre=-/usr/bin/docker kill matrix-coturn ExecStartPre=-/usr/bin/docker rm matrix-coturn + ExecStart=/usr/bin/docker run --rm --name matrix-coturn \ --log-driver=none \ --user={{ matrix_user_uid }}:{{ matrix_user_gid }} \ --cap-drop=ALL \ + --entrypoint=turnserver \ --read-only \ --tmpfs=/var/tmp:rw,noexec,nosuid,size=100m \ --network={{ matrix_coturn_docker_network }} \ -p 3478:3478 \ -p 3478:3478/udp \ + -p 5349:5349 \ + -p 5349:5349/udp \ -p {{ matrix_coturn_turn_udp_min_port }}-{{ matrix_coturn_turn_udp_max_port }}:{{ matrix_coturn_turn_udp_min_port }}-{{ matrix_coturn_turn_udp_max_port }}/udp \ -v {{ matrix_coturn_config_path }}:/turnserver.conf:ro \ {% for volume in matrix_coturn_container_additional_volumes %} @@ -25,8 +29,14 @@ ExecStart=/usr/bin/docker run --rm --name matrix-coturn \ {% endfor %} {{ matrix_coturn_docker_image }} \ -c /turnserver.conf + ExecStop=-/usr/bin/docker kill matrix-coturn ExecStop=-/usr/bin/docker rm matrix-coturn + +# This only reloads certificates (not other configuration). +# See: https://github.com/coturn/coturn/pull/236 +ExecReload=/usr/bin/docker exec matrix-coturn kill -USR2 1 + Restart=always RestartSec=30 diff --git a/roles/matrix-coturn/templates/turnserver.conf.j2 b/roles/matrix-coturn/templates/turnserver.conf.j2 index a2689bc2..2bf7649c 100644 --- a/roles/matrix-coturn/templates/turnserver.conf.j2 +++ b/roles/matrix-coturn/templates/turnserver.conf.j2 @@ -1,23 +1,35 @@ use-auth-secret static-auth-secret={{ matrix_coturn_turn_static_auth_secret }} realm=turn.{{ matrix_server_fqn_matrix }} + min-port={{ matrix_coturn_turn_udp_min_port }} max-port={{ matrix_coturn_turn_udp_max_port }} external-ip={{ matrix_coturn_turn_external_ip_address }} + log-file=stdout pidfile=/var/tmp/turnserver.pid userdb=/var/tmp/turnserver.db + no-cli + +{% if matrix_coturn_tls_enabled %} +cert={{ matrix_coturn_tls_cert_path }} +pkey={{ matrix_coturn_tls_key_path }} +{% else %} no-tls no-dtls +{% endif %} + prod no-tcp-relay + {% if matrix_coturn_user_quota != None %} user-quota={{ matrix_coturn_user_quota }} {% endif %} {% if matrix_coturn_total_quota != None %} total-quota={{ matrix_coturn_total_quota }} {% endif %} + {% for ip_range in matrix_coturn_denied_peer_ips %} denied-peer-ip={{ ip_range }} {% endfor %} diff --git a/setup.yml b/setup.yml index 3db1e5ca..e2978f59 100755 --- a/setup.yml +++ b/setup.yml @@ -6,7 +6,6 @@ roles: - matrix-base - matrix-mailer - - matrix-coturn - matrix-postgres - matrix-corporal - matrix-synapse @@ -14,4 +13,5 @@ - matrix-mxisd - matrix-dimension - matrix-nginx-proxy + - matrix-coturn - matrix-common-after