STUN/TURN Server(Coturn) on Docker

BigBlueButton on Dockerで用意されたSTUN/TURNサーバであるCoturnはメンテナンスが維持されていない状態のため、公式版のDockerイメージに置き換えます。

Coturnは、NATやファイヤーウォールの背後に位置する端末間のIP接続を確立するために必要な中継サーバであるSTUN/TURNサーバです。リアルタイムの音声や映像などの両者間通信に必要となるIPとポートは、Coturnにより管理・選定されます。

Docker Hub
https://hub.docker.com/r/coturn/coturn

GitHub:Docker Coturn

デフォルトのデータベースはSQLiteのため別途サーバは必要ありません。Redis, PostgreSQL, MongoDB, MySQLなど他のデータベースを利用する場合は、設定ファイルで各種パラメータを設定すること。


参考) ICE, STUN, TURN

セキュリティ

デフォルトではtelnetによるアクセスが出来てしまうため、ロングパスワードの設定、または cli によるアクセスを無効とすること。

/etc/turnserver.conf

# Turn OFF the CLI support.
# By default it is always ON.
# See also options cli-ip and cli-port.
#
#no-cli

#Local system IP address to be used for CLI server endpoint. Default value
# is 127.0.0.1.
#
cli-ip=127.0.0.1

# CLI server port. Default is 5766.
#
cli-port=5766

# CLI access password. Default is empty (no password).
# For the security reasons, it is recommended that you use the encrypted
# form of the password (see the -P command in the turnadmin utility).
#
# Secure form for password 'qwerty':
#
cli-password=$5$79a316b350311570$81df9cfb9af7f5e5a76eada31e7097b663a0670f99a3c07ded3f1c8e59c5658a

パスワードの作成

OpenSSL

$ openssl passwd -5 passward

openssl passwd HELP

$ openssl passwd -help
Usage: passwd [options]
Valid options are:
 -help               Display this summary
 -in infile          Read passwords from file
 -noverify           Never verify when reading password from terminal
 -quiet              No warnings
 -table              Format output as table
 -reverse            Switch table columns
 -salt val           Use provided salt
 -stdin              Read passwords from stdin
 -6                  SHA512-based password algorithm
 -5                  SHA256-based password algorithm
 -apr1               MD5-based password algorithm, Apache variant
 -1                  MD5-based password algorithm
 -aixmd5             AIX MD5-based password algorithm
 -crypt              Standard Unix password algorithm (default)
 -rand val           Load the file(s) into the random number generator
 -writerand outfile  Write random data to the specified file

/dev/urandom

$ head /dev/urandom | tr -dc A-Za-z0-9 | head -c 40

Reason: TLS/TCP socket buffer operation error (callback)

/etc/coturn/turnserver.conf

.....
.....
.....
# Do not allow an TLS/DTLS version of protocol
#
no-tlsv1
no-tlsv1_1

turnadmin

# turnadmin -a --help                                         

Usage: turnadmin [command] [options]

Commands:

	-P, --generate-encrypted-password	Generate and print to the standard
					output an encrypted form of a password
					(for web admin user or CLI). See wiki, README or man
					pages for more detailed description.
	-k, --key			generate long-term credential mechanism key for a user
	-a, --add			add/update a long-term mechanism user
	-A, --add-admin			add/update a web admin user
	-d, --delete			delete a long-term mechanism user
	-D, --delete-admin		delete an admin user
	-l, --list			list all long-term mechanism users
	-L, --list-admin		list all admin users
	-s, --set-secret=<value>	Add shared secret for TURN REST API
	-S, --show-secret		Show stored shared secrets for TURN REST API
	-X, --delete-secret=<value>	Delete a shared secret
	    --delete-all-secrets	Delete all shared secrets for REST API
	-O, --add-origin		Add origin-to-realm relation.
	-R, --del-origin		Delete origin-to-realm relation.
	-I, --list-origins		List origin-to-realm relations.
	-g, --set-realm-option		Set realm params: max-bps, total-quota, user-quota.
	-G, --list-realm-options	List realm params.
	-E, --generate-encrypted-password-aes	Generate and print to the standard
					output an encrypted form of password with AES-128

Options with mandatory values:

	-b, --db, --userdb		SQLite database file, default value is /var/db/turndb or
					  /usr/local/var/db/turndb or /var/lib/turn/turndb.
	-e, --psql-userdb, --sql-userdb	PostgreSQL user database connection string, if PostgreSQL DB is used.
	-M, --mysql-userdb		MySQL user database connection string, if MySQL DB is used.
	-J, --mongo-userdb		MongoDB user database connection string, if MongoDB is used.
	-N, --redis-userdb		Redis user database connection string, if Redis DB is used.
	-u, --user			Username
	-r, --realm			Realm
	-p, --password			Password
	-x, --key-path			Generates a 128 bit key into the given path.
	-f, --file-key-path		Contains a 128 bit key in the given path.
	-v, --verify			Verify a given base64 encrypted type password.
	-o, --origin			Origin
	--max-bps			Set value of realm's max-bps parameter.
					Setting to zero value means removal of the option.
	--total-quota			Set value of realm's total-quota parameter.
					Setting to zero value means removal of the option.
	--user-quota			Set value of realm's user-quota parameter.
					Setting to zero value means removal of the option.
	-h, --help			Help

コンテナ内で long-term mechanism user を追加し、下記サイトで動作確認。

# turnadmin -a -u user001 -r stun.example.com -p turn_password

turnutils_uclient:TLS接続の確認

下記 turnutil_uclient によりTURN/STUNサーバへのTLS接続を確認。
オプションでLetsencryptから取得した証明書とプライベートキー、TLS接続ポート、 turnserver.conf で設定した認証パスワード static-auth-secret を指定。

# turnutils_uclient -S -i /etc/letsencrypt/live/www.example.com/fullchain.pem -k /etc/letsencrypt/live/www.example.com/privkey.pem -p 5349 -W xxxxxxxxxxxxxxx xx.xx.xx.xx
0: : tls_connect: cannot connect: rc=-1, ctx=0
0: : tls_connect: cannot connect: rc=-1, ctx=0
0: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
0: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
1: : tls_connect: cannot connect: rc=-1, ctx=0
1: : tls_connect: cannot connect: rc=-1, ctx=0
1: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
1: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
3: : tls_connect: cannot connect: rc=-1, ctx=0
3: : tls_connect: cannot connect: rc=-1, ctx=0
3: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
3: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
4: : tls_connect: cannot connect: rc=-1, ctx=0
4: : tls_connect: cannot connect: rc=-1, ctx=0
4: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
4: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
5: : tls_connect: cannot connect: rc=-1, ctx=0
5: : tls_connect: cannot connect: rc=-1, ctx=0
5: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
5: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
6: : tls_connect: cannot connect: rc=-1, ctx=0
6: : tls_connect: cannot connect: rc=-1, ctx=0
6: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
6: : errno=0, err=0, error:1410242E:SSL routines:dtls1_read_bytes:tlsv1 alert protocol version (1)
9: : tls_connect: client session connected with cipher ECDHE-RSA-AES128-GCM-SHA256, method=DTLSv1.2
9: : tls_connect: client session connected with cipher ECDHE-RSA-AES128-GCM-SHA256, method=DTLSv1.2
10: : Received wrong response tid; trying again...
10: : Received wrong response tid; trying again...

README.turnutils

turnserver.conf

https://matrix-org.github.io/synapse/develop/turn-howto.html#configuration

(1) Create or edit the config file in /etc/turnserver.conf. The relevant lines, with example values, are:

use-auth-secret
static-auth-secret=[your secret key here]
realm=turn.myserver.org

See turnserver.conf for explanations of the options. One way to generate the static-auth-secret is with pwgen:

pwgen -s 64 1

A realm must be specified, but its value is somewhat arbitrary. (It is sent to clients as part of the authentication flow.) It is conventional to set it to be your server name.

(2) You will most likely want to configure coturn to write logs somewhere. The easiest way is normally to send them to the syslog:

syslog

(in which case, the logs will be available via journalctl -u coturn on a systemd system). Alternatively, coturn can be configured to write to a logfile - check the example config file supplied with coturn.

(3) Consider your security settings. TURN lets users request a relay which will connect to arbitrary IP addresses and ports. The following configuration is suggested as a minimum starting point:

# VoIP traffic is all UDP. There is no reason to let users connect to arbitrary TCP endpoints via the relay.
no-tcp-relay

# don't let the relay ever try to connect to private IP address ranges within your network (if any)
# given the turn server is likely behind your firewall, remember to include any privileged public IPs too.
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=172.16.0.0-172.31.255.255

# recommended additional local peers to block, to mitigate external access to internal services.
# https://www.rtcsec.com/article/slack-webrtc-turn-compromise-and-bug-bounty/#how-to-fix-an-open-turn-relay-to-address-this-vulnerability
no-multicast-peers
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=192.0.0.0-192.0.0.255
denied-peer-ip=192.0.2.0-192.0.2.255
denied-peer-ip=192.88.99.0-192.88.99.255
denied-peer-ip=198.18.0.0-198.19.255.255
denied-peer-ip=198.51.100.0-198.51.100.255
denied-peer-ip=203.0.113.0-203.0.113.255
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.
user-quota=12 # 4 streams per video call, so 12 streams = 3 simultaneous relayed calls per user.
total-quota=1200

(4) Also consider supporting TLS/DTLS. To do this, add the following settings to turnserver.conf:

# TLS certificates, including intermediate certs.
# For Let's Encrypt certificates, use `fullchain.pem` here.
cert=/path/to/fullchain.pem

# TLS private key file
pkey=/path/to/privkey.pem

# Ensure the configuration lines that disable TLS/DTLS are commented-out or removed
#no-tls
#no-dtls

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. This currently includes Element Android & iOS; for more details, see their respective issues as well as the underlying WebRTC issue. Consider using a ZeroSSL certificate for your TURN server as a working alternative.

(5) 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.)

(6) If your TURN server is behind 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=EXTERNAL_NAT_IPv4_ADDRESS

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

If your NAT gateway is reachable over both IPv4 and IPv6, you may configure coturn to advertise each available address:

external-ip=EXTERNAL_NAT_IPv4_ADDRESS
external-ip=EXTERNAL_NAT_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, and that the TURN server is listening on the local IPv6 address that is mapped by NAT to the external IPv6 address.