Allow STUN/TURN exposure over TCP/UDP to be controlled separately & disable STUN over UDP by default

This commit is contained in:
Slavi Pantaleev 2025-02-19 11:48:12 +02:00
parent 1c61a3d332
commit ac26cc1cb0
6 changed files with 60 additions and 16 deletions

View File

@ -1,3 +1,25 @@
# 2025-02-19
## The playbook now defaults to exposing the Coturn STUN port (3478) only over TCP
We've previously done some work to **decrease the severity** of DDoS amplification attacks done through the [Coturn](./docs/configuring-playbook-turn.md)'s STUN port (2.8x -> 1.6x) as reported in [coturn: Lower DDoS amplification/reflection factor from 2.8 to 1.6 #2592](https://github.com/spantaleev/matrix-docker-ansible-deploy/issues/2592).
To **completely eliminate the problem** of DDoS amplification attacks done through the [Coturn](./docs/configuring-playbook-turn.md) STUN port even further (read more about this in [this article](https://stormwall.network/resources/blog/protect-against-ddos-based-on-stun-exploit)), the playbook now **disables exposure of the Coturn STUN port (`3478`) over UDP**. This is a bit heavy-handed, but is probably the only way to completely eliminate the problem.
The playbook now **only exposes the Coturn STUN port (`3478`) over TCP by default**.
💡 Users may wish to further remove the (now unnnecessary) firewall rule allowing access to `3478/udp`.
If you'd like the Coturn STUN port to be exposed over UDP like before, you can revert to the previous behavior by using the following configuration in your `vars.yml` file:
```yaml
matrix_coturn_container_stun_plain_host_bind_port_udp: "3478"
```
> [!WARNING]
> People running Coturn directly on the `host` network (using `matrix_coturn_container_network: host`) will still have the STUN port exposed over UDP, as port exposure is done directly via Coturn and not via Docker. In such cases, the playbook cannot prevent `3478/udp` port exposure and you'd need to do it in another way (separate firewall rule, etc).
# 2025-02-17
## FluffyChat Web suport

View File

@ -48,10 +48,9 @@ We will be using `example.com` as the domain in the following instruction. Pleas
- `80/tcp`: HTTP webserver
- `443/tcp` and `443/udp`: HTTPS webserver
- `3478/tcp`: TURN over TCP (used by coturn)
- `3478/udp`: TURN over UDP (used by coturn)
- `5349/tcp`: TURN over TCP (used by coturn)
- `5349/udp`: TURN over UDP (used by coturn)
- `3478/tcp`: STUN/TURN over TCP (used by [coturn](./docs/configuring-playbook-turn.md))
- `5349/tcp`: TURN over TCP (used by [coturn](./docs/configuring-playbook-turn.md))
- `5349/udp`: TURN over UDP (used by [coturn](./docs/configuring-playbook-turn.md))
- `8448/tcp` and `8448/udp`: Matrix Federation API HTTPS webserver. Some components like [Matrix User Verification Service](configuring-playbook-user-verification-service.md#open-matrix-federation-port) require this port to be opened **even with federation disabled**.
- the range `49152-49172/udp`: TURN over UDP
- potentially some other ports, depending on the additional (non-default) services that you enable in the **configuring the playbook** step (later on). Consult each service's documentation page in `docs/` for that.

View File

@ -3615,8 +3615,8 @@ jitsi_web_framing_enabled: true
jitsi_turn_credentials: "{{ matrix_coturn_turn_static_auth_secret if (matrix_coturn_enabled and matrix_coturn_authentication_method == 'auth-secret') else '' }}"
jitsi_turn_host: "{{ ('turn.' + matrix_server_fqn_matrix) if matrix_coturn_enabled else '' }}"
jitsi_turns_host: "{{ ('turn.' + matrix_server_fqn_matrix) if matrix_coturn_enabled else '' }}"
jitsi_turn_port: "{{ matrix_coturn_container_stun_plain_host_bind_port.split(':')[-1] if matrix_coturn_enabled else '' }}"
jitsi_turns_port: "{{ matrix_coturn_container_stun_tls_host_bind_port.split(':')[-1] if matrix_coturn_enabled else '' }}"
jitsi_turn_port: "{{ matrix_coturn_container_stun_plain_host_bind_port_tcp.split(':')[-1] if matrix_coturn_enabled else '' }}"
jitsi_turns_port: "{{ matrix_coturn_container_stun_tls_host_bind_port_tcp.split(':')[-1] if matrix_coturn_enabled else '' }}"
# If the self-hosted Etherpad instance is available, it will also show up in Jitsi conferences,
# unless explicitly disabled by setting `jitsi_etherpad_enabled` to false.

View File

@ -51,15 +51,32 @@ matrix_coturn_container_additional_volumes: []
# A list of extra arguments to pass to the container
matrix_coturn_container_extra_arguments: []
# Controls whether the coturn container exposes its plain STUN port (tcp/3478 and udp/3478 in the container).
# Controls whether the coturn container exposes its plain STUN port (tcp/3478 in the container) over TCP.
#
# Takes an "<ip>:<port>" or "<port>" value (e.g. "127.0.0.1:3478"), or empty string to not expose.
matrix_coturn_container_stun_plain_host_bind_port: "{{ '3478' if matrix_coturn_container_network != 'host' else '' }}"
matrix_coturn_container_stun_plain_host_bind_port_tcp: "{{ '3478' if matrix_coturn_container_network != 'host' else '' }}"
# Controls whether the coturn container exposes its TLS STUN port (tcp/5349 and udp/5349 in the container).
# Controls whether the coturn container exposes its plain STUN port (udp/3478 in the container) over UDP.
#
# Takes an "<ip>:<port>" or "<port>" value (e.g. "127.0.0.1:3478"), or empty string to not expose.
#
# This is not done by default to decrease the risk of DDoS amplification attacks.
# See: https://stormwall.network/resources/blog/protect-against-ddos-based-on-stun-exploit
matrix_coturn_container_stun_plain_host_bind_port_udp: ""
# Controls whether the coturn container exposes its TLS STUN port (tcp/5349 in the container) over TCP.
#
# Takes an "<ip>:<port>" or "<port>" value (e.g. "127.0.0.1:5349"), or empty string to not expose.
matrix_coturn_container_stun_tls_host_bind_port: "{{ '5349' if matrix_coturn_container_network != 'host' else '' }}"
matrix_coturn_container_stun_tls_host_bind_port_tcp: "{{ '5349' if matrix_coturn_container_network != 'host' else '' }}"
# Controls whether the coturn container exposes its TLS STUN port (udp/5349 in the container) over UDP.
#
# Takes an "<ip>:<port>" or "<port>" value (e.g. "127.0.0.1:5349"), or empty string to not expose.
#
# This is enabled by default, unlike `matrix_coturn_container_stun_plain_host_bind_port_udp`,
# because the risk of DDoS amplification attacks is lower for TLS
# due to the handshake requiring two-way authentication and being generally more expensive.
matrix_coturn_container_stun_tls_host_bind_port_udp: "{{ '5349' if matrix_coturn_container_network != 'host' else '' }}"
# Controls whether the coturn container exposes its TURN UDP port range and which interface to do it on.
#

View File

@ -8,6 +8,8 @@
when: "item.old in vars"
with_items:
- {'old': 'matrix_coturn_docker_network', 'new': 'matrix_coturn_container_network'}
- {'old': 'matrix_coturn_container_stun_plain_host_bind_port', 'new': 'superseded by matrix_coturn_container_stun_plain_host_bind_port_tcp and matrix_coturn_container_stun_plain_host_bind_port_udp'}
- {'old': 'matrix_coturn_container_stun_tls_host_bind_port', 'new': 'superseded by matrix_coturn_container_stun_tls_host_bind_port_tcp and matrix_coturn_container_stun_tls_host_bind_port_udp'}
- name: Fail if matrix_coturn_authentication_method is invalid
ansible.builtin.fail:

View File

@ -24,13 +24,17 @@ ExecStartPre={{ devture_systemd_docker_base_host_command_docker }} create \
--read-only \
--tmpfs=/var/tmp:rw,noexec,nosuid,size=100m \
--network={{ matrix_coturn_container_network }} \
{% if matrix_coturn_container_stun_plain_host_bind_port != '' %}
-p {{ matrix_coturn_container_stun_plain_host_bind_port }}:3478 \
-p {{ matrix_coturn_container_stun_plain_host_bind_port }}:3478/udp \
{% if matrix_coturn_container_stun_plain_host_bind_port_tcp != '' %}
-p {{ matrix_coturn_container_stun_plain_host_bind_port_tcp }}:3478 \
{% endif %}
{% if matrix_coturn_container_stun_tls_host_bind_port != '' %}
-p {{ matrix_coturn_container_stun_tls_host_bind_port }}:5349 \
-p {{ matrix_coturn_container_stun_tls_host_bind_port }}:5349/udp \
{% if matrix_coturn_container_stun_plain_host_bind_port_udp != '' %}
-p {{ matrix_coturn_container_stun_plain_host_bind_port_udp }}:3478/udp \
{% endif %}
{% if matrix_coturn_container_stun_tls_host_bind_port_tcp != '' %}
-p {{ matrix_coturn_container_stun_tls_host_bind_port_tcp }}:5349 \
{% endif %}
{% if matrix_coturn_container_stun_tls_host_bind_port_udp != '' %}
-p {{ matrix_coturn_container_stun_tls_host_bind_port_udp }}:5349/udp \
{% endif %}
{% if matrix_coturn_container_turn_range_listen_interface is not in [none, 'none'] %}
-p {{ matrix_coturn_container_turn_range_listen_interface }}{{ ':' if matrix_coturn_container_turn_range_listen_interface else '' }}{{ 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 \