BigBlueButton auch hinter Firewalls nutzen

mit einem eigenen STUN-/TURN-Server

Hinweis
Dieser Artikel wurde für BigBlueButton 2.2.x und 2.3.x geschrieben.

Mit den Tipps und Tricks aus meinem letzten Artikel "BigBlueButton grundlegend anpassen" sollte der Großteil deiner Nutzer:innen keine Probleme mit Verbindungen zu deinem BigBlueButton-Server haben. Wenn sich eine dieser jedoch hinter einer restriktiven Firewall befindet, hilft auch der hinterlegte STUN-Server nicht weiter. Hier muss der Netzwerkverkehr über einen zweiten Server – den sogenannten TURN-Server – "getunnelt" werden.

Ich zeige dir hier, was es mit den einzelnen Serverarten auf sich hat, welche beiden Fehler in diesem Fall bei BigBlueButton auftreten und wie du den STUN-/TURN-Server coturn installierst und für BigBlueButton konfigurierst.

* * *

Inhaltsverzeichnis

Was ist ein STUN-Server?
Was ist ein TURN-Server?
Was ist ICE?
Fehlermeldungen
    Fehler 1004 (Incompatible SDP)
    Fehler 1007 (ICE negotiation failed)
STUN-/TURN-Server installieren
STUN-/TURN-Server konfigurieren
    Konfiguration von coturn anpassen
    Zusätzliche Ports eintragen
    Authentifizierungs-Key generieren
    Domain anpassen
    SSL-Zertifikat hinterlegen
    Log-Datei anlegen
    coturn-Server Berechtigungen anpassen
        Möglichkeit 1: Dienst-Einstellungen anpassen
        Möglichkeit 2: Kernel-Capabilities anpassen
        Möglichkeit 3: Dienst als root laufen lassen
    Checkliste vor dem Start
    coturn-Server starten
    coturn-Server testen
BigBlueButton konfigurieren
Nachteil bei Nutzung von Port 80 und 443
Ports prüfen, auf denen coturn lauscht
    Problem: coturn bindet sich nicht an alle festgelegten Ports
    Problem: coturn bindet sich nicht an den oder die SSL-Ports
WebRTC-Fehlersuche im Browser
    WebRTC-Debugging in Firefox
    WebRTC-Debugging in Chromium / Chrome
Wieso gibt es keine öffentlichen TURN-Server?

Ich möchte für BigBlueButton einen STUN-/TURN-Server aufsetzen, habe dabei aber Schwierigkeiten
Weiterführende Links

* * *

Beide Serverarten werden meist synonym unter dem Begriff STUN-/TURN-Server zusammengefasst, verfolgen aber völlig unterschiedliche Konzepte. Lass uns daher erst einmal die Begrifflichkeiten klären:

Was ist ein STUN-Server?

Der STUN-Server [Simple Traversal of User Datagram Protocol [UDP] Through Network Address Translators] ist beim Verbindungsaufbau zwischen Client und Server behilflich, wenn sich der Client hinter einer Firewall befindet. Das ist bei den meisten PCs der Fall, die hinter einem Router angeschlossen sind. Er vermittelt alle für einen direkten Verbindungsaufbau zwischen Client und Server notwendigen Parameter (IP-Adressen, NAT-Ports usw.) zwischen beiden Teilnehmern.

Standardport: 3478 (unverschlüsselt)

Was ist ein TURN-Server?

Der TURN-Server [Traversal Using Relays around NAT] hingegen leitet den gesamten Datenverkehr als "Man-in-the-middle" ("Relay Server") vom Server zum Client und umgekehrt. Dadurch können beide Teilnehmer auch dann Daten austauschen, wenn es keine Möglichkeit gibt, eine direkte Verbindung aufzubauen.

Standardport: 5349 (unverschlüsselt und/oder verschlüsselt)

Was ist ICE?

Als ICE [Interactive Connectivity Establishment] wird das Protokoll bezeichnet, mit welchem Client und Server die mithilfe von STUN und TURN ermittelten Verbindungsinformationen (und andere Daten) austauschen können.

Grafische Erklärungen
Auf der Seite help.estos.com findest du unter dem Paragrafen "Anwendungsfälle" ein paar Grafiken, die die einzelnen Server- und Verbindungsarten sehr anschaulich erklären.

* * *

Fehlermeldungen

Wenn deine Nutzer:innen eine der folgenden Fehlermeldungen zu Gesicht bekommen, dann gibt es hierfür unterschiedliche Ursachen. Im Folgenden findest du die Ursachen der zwei gängigsten Fehlermeldungen 1004 und 1007, die im Zusammenhang mit dem Audio- und Videostream stehen, und mögliche Lösungen dafür.

Fehler 1004 (Incompatible SDP)

Lokal im Browser erscheinen nacheinander folgende Fehlermeldungen:

Konsole öffnen
Du kannst dir die Fehler anzeigen lassen, indem du die Entwicklertools deines Browsers öffnest. Tippe dazu in Firefox, Chromium oder Chrome auf [F12] oder mache einen Rechtsklick auf der Seite und klicke auf "Element untersuchen (Q)".

ICE failed, your TURN server appears to be broken, see about:webrtc for more details
ERROR: clientLogger: Audio call terminated. cause=Incompatible SDP
ERROR: clientLogger: Audio error – errorCode=1004, cause=Incompatible SDP

Ursache und Lösung

Ein Browser-Addon wie uBlock Origin oder Privacy Badger verhindert, dass WebRTC deine lokale IP-Adresse auslesen kann.

Lösung
Achte darauf, dass in den Einstellungen der beiden Addons die Weitergabe der IP-Adresse nicht blockiert wird (uBlock Origin: "Freigabe der lokalen IP-Adresse via WebRTC verhindern", Privacy Badger: "WebRTC hindern, die lokale IP-Adresse zu verraten").

Der STUN- und/oder der TURN-Server sind nicht erreichbar oder der Port, mit dem die Verbindung aufgebaut werden soll, wird von einer Firewall blockiert.

Lösung
Hier kannst du nachlesen, welche Firewall-Einstellungen auf deinem Server getätigt werden müssen: docs.bigbluebutton.org/admin/configure-firewall.html

Fehler 1007 (ICE negotiation failed)

Lokal im Browser erscheinen nacheinander folgende Fehlermeldungen:

Konsole öffnen
Du kannst dir die Fehler anzeigen lassen, indem du die Entwicklertools deines Browsers öffnest. Tippe dazu in Firefox, Chromium oder Chrome auf [F12] oder mache einen Rechtsklick auf der Seite und klicke auf "Element untersuchen (Q)".

Gewählte Einstellung bei BigBlueButton: Nur zuhören

WebRTC: ICE failed, add a TURN server and see about:webrtc for more details
ERROR: clientLogger: Listen only error – KURENTO_CALL_TIMEOUT – bridge: Kurento
ERROR: clientLogger: Listen only error – SIP_CALL_TIMEOUT – bridge: SIP
ERROR: clientLogger: ICE connection failed before success
ERROR: clientLogger: Audio error – errorCode=1007, cause=ICE negotiation failed. Current state – failed

Gegebenenfalls tritt parallel auf: Fehler: Verbindungsfehler

ERROR: clientLogger: WebRTC peer for listen only failed due to ICE transitioning to [...]
ERROR: clientLogger: Listen only failed when trying to start due to Undefined reason
ERROR: clientLogger: Audio error – errorCode=CONNECTION_ERROR, cause=Undefined reason
ERROR: clientLogger: Listen only error – Undefined reason – bridge: Kurento

Gewählte Einstellung bei BigBlueButton: Mit Mikrofon

WebRTC: ICE failed, add a TURN server and see about:webrtc for more details
ERROR: clientLogger: ICE connection failed before success 
ERROR: clientLogger: Audio error – errorCode=1007, cause=ICE negotiation failed.

Ursache und Lösung

Die Nutzer:in befindet sich hinter einer Firewall, die das Aushandeln individueller Ports für eine direkte Übertragung der Audio-/Videodaten verhindert.

Lösung
Einen eigenen TURN-Server aufsetzen und in der BigBlueButton-Konfiguration hinterlegen. Wie das geht, erkläre ich dir in der Sektion STUN-/TURN-Server installieren

Wenn es bei allen Nutzern auftritt:
Die Firewall auf Serverseite blockiert die notwendigen Ports oder der Server sitzt hinter einer Firewall bzw. einem Router (NAT) und wurde bezogen auf dieses Szenario nicht korrekt konfiguriert.

Lösung
Das NAT-Tutorial von BigBlueButton Schritt für Schritt nachvollziehen. Gegebenenfalls nachprüfen, ob Konfigurations-Dateien durch ein Update von BigBlueButton nachträglich wieder auf Werkseinstellungen zurückgesetzt wurden.

* * *

STUN-/TURN-Server installieren

Hierfür nutze ich coturn, eine Software, die sowohl STUN- als auch TURN-Server beinhaltet. Das Paket ist in den normalen Paketquellen von Debian und Ubuntu enthalten und lässt sich dadurch schnell installieren.
Folge einfach dem Tutorial aus der BigBlueButton-Dokumentation unter docs.bigbluebutton.org/admin/setup-turn-server.html. Dort ist alles ausführlich beschrieben und eine passende Konfigurationsdatei für BigBlueButton findest du dort ebenfalls.

Als Server reicht im Normalfall ein "kleiner VPS" von einem Hoster wie netcup. Wichtig sind nur eine gute Netzwerkanbindung, eine eigene IPv4-/IPv6-Adresse und eine eigene (Sub-)Domain, über die der Server später erreichbar sein wird.

Wichtig
Der coturn-Server darf nicht auf dem gleichen Server installiert werden, auf dem auch BigBlueButton installiert ist.

* * *

STUN-/TURN-Server konfigurieren

Als Orientierung verweise ich dich auf das Tutorial aus der BigBlueButton-Dokumentation.

Hinweis
Damit deine Nutzer:innen auch dann an Meetings teilnehmen können, wenn deren Firewall die standardmäßig verwendeten Ports von STUN/TURN (3478 und 5349) blockiert, konfiguriere ich den coturn-Server so, dass er zusätzlich die Ports 80 und 443 für die STUN-/TURN-Funktionalität nutzt, welche in der Regel freigeschaltet sind.

Konfiguration von coturn anpassen

Die Standardkonfiguration von BigBlueButton ist für coturn ein guter Ausgangspunkt.
Kopiere sie dir von hier oder aus der Dokumentation und füge den Inhalt bei dir in die Datei /etc/turnserver.conf ein:

# Example coturn configuration for BigBlueButton

# These are the two network ports used by the TURN server which the client
# may connect to. We enable the standard unencrypted port 3478 for STUN,
# as well as port 443 for TURN over TLS, which can bypass firewalls.
listening-port=3478
tls-listening-port=443

# If the server has multiple IP addresses, you may wish to limit which
# addresses coturn is using. Do that by setting this option (it can be
# specified multiple times). The default is to listen on all addresses.
# You do not normally need to set this option.
#listening-ip=172.17.19.101

# If the server is behind NAT, you need to specify the external IP address.
# If there is only one external address, specify it like this:
#external-ip=172.17.19.120
# If you have multiple external addresses, you have to specify which
# internal address each corresponds to, like this. The first address is the
# external ip, and the second address is the corresponding internal IP.
#external-ip=172.17.19.131/10.0.0.11
#external-ip=172.17.18.132/10.0.0.12

# Fingerprints in TURN messages are required for WebRTC
fingerprint

# The long-term credential mechanism is required for WebRTC
lt-cred-mech

# Configure coturn to use the "TURN REST API" method for validating time-
# limited credentials. BigBlueButton will generate credentials in this
# format. Note that the static-auth-secret value specified here must match
# the configuration in BigBlueButton's turn-stun-servers.xml
# You can generate a new random value by running the command:
#   openssl rand -hex 16
use-auth-secret
static-auth-secret=<random value>

# If the realm value is unspecified, it defaults to the TURN server hostname.
# You probably want to configure it to a domain name that you control to
# improve log output. There is no functional impact.
realm=example.com

# Configure TLS support.
# Adjust these paths to match the locations of your certificate files
cert=/etc/letsencrypt/live/turn.example.com/fullchain.pem
pkey=/etc/letsencrypt/live/turn.example.com/privkey.pem
# Limit the allowed ciphers to improve security
# Based on https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
cipher-list="ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS"

# Enable longer DH TLS key to improve security
dh2066

# All WebRTC-compatible web browsers support TLS 1.2 or later, so disable
# older protocols
no-tlsv1
no-tlsv1_1

# Log to a single filename (rather than new log files each startup). You'll
# want to install a logrotate configuration (see below)
log-file=/var/log/coturn.log

# To enable single filename logs you need to enable the simple-log flag
simple-log

Zusätzliche Ports eintragen

Damit dein coturn-Server auch über die standardmäßig freigeschalteten Ports 80 und 443 erreichbar ist, ersetze die ersten beiden Parameter in der Datei durch folgenden Inhalt:

# TURN listener port for UDP and TCP (Default: 3478).
# Note: actually, TLS & DTLS sessions can connect to the 
# "plain" TCP & UDP port(s), too – if allowed by configuration.
#
listening-port=80

# TURN listener port for TLS (Default: 5349).
# Note: actually, "plain" TCP & UDP sessions can connect to the TLS & DTLS
# port(s), too – if allowed by configuration. The TURN server 
# "automatically" recognizes the type of traffic. Actually, two listening
# endpoints (the "plain" one and the "tls" one) are equivalent in terms of
# functionality; but we keep both endpoints to satisfy the RFC 5766 specs.
# For secure TCP connections, we currently support SSL version 3 and 
# TLS version 1.0, 1.1 and 1.2.
# For secure UDP connections, we support DTLS version 1.
#
tls-listening-port=443

# Alternative listening port for UDP and TCP listeners;
# default (or zero) value means "listening port plus one". 
# This is needed for RFC 5780 support
# (STUN extension specs, NAT behavior discovery). The TURN Server 
# supports RFC 5780 only if it is started with more than one 
# listening IP address of the same family (IPv4 or IPv6).
# RFC 5780 is supported only by UDP protocol, other protocols
# are listening to that endpoint only for "symmetry".
#
alt-listening-port=3478

# Alternative listening port for TLS and DTLS protocols.
# Default (or zero) value means "TLS listening port plus one".
#
alt-tls-listening-port=5349

Authentifizierungs-Key generieren

Damit sich BigBlueButton am TURN-Server authentifizieren kann, wird ein static-auth-secret genutzt.
Das generierst du ganz einfach mit dem Befehl

openssl rand -hex 16

Trage den Schlüssel dann anstatt <random value> in die obige Datei ein:

static-auth-secret=<random value>

Wichtig
Behalte den Schlüssel für dich, denn mit diesem Schlüssel kann jede:r die TURN-Funktionalität deines Servers verwenden.

Domain anpassen

Die Angabe example.com ersetzt du durch die URL, unter der dein coturn-Server von außen erreichbar sein soll:

realm=example.com

SSL-Zertifikat hinterlegen

Damit die verschlüsselte Verbindung zu deinem Server aufgebaut werden kann, benötigt dieser noch die Pfade zu den Bestandteilen des SSL-Zertifikates. Nachdem du dir das Zertifikat über Let's Encrypt mit dem Befehl

certbot certonly --standalone -d turn.example.com

ausgestellt hast, trägst du die beiden Pfade in die Konfiguration ein:

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

Ersetze dabei turn.example.com durch die URL, unter der dein coturn-Server von außen erreichbar sein soll.

Achtung
Achte darauf, dass coturn unter dessen laufendem Linux-Benutzer die benötigten Berechtigungen besitzt, um die beiden Zertifikats-Bestandteile zu lesen und bis zu diesen navigieren zu dürfen (x-Recht).

Hinweis zur Erneuerung des SSL-Zertifikates

Attempting to renew cert (turn.example.com) from /etc/letsencrypt/renewal/turn.example.com.conf produced an unexpected error: Problem binding to port 80: Could not bind to IPv4 or IPv6. Skipping.

Bei Erneuerung des SSL-Zertifikates darauf achten, dass Port 80 währenddessen nicht belegt ist. Am besten erneuerst du das Zertifikat mit dem Befehl

certbot renew --pre-hook "systemctl stop coturn.service" --post-hook "systemctl start coturn.service"

Log-Datei anlegen

Bei meiner Installation konnte der Server aufgrund mangelnder Berechtigungen nicht in die standardmäßig angegebene Log-Datei /var/log/coturn.log schreiben. Leg die Datei, die in deiner Konfiguration angegeben ist, also entweder vorher mit den passenden Rechten an oder wähle einen Dateipfad, in welchem der Benutzer, unter dem der Prozess coturn läuft, Schreibrechte hat. In der Standardeinstellung läuft coturn unter Benutzer turnserver und Gruppe turnserver.

log-file=/var/log/coturn.log

coturn-Server Berechtigungen anpassen

Da der coturn-Server standardmäßig nicht mit root-Berechtigungen läuft, darf er seine Dienste nicht an privilegierte Ports (Portbereich < 1024) binden. Da wir aus diesem Bereich Port 80 und 443 verwenden möchten, gibt es drei Möglichkeiten, das zu ändern, wobei ich die erste Möglichkeit empfehle:

Möglichkeit 1: Dienst-Einstellungen anpassen

Führe den Befehl systemctl edit coturn aus und füge folgenden Inhalt ein:

[Service]
AmbientCapabilities=CAP_NET_BIND_SERVICE

Nach dem Speichern übernimmst du die Service-Anpassungen mit systemctl daemon-reload.

Da du die Änderungen nicht direkt in der Datei /lib/systemd/system/coturn.service getätigt hast, bleiben Sie auch nach einem Update von coturn bestehen.

Möglichkeit 2: Kernel-Capabilities anpassen

Installiere hierzu mit apt install libcap2-bin das Tool setcap aus dem Debian-Repository.

Mit which turnserver erhältst du den vollen Pfad für den TURN-Server und mit

/sbin/setcap 'cap_net_bind_service=+ep' /usr/bin/turnserver

passt du die Berechtigungen für die ausführbare Datei des TURN-Servers an.
Ersetze /usr/bin/turnserver hier durch deinen Rückgabewert aus dem Befehl which turnserver.

Möglichkeit 3: Dienst als root laufen lassen

Warnung
Diese Methode ist ausdrücklich NICHT für den Produktivbetrieb empfohlen und sollte nur zu Fehlersuchzwecken eingesetzt werden. Beispielsweise, wenn das SSL-Zertifikat für die Domain aufgrund falscher Berechtigungen nicht gelesen oder die Log-Datei nicht geschrieben werden kann.

Führe den Befehl systemctl edit coturn aus und füge folgenden Inhalt ein:

[Service]
User=root

Nach dem Speichern übernimmst du die Service-Anpassungen mit systemctl daemon-reload.

Da du die Änderungen nicht direkt in der Datei /lib/systemd/system/coturn.service getätigt hast, bleiben Sie auch nach einem Update von coturn bestehen.

Checkliste vor dem Start

  • Sind die Pfade zu den SSL-Zertifikatsbestandteilen korrekt in /etc/turnserver.conf hinterlegt?
  • Sind die SSL-Zertifikatsbestandteile für den Benutzer, unter dem der Prozess coturn gestartet wurde, lesbar (r)?
  • Darf der Benutzer, unter dem der Prozess coturn gestartet wurde, in den / die Ordner mit den SSL-Zertifikatsbestandteilen navigieren (x)?
  • Ist die Log-Datei für den Benutzer, unter dem der Prozess coturn gestartet wurde, schreibbar (w)?
  • Gibt es auf dem Server andere Dienste, die bereits einen der vier verwendeten Ports 80, 443, 3478 und 5349 belegen?

coturn-Server starten

Nun ist alles korrekt konfiguriert und du kannst deinen Server das erste Mal starten.

Vorher noch in der Datei /etc/default/coturn die Zeile

#
# Uncomment it if you want to have the turnserver running as 
# an automatic system service daemon
#
TURNSERVER_ENABLED=1

einkommentieren, damit der Server auch automatisch gestartet wird. Danach kannst du den coturn-Server starten:

systemctl start coturn

coturn-Server testen

Den STUN-Server kannst du ganz einfach über Trickle ICE testen. Hier muss bei Angabe deiner Domain im Schema stun:turn.example.com mindestens ein Eintrag mit dem Wert srflx zurückgegeben werden.

Den TURN-Server testest du am Besten, indem du dich von einem PC einwählst, der nur auf Port 80 und 443 Zugriff ins Internet hat. Wenn du dich dann mit Sprach- und Videoübertragung in eine BigBlueButton-Sitzung einwählen kannst, funktioniert der TURN-Server.

Ansonsten findest du in der Sektion WebRTC-Fehlersuche im Browser noch weitere Debugging-Möglichkeiten deines TURN-Servers. Auch die Konsole deines Browsers gibt reichlich Auskunft über die Verbindungsaufhandlung und die verwendeten oder ggf. nicht gefundenen STUN-/TURN-Server. Wie du die Konsole öffnest, ist weiter oben bei den beiden Fehlerarten Fehler 1004 und Fehler 1007 beschrieben.

* * *

BigBlueButton konfigurieren

Jetzt fehlt nur noch der Eintrag deines STUN-/TURN-Servers in der BigBlueButton-Konfigurationsdatei. Öffne dazu die Datei /usr/share/bbb-web/WEB-INF/classes/spring/turn-stun-servers.xml auf deinem BigBlueButton-Server und kopiere dir den Inhalt von hier oder aus der Dokumentation:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

    <bean id="stun0" class="org.bigbluebutton.web.services.turn.StunServer">
        <constructor-arg index="0" value="stun:turn.example.com"/>
    </bean>


    <bean id="turn0" class="org.bigbluebutton.web.services.turn.TurnServer">
        <constructor-arg index="0" value="<random value>"/>
        <constructor-arg index="1" value="turns:turn.example.com:443?transport=tcp"/>
        <constructor-arg index="2" value="86400"/>
    </bean>

    <bean id="turn1" class="org.bigbluebutton.web.services.turn.TurnServer">
        <constructor-arg index="0" value="<random value>"/>
        <constructor-arg index="1" value="turn:turn.example.com:443?transport=tcp"/>
        <constructor-arg index="2" value="86400"/>
    </bean>

    <bean id="stunTurnService"
            class="org.bigbluebutton.web.services.turn.StunTurnService">
        <property name="stunServers">
            <set>
                <ref bean="stun0"/>
            </set>
        </property>
        <property name="turnServers">
            <set>
                <ref bean="turn0"/>
                <ref bean="turn1"/>
            </set>
        </property>
    </bean>
</beans>

Ersetze jeweils die Angaben turn.example.com durch die URL, unter der dein coturn-Server erreichbar ist und <random value> durch deinen generierten Authentifizierungs-Key.

Anschließend startest du den BigBlueButton-Server neu:

bbb-conf --restart

Von nun an wird der Netzwerkverkehr deines Servers über deinen eigenen STUN-/TURN-Server geleitet und auch Nutzer:innen, die hinter einer Firewall sitzen, können problemlos an deinen BigBlueButton-Sitzungen teilnehmen.

* * *

Nachteil bei Nutzung von Port 80 und 443

Einen Nachteil gibt es, wenn man coturn an die beiden Ports 80 und 443 bindet: Es kommen allerlei Anfragen aus dem Internet, die keine STUN-/TURN-Requests sind und dennoch in den Log-Dateien auftauchen.

Eine effektive Gegenmaßnahme ist mir leider nicht bekannt – wenn du eine kennst, hinterlasse mir gerne einen Kommentar unter diesem Artikel.

17037: IPv4. tcp or tls connected to: 128.14.134.170:59844
17038: session 000000000000000039: client socket to be closed in client handler: ss=0x7fc8cc0a9ca0
17038: session 000000000000000039: usage: realm=<turn.example.com>, username=<>, rp=1, rb=206, sp=0, sb=0
17038: session 000000000000000039: closed (2nd stage), user <> realm <turn.example.com> origin <>, local 11.22.33.44
17038: session 000000000000000039: SSL shutdown received, socket to be closed (local 11.22.33.44:443, remote 128.14.134.170
17323: IPv4. tcp or tls connected to: 61.219.11.153:64550
17325: session 001000000000000040: client socket to be closed in client handler: ss=0x7fc8d40591c0
17325: session 001000000000000040: usage: realm=<turn.example.com>, username=<>, rp=1, rb=18, sp=0, sb=0
17325: session 001000000000000040: closed (2nd stage), user <> realm <turn.example.com> origin <>, local 11.22.33.44
17592: IPv4. tcp or tls connected to: 195.54.160.135:53184
17592: session 001000000000000041: client socket to be closed in client handler: ss=0x7fc8d40591c0
17592: session 001000000000000041: usage: realm=<turn.example.com>, username=<>, rp=1, rb=303, sp=0, sb=0
17592: session 001000000000000041: closed (2nd stage), user <> realm <turn.example.com> origin <>, local 11.22.33.44
* * *

Ports prüfen, auf denen coturn lauscht

Um herauszufinden, an welche Ports sich coturn nach dem Start wirklich bindet, reicht es, den Dienst neu zu starten und daraufhin in die Log-Datei zu schauen: systemctl restart coturn.service ; tail -n 100 /var/log/coturn.log.

Alternativ dazu kannst du mit dem Befehl ss -alp | grep turnserver auch ohne Neustart des Dienstes nachsehen, auf welchen Ports der Dienst lauscht.

Problem: coturn bindet sich nicht an alle festgelegten Ports

Nach mehreren Monaten Betriebszeit habe ich außerdem festgestellt, dass der Server nicht (mehr) wie in meiner Konfiguration vorgegeben auf allen vier Ports (80, 443, 3478 und 5349) lauscht, sondern nur noch auf den ersten beiden.

Grund dafür ist das Setzen des Parameters listening-ip mit nur einer IP-Adresse:

# If the server has multiple IP addresses, you may wish to limit which
# addresses coturn is using. Do that by setting this option (it can be
# specified multiple times). The default is to listen on all addresses.
# You do not normally need to set this option.
listening-ip=123.123.123.123

Der Server bindet an diese IP-Adresse daraufhin nur noch die beiden Ports, welche unter listening-port bzw. tls-listening-port definiert sind. Die Angaben alt-listening-port und alt-tls-listening-port werden stillschweigend ignoriert.

Für den Fall, dass du den coturn-Server also nur mit einer IP-Adresse nutzt, aber an alle vier Ports binden möchtest, solltest du diesen Parameter auskommentiert lassen.

Problem: coturn bindet sich nicht an den oder die SSL-Ports

Das kann daran liegen, dass der Benutzer, unter dem der coturn-Server läuft, nicht auf die SSL-Zertifikatsbestandteile zugreifen darf. Da coturn hier (auch mit eingestelltem verbose Parameter für die Log-Datei) keine Fehlermeldung bringt, tappt man erstmal im Dunkeln. Und wenn dann nocht ein Let's Encrypt-Zertifikat in Kombination mit certbot zum Einsatz kommt, gibt es einige weitere Fallstricke.

Prüfe also der Reihe nach:

  1. Sind die Pfade für die beiden SSL-Zertifikatsbestandteile (cert und pkey) in der Datei /etc/turnserver.conf korrekt?
  2. Sind die Berechtigungen für die SSL-Zertifikatsbestandteile korrekt gesetzt?

    Da coturn als Benutzer turnserver mit der Gruppe turnserver läuft, müssen die Zertifikatsbestandteile für diesen Benutzer lesbar sein. Auch erneuert certbot alle zwei Monate die Zertifikate, so dass nach einer Erneuerung des Zertifikats die Berechtigungen nachgezogen werden müssen.

  3. Wenn Let's Encrypt zum Einsatz kommt, dann müssen beide Zertifikatspfade für den Benutzer, unter dem der coturn Prozess läuft, erreichbar sein.

    Denn die eigentlichen Zertifikatsbestandteile liegen an einem anderen Ort, als du ihn in deiner Konfigurationsdatei hinterlegt hast. Da du bei einem Verweis auf diese alle zwei Monate den Pfad in der coturn-Konfigurationsdatei korrigieren müsstest, gibt es bei Let's Encrypt Symlinks auf die jeweils aktuellen Zertifikatsbestandteile.

    Das sind die, welche du auch in deiner Konfigurationsdatei hinterlegt hast. Der Grund ist, dass die eigentlichen Zertifikatsbestandteile im Namen eine Zahl tragen (hier das X), die bei jedem Erneuerungsvorgang von certbot um eins hochgezählt wird.

    Eigentliche Zertifikatsbestandteile:
    /etc/letsencrypt/archive/turn.meinedomain.de/fullchainX.pem
    /etc/letsencrypt/archive/turn.meinedomain.de/privkeyX.pem

    Symlinks
    /etc/letsencrypt/live/turn.meinedomain.de/fullchain.pem
    /etc/letsencrypt/live/turn.meinedomain.de/privkey.pem

    Wieso ist das wichtig?
    Der turnserver muss nicht nur Zugriff auf den Dateiinhalt der eigentlichen Zertifikatsbestandteile bekommen (Lesen), sondern auch auf beide Dateipfade zugreifen dürfen (Execute).

Meine Empfehlungen

Lese-Berechtigung für das aktuelle Zertifikat setzen (muss nach jeder Zertifikats-Erneuerung erneut gemacht werden):

chown turnserver /etc/letsencrypt/live/turn.meinedomain.de/fullchain.pem
chown turnserver /etc/letsencrypt/live/turn.meinedomain.de/privkey.pem

Pfad-Zugriff gewähren:

chmod +x /etc/letsencrypt/live
chmod +x /etc/letsencrypt/archive
chmod 755 /etc/letsencrypt/live/turn.meinedomain.de
chmod 755 /etc/letsencrypt/archive/turn.meinedomain.de

Nach einem Neustart des coturn-Servers mit systemctl restart coturn.service sollte er sich korrekt an die beiden SSL-Ports binden.

* * *

WebRTC-Fehlersuche im Browser

Du kannst auf einem Client ganz einfach herausfinden, ob es Probleme beim Aufbau einer Verbindung zum STUN-/TURN-Server gibt. Nehme dazu an einer BigBlueButton-Sitzung teil und öffne parallel einen der folgenden Links in einem neuen Tab:

WebRTC-Debugging in Firefox

about:webrtc

WebRTC-Debugging in Chromium / Chrome

chrome://webrtc-internals/
chrome://webrtc-logs/

Der folgende Screenshot zeigt die Ansicht aus Firefox. Nachdem du oben auf "Details einblenden" geklickt hast, klappen die ICE-Statistiken auf. An der Farbe der ersten Spalte siehst du, ob der Verbindungsaufbau zum Server erfolgreich war (grün), sich noch im Aufbau befindet (transparent), fehlgeschlagen ist (rot) oder abgebrochen wurde (gelb).

* * *

Wieso gibt es keine öffentlichen TURN-Server?

Öffentliche STUN-Server gibt es zu Hauf, z. B. hier und hier. Das liegt daran, dass sie außer den IP-Adressen der beiden Teilnehmer keine datenschutzrelevanten Daten übertragen. Außerdem sind die übertragenenen Datenmengen gering, sodass man viele Teilnehmer mit einem Server versorgen kann.

Anders sieht es hingegen bei einem TURN-Server aus. Dieser "tunnelt" den gesamten Netzwerkverkehr zwischen Client und Server und könnte als "Man-in-the-middle" den gesamten Netzwerkverkehr mitschneiden oder manipulieren. Dadurch benötigt der Server ein Vielfaches an Bandbreite, denn er muss den gesamten Datenstrom an Audio- und Videodaten empfangen und wieder senden.

Wenn du mehr wissen willst, findest du hier einen (englischen) Artikel zu dem Thema:
Why Doesn't Google Provide a Free TURN Server?

* * *

Ich möchte für BigBlueButton einen STUN-/TURN-Server aufsetzen, habe dabei aber Schwierigkeiten

Ich unterstütze dich gerne bei der Installation eines eigenen STUN-/TURN-Servers für BigBlueButton.
Schreib mir hierzu einfach über Kontakt, per Telegram oder unten in die Kommentare eine Nachricht.

* * *

Prozess an Port 80 und 443 binden

SSL-Datei nicht lesbar

* * *

Änderungshistorie

26.07.2021, 22:45 – Tote Links zur BigBlueButton-Dokumentation repariert
18.05.2021, 10:45 – Link zum Matrix-Austauschkanal ergänzt
17.05.2021, 17:50 – Ergänzen der Passage "Problem: coturn bindet sich nicht an den oder die SSL-Ports" und Korrigieren der Serviceanpassungen für privilegierte Ports
30.11.2020, 16:20 – Ergänzen der Passage "Ports prüfen, auf denen coturn lauscht"
02.08.2020, 23:30 – Artikel veröffentlicht
21.06.2020, 22:34 – Artikel erstellt

* * *
Christian Süßenguth Christian Süßenguth @sweetgood

Hi, ich bin Christian und Inhaber der Firma SWEETGOOD. Mit dem andersGOOD Blog möchte ich auch dich für datensichere IT-Lösungen begeistern. So bringst du dein Unternehmen voran, ohne großen Konzernen deine wertvollen Daten zu liefern. Probiers mal anders!


Kommentarbereich

Die Kommentare sind für dich noch deaktiviert, da du dem Setzen von Cookies bisher nicht zugestimmt hast.
Klicke oben rechts auf "Ja, klar!" und lade die Seite neu, um die Kommentare anzuzeigen.

Seite neu laden

👾 Magst du Kekse?

Ich würde gerne Cookies setzen

Ist das OK für dich?