I am trying to build a TURN server using Coturn configured on an AWS instance. I have set the following incoming security groups:
-0b2ed368e187eb2b1 22 TCP 0.0.0.0/0 SSH – –
sgr-003d18fd1b201dd42 3478 - 3479 TCP 0.0.0.0/0 TLS/TCP – –
sgr-0cc11343f95a2b395 32355 - 65535 TCP 0.0.0.0/0 TLS/TCP – –
sgr-0ce03cb3e6b05fb57 32355 - 65535 UDP 0.0.0.0/0 TLS/TCP – –
sgr-04d3824d3597c819b 3478 - 3479 UDP 0.0.0.0/0 TLS/TCP
And my configuration file looks like:
#
# Listener interface device (optional, Linux only).
# NOT RECOMMENDED.
#
#listening-device=eth0
listening-port=3478
tls-listening-port=5349
#alt-tls-listening-port=0
# Some network setups will require using a TCP reverse proxy in front
# of the STUN server. If the proxy port option is set a single listener
# is started on the given port that accepts connections using the
# haproxy proxy protocol v2.
# (https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)
#
#tcp-proxy-port=5555
# Listener IP address of relay server. Multiple listeners can be specified.
# If no IP(s) specified in the config file or in the command line options,
# then all IPv4 and IPv6 system IPs will be used for listening.
#
listening-ip=XXX.XX.XX.XXX
#aux-server=172.17.19.110:33478
# If no relay IP(s) specified, then the turnserver will apply the default
# policy: it will decide itself which relay addresses to be used, and it
# will always be using the client socket IP address as the relay IP address
# of the TURN session (if the requested relay address family is the same
# as the family of the client socket).
relay-ip=XXX.XX.XX.XXX
#relay-ip=2607:f0d0:1002:51::5
# By default, this value is empty, and no address mapping is used.
# (Uses EC2 instance public/private ips)
external-ip=X.XX.XX.XXX/XXX.XX.XX.XXX
#
#relay-threads=0
# Lower and upper bounds of the UDP relay endpoints:
# (default values are 49152 and 65535)
#
min-port=3478
max-port=65535
# Uncomment to run TURN server in 'normal' 'moderate' verbose mode.
# By default the verbose mode is off.
verbose
# Uncomment to use fingerprints in the TURN messages.
# By default the fingerprints are off.
#
fingerprint
# Uncomment to use long-term credential mechanism.
# By default no credentials mechanism is used (any user allowed).
#
lt-cred-mech
# This option is the opposite of lt-cred-mech.
# (TURN Server with no-auth option allows anonymous access).
# If neither option is defined, and no users are defined,
# then no-auth is default. If at least one user is defined,
# in this file, in command line or in usersdb file, then
# lt-cred-mech is default.
#
#no-auth
# Enable prometheus exporter
# If enabled the turnserver will expose an endpoint with stats on a prometheus format
# this endpoint is listening on a different port to not conflict with other configurations.
#
# You can simply run the turnserver and access the port 9641 and path /metrics
#
# For mor info on the prometheus exporter and metrics
# https://prometheus.io/docs/introduction/overview/
# https://prometheus.io/docs/concepts/data_model/
#
#prometheus
# TURN REST API flag.
# (Time Limited Long Term Credential)
# Flag that sets a special authorization option that is based upon authentication secret.
#
# This feature's purpose is to support "TURN Server REST API", see
# "TURN REST API" link in the project's page
# https://github.com/coturn/coturn/
#
# This option is used with timestamp:
# usercombo -> "timestamp:userid"
# turn user -> usercombo
# turn password -> base64(hmac(secret key, usercombo))
#
# This allows TURN credentials to be accounted for a specific user id.
# If you don't have a suitable id, then the timestamp alone can be used.
# This option is enabled by turning on secret-based authentication.
# The actual value of the secret is defined either by the option static-auth-secret,
# or can be found in the turn_secret table in the database (see below).
#
# Read more about it:
# - https://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
# - https://www.ietf.org/proceedings/87/slides/slides-87-behave-10.pdf
#
# Be aware that use-auth-secret overrides some parts of lt-cred-mech.
# The use-auth-secret feature depends internally on lt-cred-mech, so if you set
# this option then it automatically enables lt-cred-mech internally
# as if you had enabled both.
#
#
# Note that you can use only one auth mechanism at the same time! This is because,
# both mechanisms conduct username and password validation in different ways.
#
# Use either lt-cred-mech or use-auth-secret in the conf
# to avoid any confusion.
#
#use-auth-secret
# 'Static' authentication secret value (a string) for TURN REST API only.
# If not set, then the turn server
# will try to use the 'dynamic' value in the turn_secret table
# in the user database (if present). The database-stored value can be changed on-the-fly
# by a separate program, so this is why that mode is considered 'dynamic'.
#
#static-auth-secret=XXXXXXXXXXXX
# Server name used for
# the oAuth authentication purposes.
# The default value is the realm name.
#server-name=blackdow.carleon.gov
# Flag that allows oAuth authentication.
#
#oauth
# 'Static' user accounts for the long term credentials mechanism, only.
# This option cannot be used with TURN REST API.
# 'Static' user accounts are NOT dynamically checked by the turnserver process,
# so they can NOT be changed while the turnserver is running.
#
user=XXXXXX:XXXXXX
#user=username2:key2
# OR:
#user=username1:password1
#user=username2:password2
#
# Keys must be generated by turnadmin utility. The key value depends
# on user name, realm, and password:
# Example:
# $ turnadmin -k -u ninefingers -r north.gov -p youhavetoberealistic
# Output: 0xbc807ee29df3c9ffa736523fb2c4e8ee
# ('0x' in the beginning of the key is what differentiates the key from
# password. If it has 0x then it is a key, otherwise it is a password).
#
# The corresponding user account entry in the config file will be:
#
#user=ninefingers:0xbc807ee29df3c9ffa736523fb2c4e8ee
# Or, equivalently, with open clear password (less secure):
#user=ninefingers:youhavetoberealistic
#
# SQLite database file name.
#
# The default file name is /var/db/turndb or /usr/local/var/db/turndb or
# /var/lib/turn/turndb.
#
#userdb=/var/db/turndb
# PostgreSQL database connection string in the case that you are using PostgreSQL
# as the user database.
# This database can be used for the long-term credential mechanism
# and it can store the secret value for secret-based timed authentication in TURN REST API.
# See http://www.postgresql.org/docs/8.4/static/libpq-connect.html for 8.x PostgreSQL
# versions connection string format, see
# http://www.postgresql.org/docs/9.2/static/libpq-connect.html#LIBPQ-CONNSTRING
# for 9.x and newer connection string formats.
#
#psql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> connect_timeout=30"
# MySQL database connection string in the case that you are using MySQL
# as the user database.
# This database can be used for the long-term credential mechanism
# and it can store the secret value for secret-based timed authentication in TURN REST API.
#
# Optional connection string parameters for the secure communications (SSL):
# ca, capath, cert, key, cipher
# (see http://dev.mysql.com/doc/refman/5.1/en/ssl-options.html for the
# command options description).
# Use the string format below (space separated parameters, all optional):
#
#mysql-userdb="host=<host> dbname=<database-name> user=<database-user> password=<database-user-password> port=<port> connect_timeout=<seconds> red_timeout=<seconds>"
# If you want to use an encrypted password in the MySQL connection string,
# then set the MySQL password encryption secret key file with this option.
#
# Warning: If this option is set, then the mysql password must be set in "mysql-userdb" in an encrypted format!
# If you want to use a cleartext password then do not set this option!
#
# This is the file path for the aes encrypted secret key used for password encryption.
#
#secret-key-file=/path/
#redis-userdb="ip=<ip-address> dbname=<database-number> password=<database-user-password> port=<port> connect_timeout=<seconds>"
# Redis status and statistics database connection string, if used (default - empty, no Redis stats DB used).
#redis-statsdb="ip=<ip-address> dbname=<database-number> password=<database-user-password> port=<port> connect_timeout=<seconds>"
realm=XXXX.amazonaws.com
#check-origin-consistency
#total-quota=0
#max-bps=0
#
# Uncomment if no TCP client listener is desired.
# By default TCP client listener is always started.
#
#no-tcp
# Uncomment if no TLS client listener is desired.
# By default TLS client listener is always started.
#
#no-tls
# Uncomment if no DTLS client listener is desired.
# By default DTLS client listener is always started.
#
#no-dtls
# Uncomment if no UDP relay endpoints are allowed.
#no-tcp-relay
#stale-nonce=600
#channel-lifetime=600
#permission-lifetime=300
# Certificate file.
# Use an absolute path or path relative to the
# configuration file.
# Use PEM file format.
#
#cert=/usr/local/etc/turn_server_cert.pem
# Private key file.
# Use an absolute path or path relative to the
#pkey-pwd=...
# Allowed OpenSSL cipher list for TLS/DTLS connections.
# Default value is "DEFAULT".
#
#cipher-list="DEFAULT"
# CA file in OpenSSL format.
# Forces TURN server to verify the client SSL certificates.
# By default this is not set: there is no default value and the client
# certificate is not checked.
#
#ec-curve-name=prime256v1
# Use 566 bits predefined DH TLS key. Default size of the key is 2066.
#
#dh566
# Use 1066 bits predefined DH TLS key. Default size of the key is 2066.
#
#dh1066
# Use custom DH TLS key, stored in PEM format in the file.
# Flags --dh566 and --dh2066 are ignored when the DH key is taken from a file.
#
#dh-file=<DH-PEM-file-name>
# Flag to prevent stdout log messages.
# By default, all log messages go to both stdout and to
# the configured log file. With this option everything will
# go to the configured log only (unless the log file itself is stdout).
#
#no-stdout-log
# In the runtime, the logfile can be reset with the SIGHUP signal
# to the turnserver process.
#
log-file=/var/log/coturn/coturn.log
#secure-stun
# Mobility with ICE (MICE) specs support.
#
#mobility
#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
The output is as follows:
ERROR: Cannot open log file for writing: /var/log/coturn/coturn_2022-10-22.log
0: : log file opened: /var/log/turn_47167_2022-10-22.log
0: : Relay address to use: 172.xx.xx.xxx
0: : Whitelisting external-ip private part: 172.xx.xx.xxx
0: : Config file found: /etc/turnserver.conf
0: :
RFC 3489/5389/5766/5780/6062/6156 STUN/TURN Server
Version Coturn-4.5.2 'dan Eider'
0: :
Max number of open files/sockets allowed for this process: 1048576
0: :
Due to the open files/sockets limitation,
max supported number of TURN Sessions possible is: 524000 (approximately)
0: :
==== Show him the instruments, Practical Frost: ====
0: : TLS supported
0: : DTLS supported
0: : DTLS 1.2 supported
0: : TURN/STUN ALPN supported
0: : Third-party authorization (oAuth) supported
0: : GCM (AEAD) supported
0: : OpenSSL compile-time version: OpenSSL 3.0.2 15 Mar 2022 (0x30000020)
0: :
0: : SQLite supported, default database location is /var/lib/turn/turndb
0: : Redis supported
0: : PostgreSQL supported
0: : MySQL supported
0: : MongoDB is not supported
0: :
0: : Default Net Engine version: 3 (UDP thread per CPU core)
=====================================================
0: : Domain name:
0: : Default realm:
0: : ERROR:
CONFIG ERROR: Empty cli-password, and so telnet cli interface is disabled! Please set a non empty cli-password!
0: : WARNING: cannot find certificate file: turn_server_cert.pem (1)
0: : WARNING: cannot start TLS and DTLS listeners because certificate file is not set properly
0: : WARNING: cannot find private key file: turn_server_pkey.pem (1)
0: : WARNING: cannot start TLS and DTLS listeners because private key file is not set properly
0: : NO EXPLICIT LISTENER ADDRESS(ES) ARE CONFIGURED
0: : ===========Discovering listener addresses: =========
0: : Listener address to use: 127.0.0.1
0: : Listener address to use: 172.xx.xx.xxx
0: : Listener address to use: ::1
0: : =====================================================
0: : Total: 1 'real' addresses discovered
0: : =====================================================
0: : pid file created: /var/run/turnserver.pid
0: : IO method (main listener thread): epoll (with changelist)
0: : Wait for relay ports initialization...
0: : relay 172.xx.xx.xxx initialization...
0: : relay 172.xx.xx.xxx initialization done
0: : Relay ports initialization done
0: : IO method (general relay thread): epoll (with changelist)
0: : turn server id=1 created
bind: Address already in use
0: : Trying to bind fd 12 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
0: : IO method (general relay thread): epoll (with changelist)
0: : turn server id=0 created
0: : IPv4. UDP listener opened on: 127.0.0.1:3478
0: : IPv4. UDP listener opened on: 127.0.0.1:3479
0: : IPv4. UDP listener opened on: 172.xx.xx.xxx:3478
0: : IPv4. UDP listener opened on: 172.xx.xx.xxx:3479
0: : IPv6. UDP listener opened on: ::1:3478
0: : IPv6. UDP listener opened on: ::1:3479
0: : Total General servers: 2
bind: Address already in use
0: : Trying to bind fd 29 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
0: : IO method (admin thread): epoll (with changelist)
0: : IO method (auth thread): epoll (with changelist)
0: : IO method (auth thread): epoll (with changelist)
0: : SQLite DB connection success: /var/lib/turn/turndb
bind: Address already in use
0: : Trying to bind fd 12 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
bind: Address already in use
0: : Trying to bind fd 29 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
bind: Address already in use
0: : Trying to bind fd 12 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
bind: Address already in use
0: : Trying to bind fd 29 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
bind: Address already in use
0: : Trying to bind fd 12 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
bind: Address already in use
0: : Trying to bind fd 29 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
bind: Address already in use
0: : Trying to bind fd 12 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
bind: Address already in use
0: : Trying to bind fd 29 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
bind: Address already in use
0: : Trying to bind fd 12 to <127.0.0.1:3478>: errno=98
Cannot bind local socket to addr: Address already in use
0: : Cannot bind TLS/TCP listener socket to addr 127.0.0.1:3478
0: : Trying to bind TLS/TCP listener socket to addr 127.0.0.1:3478, again...
ETA netstat results:
tcp 0 0 172.31.XX.XXX:3478 0.0.0.0:* LISTEN 51761/turnserver
tcp 0 0 172.31.XX.XXX:3478 0.0.0.0:* LISTEN 51761/turnserver
udp 0 0 172.31.XX.XXX:3478 0.0.0.0:* 51761/turnserver
udp 0 0 172.31.XX.XXX:3478 0.0.0.0:* 51761/turnserver
I'm trying to figure out why UDP cannot have the port. It also will not allow me to gather candidates using Trickle ICE, which is problematic (and I am guessing means our components would not be able to use it for communication).
I have never used Coturn or configured a server from scratch and this is part of a sponsored agile project, so I do not have time to keep being stuck on it. Unfortunately, no one else on my team knows anything about Turn servers either. Any help is greatly appreciated!
Update in case anyone else runs into this issue:
It was a permissions issue. Ensure you use sudo systemctl kill coturn
(To kill any existing instance/service)
Then call sudo turnserver -c /etc/turnserver.conf
which will properly load the config file and not deny allocation of listening ports.