network-programmingserverwebrtcturncoturn

How to resolve Coturn Configuration Issues: Unable to Bind fd 29 to 127.0.0.1:3478


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!


Solution

  • 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.