Help with setting up my own TURN server

That would be a yes, for the server’s own firewall, but I am not sure about what the ISP might do, or the modem/router.
I can test successfully using Trickle ICE internally but when I do it externally (via laptop connected to mobile data from smart phone) the tests do not succeed.

I am trying to find an effective method for testing ports (particularly 10000-30000) are opened in the firewall. (maybe running iperf on both client and on my turn server for testing some ports within range of ports that need to be opened, if iperf does UDP).

nmap says the TCP listening ports are available, both internally and externally. But I am having issues trying to test UDP ports with nmap. I started the UDP test but nmap is not completing the UDP test.

# nmap -n -PN -sT -sU -p- myturn.server.com
Host is up (0.024s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT     STATE SERVICE
22/tcp   open  ssh
3478/tcp open  stun
5349/tcp open  stuns
# nft list ruleset
table ip filter {
	chain INPUT {
		type filter hook input priority filter; policy drop;
		iifname "lo" accept
		iifname "enp1s0" ct state established,related accept
		iifname "enp1s0" ct state new udp dport { 3478, 4222, 5349, 10000-30000 } accept
		iifname "enp1s0" ct state new ip saddr { zz.zz.zz.27, zz.zz.zz.35, zz.zz.zz.43 } tcp dport 22 accept
		iifname "enp1s0" ct state new tcp dport { 80, 443, 3478, 5349 } accept
		iifname "enp1s0" icmp type echo-request accept
	}

	chain FORWARD {
		type filter hook forward priority filter; policy drop;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy drop;
		oifname "lo" accept
		oifname "enp1s0" accept
		oifname "enp1s0" icmp type echo-request accept
	}
}
# nft list ruleset
table ip filter {
	chain INPUT {
		type filter hook input priority filter; policy drop;
		iifname "lo" accept
		iifname "enp1s0" ct state established,related accept
		iifname "enp1s0" ct state new udp dport { 3478, 4222, 5349, 10000-30000 } accept
		iifname "enp1s0" ct state new ip saddr { zz.zz.zz.27, zz.zz.zz.35, zz.zz.zz.43 } tcp dport 22 accept
-		iifname "enp1s0" ct state new tcp dport { 80, 443, 3478, 5349 } accept
+		iifname "enp1s0" ct state new tcp dport { 80, 443, 3478, 5349, 10000-30000} accept
		iifname "enp1s0" icmp type echo-request accept
	}

	chain FORWARD {
		type filter hook forward priority filter; policy drop;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy drop;
		oifname "lo" accept
		oifname "enp1s0" accept
		oifname "enp1s0" icmp type echo-request accept
	}

Please add this and see if it works.

Adding 10000-30000 to the TCP list was a interesting idea to try, but this did not help.

# /usr/sbin/nft list ruleset
table ip filter {
	chain INPUT {
		type filter hook input priority filter; policy drop;
		iifname "lo" accept
		iifname "enp1s0" ct state established,related accept
		iifname "enp1s0" ct state new udp dport { 3478, 4222, 5349, 10000-30000 } accept
		iifname "enp1s0" ct state new ip saddr { zz.zz.zz.27, zz.zz.zz.35, zz.zz.zz.43 } tcp dport 22 accept
		iifname "enp1s0" ct state new tcp dport { 80, 443, 3478, 5349, 10000-30000 } accept
		iifname "enp1s0" icmp type echo-request accept
	}

	chain FORWARD {
		type filter hook forward priority filter; policy drop;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy drop;
		oifname "lo" accept
		oifname "enp1s0" accept
		oifname "enp1s0" icmp type echo-request accept
	}
}

However I want to state again, the Trickle ICE test works in our internal network with the above firewall running on the server, but does not work external via the ISP’s internet connection. So I suspect either the ISP or the modem/router is doing something to block some ports. However nmap test for TCP shows that the ISP and the modem/router are not blocking TCP connections to 3478 or 5349. Sadly I can only get nmap to test these two open TCP ports, not the open UDP ports.

Running this test on the TURN server itself, gives the below result showing both TCP and UDP listening ports (all looks good here) :

# lsof -i -n | egrep "COMMAND|LISTEN|UDP|TCP"
turnserve 549 turnserver   47u  IPv4  17953      0t0  UDP *:3478 
turnserve 549 turnserver   48u  IPv4  17954      0t0  UDP *:5349 
dhtnode   552    opendht    5u  IPv4    621      0t0  UDP *:4222 
dhtnode   552    opendht    6u  IPv6    622      0t0  UDP *:4222 

Rubus, thank you for your help.

I suggest we wait until I can do further tests to see if my ISP is blocking any ports or not.

I will post back again once I can confirm that there is no issue with my IPS or modem/router blocking ports. But as this is not something I can do quickly, it will take me a few days before I can run such tests.

I am open to learn about any way to test TCP and UDP from client to server. I think iperf may be a good tool to use and maybe iperf3 can test a range of ports.

`iperf3 -s -p <port_number>` where `<port_number>` is the port to test.

-p,  --port m[-n]
    set client or server port(s) to send or listen on per m (default 5001) w/optional port range per m-n (e.g. -p 6002-6008) (see Notes)

-u,  --udp
    use UDP rather than TCP

TCP test:
On server:
iperf -s  -p 10000-30000

On client:
iperf -c serverip -p 10000-30000

UDP test:
On server:
iperf -u -s -p 10000-30000

On client:
iperf -u -c serverip -p 10000-30000

While I could not get iperf3 to work with a IP range, I did several tests for various ports 443, 3478, 5349, 10000, 12500, 30000, 30001 for both UDP and TCP

The test proved to me that the ports are accessible from the Internet.

For example, 30001 failed, but 30000 worked for both UDP and TCP.

So firewalls blocking ports should not be the issue.

After I was confident that the required ports were open to the Internet, I checked the logs for the internal network test which works, and the external Internet test that does not work. (not work means that I do not get a srflx or relay report in the Trickle ICE test).

Can anyone see why the internal test succeeds and the external test fails from the below coturn server logs?

Internal network test (which works)

Feb 24 00:25:35 myturn turnserver[1088]: 2249: : session 004000000000000008: realm <ring> user <ring>: incoming packet ALLOCATE processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2249: : session 004000000000000008: realm <ring> user <ring>: incoming packet ALLOCATE processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2249: : session 007000000000000003: realm <ring> user <ring>: incoming packet ALLOCATE processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2249: : session 004000000000000008: refreshed, realm=<ring>, username=<ring>, lifetime=0
Feb 24 00:25:35 myturn turnserver[1088]: 2249: : session 004000000000000008: realm <ring> user <ring>: incoming packet REFRESH processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2249: : session 007000000000000003: refreshed, realm=<ring>, username=<ring>, lifetime=0
Feb 24 00:25:35 myturn turnserver[1088]: 2249: : session 007000000000000003: realm <ring> user <ring>: incoming packet REFRESH processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2250: : session 004000000000000008: usage: realm=<ring>, username=<ring>, rp=5, rb=392, sp=5, sb=500
Feb 24 00:25:35 myturn turnserver[1088]: 2250: : session 004000000000000008: peer usage: realm=<ring>, username=<ring>, rp=0, rb=0, sp=0, sb=0
Feb 24 00:25:35 myturn turnserver[1088]: 2250: : session 004000000000000008: closed (2nd stage), user <ring> realm <ring> origin <>, local 0.0.0.0:3478, remote 49.195.46.231:50675, reason: allocation timeout
Feb 24 00:25:35 myturn turnserver[1088]: 2250: : session 004000000000000008: delete: realm=<ring>, username=<ring>
Feb 24 00:25:35 myturn turnserver[1088]: 2250: : session 007000000000000003: usage: realm=<ring>, username=<ring>, rp=4, rb=348, sp=4, sb=400
Feb 24 00:25:35 myturn turnserver[1088]: 2250: : session 007000000000000003: peer usage: realm=<ring>, username=<ring>, rp=0, rb=0, sp=0, sb=0
Feb 24 00:25:35 myturn turnserver[1088]: 2250: : session 007000000000000003: closed (2nd stage), user <ring> realm <ring> origin <>, local 0.0.0.0:3478, remote 49.195.46.231:50676, reason: allocation timeout
Feb 24 00:25:35 myturn turnserver[1088]: 2250: : session 007000000000000003: delete: realm=<ring>, username=<ring>
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000008: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : IPv4. Local relay addr: zz.zz.zz.zz:17217
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000008: new, realm=<ring>, username=<ring>, lifetime=3600
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000008: realm <ring> user <ring>: incoming packet ALLOCATE processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000009: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : IPv4. Local relay addr: zz.zz.zz.zz:22889
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000009: new, realm=<ring>, username=<ring>, lifetime=3600
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000009: realm <ring> user <ring>: incoming packet ALLOCATE processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000008: refreshed, realm=<ring>, username=<ring>, lifetime=0
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000008: realm <ring> user <ring>: incoming packet REFRESH processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000009: refreshed, realm=<ring>, username=<ring>, lifetime=0
Feb 24 00:25:35 myturn turnserver[1088]: 2330: : session 006000000000000009: realm <ring> user <ring>: incoming packet REFRESH processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2331: : session 006000000000000008: usage: realm=<ring>, username=<ring>, rp=3, rb=244, sp=3, sb=292
Feb 24 00:25:35 myturn turnserver[1088]: 2331: : session 006000000000000008: peer usage: realm=<ring>, username=<ring>, rp=0, rb=0, sp=0, sb=0
Feb 24 00:25:35 myturn turnserver[1088]: 2331: : session 006000000000000008: closed (2nd stage), user <ring> realm <ring> origin <>, local 0.0.0.0:3478, remote ii.ii.ii.ii:43442, reason: allocation timeout
Feb 24 00:25:35 myturn turnserver[1088]: 2331: : session 006000000000000008: delete: realm=<ring>, username=<ring>
Feb 24 00:25:35 myturn turnserver[1088]: 2331: : session 006000000000000009: usage: realm=<ring>, username=<ring>, rp=3, rb=244, sp=3, sb=292
Feb 24 00:25:35 myturn turnserver[1088]: 2331: : session 006000000000000009: peer usage: realm=<ring>, username=<ring>, rp=0, rb=0, sp=0, sb=0
Feb 24 00:25:35 myturn turnserver[1088]: 2331: : session 006000000000000009: closed (2nd stage), user <ring> realm <ring> origin <>, local 0.0.0.0:3478, remote ii.ii.ii.ii:50372, reason: allocation timeout
Feb 24 00:25:35 myturn turnserver[1088]: 2331: : session 006000000000000009: delete: realm=<ring>, username=<ring>
Feb 24 00:25:35 myturn turnserver[1088]: 2385: : session 001000000000000005: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:25:35 myturn turnserver[1088]: 2385: : IPv4. Local relay addr: zz.zz.zz.zz:23157
Feb 24 00:25:35 myturn turnserver[1088]: 2385: : session 001000000000000005: new, realm=<ring>, username=<ring>, lifetime=3600
Feb 24 00:25:35 myturn turnserver[1088]: 2385: : session 001000000000000005: realm <ring> user <ring>: incoming packet ALLOCATE processed, success
Feb 24 00:25:35 myturn turnserver[1088]: 2385: : session 006000000000000010: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:25:35 myturn turnserver[1088]: 2385: : IPv4. Local relay addr: zz.zz.zz.zz:12833

External (Internet) test that does not work

Feb 24 00:23:19 myturn turnserver[1088]: 1370: : session 002000000000000006: realm <ring> user <ring>: incoming packet REFRESH processed, success
Feb 24 00:23:19 myturn turnserver[1088]: 1370: : session 000000000000000001: realm <ring> user <ring>: incoming packet REFRESH processed, success
Feb 24 00:23:19 myturn turnserver[1088]: 1371: : session 000000000000000001: usage: realm=<ring>, username=<ring>, rp=6, rb=436, sp=6, sb=600
Feb 24 00:23:19 myturn turnserver[1088]: 1371: : session 002000000000000006: usage: realm=<ring>, username=<ring>, rp=6, rb=436, sp=6, sb=600
Feb 24 00:23:19 myturn turnserver[1088]: 1371: : session 000000000000000001: peer usage: realm=<ring>, username=<ring>, rp=0, rb=0, sp=0, sb=0
Feb 24 00:23:19 myturn turnserver[1088]: 1371: : session 000000000000000001: closed (2nd stage), user <ring> realm <ring> origin <>, local 0.0.0.0:3478, remote 49.195.46.231:50648, reason: allocation timeout
Feb 24 00:23:19 myturn turnserver[1088]: 1371: : session 000000000000000001: delete: realm=<ring>, username=<ring>
Feb 24 00:23:19 myturn turnserver[1088]: 1371: : session 002000000000000006: peer usage: realm=<ring>, username=<ring>, rp=0, rb=0, sp=0, sb=0
Feb 24 00:23:19 myturn turnserver[1088]: 1371: : session 002000000000000006: closed (2nd stage), user <ring> realm <ring> origin <>, local 0.0.0.0:3478, remote 49.195.46.231:50649, reason: allocation timeout
Feb 24 00:23:19 myturn turnserver[1088]: 1371: : session 002000000000000006: delete: realm=<ring>, username=<ring>
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 003000000000000001: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 005000000000000004: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 003000000000000001: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 005000000000000004: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : IPv4. Local relay addr: zz.zz.zz.zz:20341
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 005000000000000004: new, realm=<ring>, username=<ring>, lifetime=3600
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 005000000000000004: realm <ring> user <ring>: incoming packet ALLOCATE processed, success
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : IPv4. Local relay addr: zz.zz.zz.zz:17116
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 003000000000000001: new, realm=<ring>, username=<ring>, lifetime=3600
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 003000000000000001: realm <ring> user <ring>: incoming packet ALLOCATE processed, success
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 005000000000000004: refreshed, realm=<ring>, username=<ring>, lifetime=0
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 003000000000000001: refreshed, realm=<ring>, username=<ring>, lifetime=0
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 005000000000000004: realm <ring> user <ring>: incoming packet REFRESH processed, success
Feb 24 00:23:19 myturn turnserver[1088]: 2106: : session 003000000000000001: realm <ring> user <ring>: incoming packet REFRESH processed, success
Feb 24 00:23:19 myturn turnserver[1088]: 2107: : session 005000000000000004: usage: realm=<ring>, username=<ring>, rp=4, rb=288, sp=4, sb=392
Feb 24 00:23:19 myturn turnserver[1088]: 2107: : session 005000000000000004: peer usage: realm=<ring>, username=<ring>, rp=0, rb=0, sp=0, sb=0
Feb 24 00:23:19 myturn turnserver[1088]: 2107: : session 005000000000000004: closed (2nd stage), user <ring> realm <ring> origin <>, local 0.0.0.0:3478, remote 49.195.46.231:50666, reason: allocation timeout
Feb 24 00:23:19 myturn turnserver[1088]: 2107: : session 005000000000000004: delete: realm=<ring>, username=<ring>
Feb 24 00:23:19 myturn turnserver[1088]: 2107: : session 003000000000000001: usage: realm=<ring>, username=<ring>, rp=4, rb=288, sp=4, sb=392
Feb 24 00:23:19 myturn turnserver[1088]: 2107: : session 003000000000000001: peer usage: realm=<ring>, username=<ring>, rp=0, rb=0, sp=0, sb=0
Feb 24 00:23:19 myturn turnserver[1088]: 2107: : session 003000000000000001: closed (2nd stage), user <ring> realm <ring> origin <>, local 0.0.0.0:3478, remote 49.195.46.231:50665, reason: allocation timeout
Feb 24 00:23:19 myturn turnserver[1088]: 2107: : session 003000000000000001: delete: realm=<ring>, username=<ring>
Feb 24 00:23:19 myturn turnserver[1088]: 2249: : session 004000000000000008: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:23:19 myturn turnserver[1088]: 2249: : session 007000000000000003: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:23:19 myturn turnserver[1088]: 2249: : session 004000000000000008: realm <ring> user <>: incoming packet message processed, error 401: Unauthorized
Feb 24 00:23:19 myturn turnserver[1088]: 2249: : IPv4. Local relay addr: zz.zz.zz.zz:24961
Feb 24 00:23:19 myturn turnserver[1088]: 2249: : IPv4. Local relay addr: zz.zz.zz.zz:17924
Feb 24 00:23:19 myturn turnserver[1088]: 2249: : session 004000000000000008: new, realm=<ring>, username=<ring>, lifetime=3600
Feb 24 00:23:19 myturn turnserver[1088]: 2249: : session 007000000000000003: new, realm=<ring>, username=<ring>, lifetime=3600
Feb 24 00:23:19 myturn turnserver[1088]: 2249: : session 007000000000000003: realm <ring> user <ring>: incoming packet ALLOCATE processed, success

Today I spoke with our ISP and there was nothing they could identify which may cause issues.

This brings me back checking the Turn server configuration and testing.

When I use Firefox, internally in my network I get srflx, relay, Done lines but not when I run the test externally.

When I use a Chrome browser I get the following (externally or internally):
The server stun:turn.mydomain.com:3478 returned an error with code=701:
STUN binding request timed out.
The server turn:turn.mydomain.com:3478?transport=udp returned an error with code=701:
TURN allocate request timed out.

I have used many different turnserver.conf settings.

Can anyone get Trickle ICE test for turn to work and provide me with the test and the turnserver.conf that works?

I am beginning to believe that the test and the simple turnserver.conf settings do not work. I would like to know for certain that what I am trying to achieve can actually work.

I believe the below simple turnserver.conf settings should work. I have tried more complex settings but without any different results.

$ cat /etc/turnserver.conf
listening-port=3478
listening-ip=0.0.0.0
min-port=10000
max-port=30000
lt-cred-mech
user=ring:ring
realm=ring
verbose

After further testing:

  1. my internet facing Turn server still does not work. Something to do with the STUN failing, maybe? Chrome reports 701 error. I still suspect some issue with firewalls or routing. I will keep checking.

  2. my Isolated test environment is working well.

But only if the Internet is disconnected before powering on the test environment. My test environment attempts to repent is has a network acting as if it was the Internet (i.e. a global network). If the test environment gets to see the real Internet, then I believe real Internet facing IPs are cached, causing the test environment’s network not to be seen as being the Internet. Thus as long as my test environment is disconnected from the real Internet before the test environment is brought up, messaging between two test PCs which are both behind NATed firewalls does work.

$ cat /etc/turnserver.conf
listening-port=3478
listening-ip=0.0.0.0
external-ip=192.168.100.2/192.168.100.2 #  (this is pretend Internet, see my test environment diagram above)
min-port=10000
max-port=30000
lt-cred-mech
realm=ring
user=ring:ring
verbose  # gives me a more detailed log entries
no-cli   #  ("no-cli" is not required, but I like to include it as I don't use a CLI)

I am pleased to report my TURN server for Jami is now working well.

Thank you to those who replied to my queries.

I think I am a little less ignorant about setting up STUN and TURN servers. But I have much to learn yet. And I still have many questions, some of which I hope to post in new topics which I intend to raise.

Over time I want to post what I have discovered, and maybe have learned. If my conclusions are wrong, I hope others will correct me. If I am correct, then maybe my statements can help others.

Besides ignorance of how TURN servers are configured, my other main issue was having a suitable test environment. My first test environment had the Jami clients and the TURN server trying to work through several NAT firewalls, and hence just did not work.

I ended up using two different test environments:

  1. A totally Internet isolated test environment. This required no Internet access before the Test environment computers were powered on. I guess this was to stop any routing to the Internet from being initiated. Once the real world Internet was detected, determined Internet facing IP addresses would get used instead of my internal test environment IPs.

  2. Real world Internet access environment, comprising of two client computers connected to the Internet via different Internet services. The Internet services had their own dynamic Internet facing IPs. And a directly connected, Internet facing DHT Node and TURN server with, one Internet facing IP address and then later I added a second Internet facing IP address to give two Internet facing IP addresses, which removed the “WARNING: I cannot support STUN CHANGE_REQUEST functionality because only one IP address is provided” log message from my logs.
    Note: By “directly connected, Internet facing”, I mean the TURN server’s IP address is also the server’s Internet IP address, there is no NAT firewall between the Internet and the CoTurn TURN server.

This is my final CoTurn sever configuration. Maybe posting this will help someone. Maybe others can comment if you see something wrong, something not necessary, or something you like.

# cat /etc/turnserver.conf
# TURN listener port for UDP and TCP (Default: 3478).
listening-port=3478
tls-listening-port=5349
listening-ip=216.13.205.12
listening-ip=216.13.205.10
external-ip=216.13.205.12/216.13.205.12
external-ip=216.13.205.10/216.13.205.10
min-port=10000
max-port=30000
lt-cred-mech
realm=ring
# Specify the user for the TURN authentification
user=ring:ring
# Turn OFF the CLI support to disable telnet client connections on IP address 127.0.0.1, port 5766. Removed log message: "Empty cli-password..." 
no-cli
# Enable verbose logging
verbose
# Use fingerprint in TURN message
fingerprint

# Disable weak encryption protocols
no-tlsv1
no-tlsv1_1
no-tlsv1_2

# Path to the SSL certificate and private key.
pkey=/etc/letsencrypt/live/turn.mydomain.com.au/privkey.pem
cert=/etc/letsencrypt/live/turn.mydomain.com.au/cert.pem

# Require authentication of the STUN Binding request.
# By default, the clients are allowed anonymous access to the STUN Binding functionality.
#
secure-stun

# Specify the allowed OpenSSL cipher list for TLS/DTLS connections
cipher-list="ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384"

# (To avoid any security issue that allowing loopback access may raise,
# the no-loopback-peers option is replaced by allow-loopback-peers.)
#no-loopback-peers # removed after seeing log message: "Bad configuration format: no-loopback-peers"

# Flag that can be used to disallow peers on well-known broadcast addresses (224.0.0.0 and above, and FFXX:*).
# This is an extra security measure.
#
no-multicast-peers
# Option to allow or ban specific ip addresses or ranges of ip addresses.
# If an ip address is specified as both allowed and denied, then the ip address is
# considered to be allowed. This is useful when you wish to ban a range of ip
# addresses, except for a few specific ips within that range.
#
# This can be used when you do not want users of the turn server to be able to access
# machines reachable by the turn server, but would otherwise be unreachable from the
# internet (e.g. when the turn server is sitting behind a NAT)
#

# IPv4 Private-Use
# Note: 10.0.0.0/24 was one of my test Client computer's private network so do not deny this #network: denied-peer-ip=10.0.0.0-10.255.255.255
#denied-peer-ip=172.16.0.0-172.31.255.255
#denied-peer-ip=192.168.0.0-192.168.255.255

# Other IPv4 Special-Purpose addresses
#denied-peer-ip=100.64.0.0-100.127.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=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

# IPv6 Unique-Local
#denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

# IPv6 Link-Local Unicast
#denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff

# Other IPv6 Special-Purpose assignments
#denied-peer-ip=::ffff:0:0-::ffff:ffff:ffff
#denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff
#denied-peer-ip=64:ff9b:1::-64:ff9b:1:ffff:ffff:ffff:ffff:ffff
#denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff
#denied-peer-ip=2001:db8::-2001:db8:ffff:ffff:ffff:ffff:ffff:ffff
#denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff

My comments on the TURN server configuration settings:

  1. TLS - I wanted to enable TLS support so I used LetsEncrypt to provide valid security certificates and set “tls-listening-port=5349”. This also removed some log messages that were annoying me, e.g. “WARNING: cannot find certificate file…”, “WARNING: cannot start TLS and DTLS listeners…”, etc.

  2. Before using two network interfaces and two IP addresses, I had used “listening-ip=0.0.0.0” which had worked.

  3. I used “external-ip=<isolated internal IP>/<isolated internal IP>” so my Internet isolated Test Environment knew what IP to use for its “Internet facing IP address”. I decided to also specify the address for the Internet facing Test Environment (“external-ip=<internet IP>/<internet IP>”), even though I believe the CoTurn server can determine the IP to use when the server’s IP is the same as its Internet facing IP address.

  4. I used two Internet facing IP addresses to prove that this would remove the “WARNING: I cannot support STUN CHANGE_REQUEST functionality because only one IP address is provided” message from the log files. I do not know if Jami makes use of “STUN CHANGE_REQUEST functionality”, when it is available?

  5. I decided to use “user=ring:ring” instead of adding the user using turnadmin. I used “ring:ring” as the UserID and password as well as the realm of “ring” so I never needed to change these settings from the turn.jami.net values while I was testing, and was swapping between turn.mydomain.com.au and turn.jami.net while doing tests.

  6. In the hopes it makes the server more secure, I turned off the telnet command line interface using “no-cli”. This also stopped log entries complaining about “CONFIG ERROR: Empty cli-password, and so telnet cli interface is disabled!”. This log message implies that the CLI interface is disabled if a CLI password is not specified, so my including “no-cli” is not actually necessary, except to stop the log message.

  7. In the hopes it makes the server more secure, I specified “no-loopback-peers”. I believe this is now the default for the CoTurn server and hence is not required, since the option is replaced by allow-loopback-peers.
    Update 20250302: CoTurn was complaining about “Bad configuration format: no-loopback-peers” so I removed this option from my configuration.

  8. I need to learn more about “denied-peer-ip” and what “when you do not want users of the turn server to be able to access machines reachable by the turn server”. But as I have seen other systems that use TURN recommend disabling these ranges, I included them. What does “users … access machines” mean and/or imply? In what way can they “access” other “machines” (presumably user’s computers) ?.
    I found that because 10.0.0.0/24 was one of my test Client computer’s private network, I could not deny this network, as in “denied-peer-ip=10.0.0.0-10.255.255.255”, otherwise the Jami client could not be reached by other Jami clients or reach other Jami clients.
    Update 20250302: I have removed the “denied-peer-ip” as 1) I do not believe they are required for Coturn 4.5.2 and above, 2) some of the designated IP ranges are used by Jami Client’s LANs.
    See:

https://www.enablesecurity.com/blog/cve-2020-26262-bypass-of-coturns-access-control-protection/?form=MG0AV3

 Since the fixed version 4.5.2, rules blocking loopback and current network addresses are no longer needed. So our main recommendation is to upgrade to the latest fixed version.
  1. I have read comments suggesting Jami uses end to end encryption, hence using Jami does not use TLS or DTLS, so we don’t need to enable TLS/DTLS, to use tls_listening_port" or certificates. To stop CoTurn log entries about this, include “no-tls”.
    If you do you enable TLS and DTLS, we should disable weak encryption protocols.
# Disable weak encryption protocols
no-tlsv1
no-tlsv1_1
no-tlsv1_2

After sorting out the issues with 1) my test environment’s networking, 2) CoTurn turnserver settings, and getting the CoTurn Server to work, I then addressed the issue of what ports need to be open to have Jami work.

My understanding of firewalls is that:

  1. you only need to block ports that the server’s services are listening on. Examples of these services: FTP, Telnet, SSH, SMTP, HTTP, HTTPS, TURN, TURNS.

  2. A number of services work such that you establish a connection on a defined port that the service is listening on, then once established, a new port, usually in the higher port range that is not a designated fixed port number and the network traffic moves to using the higher port, which frees up the defined port for new connections. This network traffic is known as “established and related” traffic.

  3. As a result of points 1) and 2) when setting firewall rules you only need to allow (open) access to ports on which your server’s services are listening on, and then allow established and related traffic to keep flowing.

Resulting from the above ideas, I could not see a reason for ports 10000-30000 to be open. However if they were not, the Jami clients were not able to complete (i.e. work).

I then tried to change the ports 10000-30000 to 49152-65535 and this did work, however because I don’t know if there is a reason why ports 10000-30000 has been used in the documentation, I will stay with using these ports.

While most examples of firewalls I have seen open all out going ports, I prefer to block all outgoing ports except those required to maintain the server and those required for the service (e.g. TURN, DHT Node) if there are any that are required.

Below I give examples of some of my /etc/nftables.conf files that I used:

In the below example is for when using one Internet facing IP addresses and a port range of “10000-30000”.

# nft list ruleset
table ip filter {
	chain INPUT {
		type filter hook input priority filter; policy drop;
		iifname "lo" accept
		iifname "enp1s0" ct state established,related accept
		iifname "enp1s0" ct state new udp dport { 3478, 4222, 5349, 10000-30000 } accept
		iifname "enp1s0" ct state new ip saddr { 199.46.34.30, 199.46.34.25, 199.46.34.46 } tcp dport 22 accept
		iifname "enp1s0" ct state new tcp dport { 3478, 5349, 10000-30000 } accept
		iifname "enp1s0" icmp type echo-request accept
	}

	chain FORWARD {
		type filter hook forward priority filter; policy drop;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy drop;
		oifname "lo" accept
		oifname "enp1s0" ct state established,related accept
		oifname "enp1s0" ct state new udp dport 53 accept
		oifname "enp1s0" ct state new tcp dport { ssh, 53, 80, 123, 443 } accept
		oifname "enp1s0" icmp type echo-request accept
	}
}

In the below example is for when using two Internet facing IP addresses and a port range of “49152-65535” (also changing min-port and max-port in CoTurn configuration).

# /usr/sbin/nft list ruleset
table ip filter {
	chain INPUT {
		type filter hook input priority filter; policy drop;
		iifname "lo" accept
		iifname { "enp1s0", "enp7s0" } ct state established,related accept
		iifname { "enp1s0", "enp7s0" } ct state new udp dport { 3478, 4222, 5349, 49152-65535 } accept
		iifname { "enp1s0", "enp7s0" } ct state new ip saddr { 199.46.34.30, 199.46.34.25, 199.46.34.46 } tcp dport 22 accept
		iifname { "enp1s0", "enp7s0" } ct state new tcp dport { 3478, 5349, 49152-65535 } accept
		iifname { "enp1s0", "enp7s0" } icmp type echo-request accept
	}

	chain FORWARD {
		type filter hook forward priority filter; policy drop;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy drop;
		oifname "lo" accept
		oifname { "enp1s0", "enp7s0" } ct state established,related accept
		oifname { "enp1s0", "enp7s0" } ct state new udp dport 53 accept
		oifname { "enp1s0", "enp7s0" } ct state new tcp dport { ssh, 53, 80, 123, 443 } accept
		oifname { "enp1s0", "enp7s0" } icmp type echo-request accept
	}
}

Returning back to the Jami documentation’s port range:

# /usr/sbin/nft list ruleset
table ip filter {
	chain INPUT {
		type filter hook input priority filter; policy drop;
		iifname "lo" accept
		iifname { "enp1s0", "enp7s0" } ct state established,related accept
		iifname { "enp1s0", "enp7s0" } ct state new udp dport { 3478, 4222, 5349, 10000-30000 } accept
		iifname { "enp1s0", "enp7s0" } ct state new ip saddr { 199.46.34.30, 199.46.34.25, 199.46.34.46 } tcp dport 22 accept
		iifname { "enp1s0", "enp7s0" } ct state new tcp dport { 3478, 5349, 10000-30000 } accept
		iifname { "enp1s0", "enp7s0" } icmp type echo-request accept
	}

	chain FORWARD {
		type filter hook forward priority filter; policy drop;
	}

	chain OUTPUT {
		type filter hook output priority filter; policy drop;
		oifname "lo" accept
		oifname { "enp1s0", "enp7s0" } ct state established,related accept
		oifname { "enp1s0", "enp7s0" } ct state new udp dport { 53, 123 } accept
		oifname { "enp1s0", "enp7s0" } ct state new tcp dport { ssh, 53, 80, 443 } accept
		oifname { "enp1s0", "enp7s0" } icmp type echo-request accept
	}
}

UPDATE: I have correct NTP port 123: as “timesyncd” does not use TCP; it uses UDP

However Jami doesn’t support TURN over DTLS or TURN over TLS.

After the client sends an Allocate request to the server, the server will listens on a port in the range (For coTURN, you can set it in turnserver.conf), then replies with an Allocate success response containing the allocated relayed transport address.

I wanted to understand how Jami maintains security and privacy, particularly when a TURN server is being used in the middle of the communications between two clients.

After researching on the Internet my understanding is that the Jami Client encrypts all data (text, audio, video, file) before transmission, which is why Jami uses a Client and not web browser. This would imply that all network traffic is encrypted while it passes through the TURN server, and thus it is not necessary to encryption a second time by using TLS or DTLS. The TURN server is forwarding/relaying encrypted data. Is my understanding correct?

I wonder what method of encryption the Jami Client uses?

Thinking further about Jami not requiring TLS or DTLS, does this mean if my TURN server will only be used for Jami, I could use “no-tls” and “no-dtls”? This stops the server from giving warnings “WARNING: cannot start TLS and DTLS listeners”.

By " For coTURN, you can set it in turnserver.conf" do you mean the min-port=10000 and max-port=30000 settings?

Is there a reason why Jami uses the 10000-30000 port range, while not required or necessary, I would have thought that Jami would have used the port range 49152 - 65535 ? I am just curious if there is some specific reason?

https://datatracker.ietf.org/doc/html/rfc5766
6.  Creating an Allocation
   In all cases, the server SHOULD only allocate ports from the range
   49152 - 65535 (the Dynamic and/or Private Port range [Port-Numbers]),
   unless the TURN server application knows, through some means not
   specified here, that other applications running on the same host as
   the TURN server application will not be impacted by allocating ports
   outside this range.

Can you please add instructions on how to set up a TURN server for Jami on the Jami documentation website?

Thank you