Can't get built-in STUN/TURN server to work
Hello! I recently installed and set up the docker version of Ejabberd from docker.io/ejabberd/ecs. Here is my docker-compose.yml file:
services:
ejabberd:
image: ejabberd/ecs
container_name: ejabberd
restart: unless-stopped
ports:
- "5222:5222"
- "5223:5223"
- "5269:5269"
- "5280:5280"
- "5443:5443"
- "3478:3478" # stun/turn
- "5349:5349" # stuns/turns
- "49152-49500:49152-49500" # turn
volumes:
- ./config:/home/ejabberd/conf
- ./db:/home/ejabberd/database
- ./logs:/home/ejabberd/logs
- ./upload:/home/ejabberd/upload
depends_on:
- ejabberd-postgres
ejabberd-postgres:
image: postgres:15-alpine
container_name: ejabberd-postgres
restart: unless-stopped
volumes:
- ./postgres/data:/var/lib/postgresql/data
- ./postgres/config:/config/sql
- ./postgres/docker:/docker-entrypoint-initdb.d
environment:
POSTGRES_DB: ejabberd
POSTGRES_USER: ejabberd
POSTGRES_PASSWORD: secret-password
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
All the chat functions seem to work great. I then tried to set up the built-in STUN/TURN server to enable voice and video calls. I added/edited the following in my ejabberd.yml file:
...
certfiles:
...
- /home/ejabberd/conf/certs/stun-turn/fullchain.pem
- /home/ejabberd/conf/certs/stun-turn/privkey.pem
...
...
listen:
...
-
port: 3478
transport: udp
module: ejabberd_stun
use_turn: true
## The server's public IPv4 address:
turn_ipv4_address: "my-external-ipv4-address"
## The server's public IPv6 address:
# turn_ipv6_address: "2001:db8::3"
turn_min_port: 49152
turn_max_port: 49500
-
port: 5349
transport: tcp
module: ejabberd_stun
use_turn: true
tls: true
turn_ipv4_address: "my-external-ipv4-address"
turn_min_port: 49152
turn_max_port: 49500
...
...
modules:
...
mod_stun_disco:
secret: my-secret
services:
-
host: my-external-ipv4-address
port: 3478
type: stun
transport: udp
restricted: false
-
host: my-external-ipv4-address
port: 3478
type: turn
transport: udp
restricted: true
-
host: xmpp.mydomain.com
port: 5349
type: stuns
transport: tcp
restricted: false
-
host: xmpp.mydomain.com
port: 5349
type: turns
transport: tcp
restricted: true
...
I have the following ports forwarded on my router:
- For XMPP: 5222, 5269, 5443
- For STUN/TURN: 3478(tcp/udp), 5349(tcp/udp), 49152-49500(udp)
I also have the following DNS records set up:
+ A | mydomain.com | my-external-ipv4-address
+ CNAME | *.mydomain.com | mydomain.com
+ SRV | _stun._tcp.xmpp.mydomain.com | 0 0 3478 xmpp.mydomain.com
+ SRV | _stun._udp.xmpp.mydomain.com | 0 0 3478 xmpp.mydomain.com
+ SRV | _stuns._tcp.xmpp.mydomain.com | 0 0 5349 xmpp.mydomain.com
+ SRV | _turn._tcp.xmpp.mydomain.com | 0 0 3478 xmpp.mydomain.com
+ SRV | _turn._udp.xmpp.mydomain.com | 0 0 3478 xmpp.mydomain.com
+ SRV | _turns._tcp.xmpp.mydomain.com | 0 0 5349 xmpp.mydomain.com
I haven't been able to get the STUN/TURN server to work. Any advice would be greatly appreciated!
It is also worth noting that I have a Nginx Proxy Manager reverse proxy setup that manages my SSL certificates and through which all the HTTP/HTTPS traffic gets routed. However, the XMPP and STUN/TURN traffic should not get routed through it since (as far as I'm aware) they don't use ports 80/443.
Hi, I think your docker-compose.yml is not correct. You need to open the UDP ports for TURN to work:
old:
ports:
- "5222:5222"
- "5223:5223"
- "5269:5269"
- "5280:5280"
- "5443:5443"
- "3478:3478" # stun/turn
- "5349:5349" # stuns/turns
- "49152-49500:49152-49500" # turn
new:
ports:
- "5222:5222"
- "5223:5223"
- "5269:5269"
- "5280:5280"
- "5443:5443"
- "3478:3478/udp" # stun/turn
- "5349:5349" # stuns/turns
- "49152-49500:49152-49500/udp" # turn
Unfortunately, that still doesn't work. :/
Although not recommended from Docker best practices, could you give it a try to run it in the host network instead with Docker port forwarding? (although I am not convinced it is the problem).
instead of the ports definition in the docker-compose.yml, can you use:
network_mode: "host"
Just tried it, and that doesn't seem to work either.
My tests involved starting video calls between two different accounts on different devices and different networks, a PC running Gajim and an Android phone running Conversations. I also tried testing the STUN/TURN server using the Trickle ICE test with negative results in all configurations.
It is possible that I am doing something wrong with the configuration outside of Ejabberd (DNS or port forwarding), but I've tried all the ideas I had and double-checked everything and nothing worked.
I might try setting up a Coturn server, making sure it actually works with the ICE test, then configuring Ejabberd to use it, either temporarily (to see if the problem lies with docker-ejabberd or with my external configuration) or as a permanent solution.
If anyone has any pointers of where I might be doing something wrong or any advice, that would be greatly appreciated.
Hm.. I will need to test it myself locally, because I do not spot anything obvious in your configuration.
You may also try https://github.com/processone/eturnal/blob/master/doc/CONTAINER.md which uses the same stun library as ejabberd. There is also a quick-start example for simple connectivity tests with trickle ICE and else.
P.S. I tested icetest.info with the following podman command:
podman run --rm --name ejabberd -d -p 3479:3478/udp -v $PWD/ejabberd.yml:/home/ejabberd/conf/ejabberd.yml docker.io/ejabberd/ecs
For ejabberd.yml I just used a copy w/o modification from here.
When configuring icetest with stun:203.0.113.3:3479 I have a positive STUN response. TURN I could not yet test.
P.S. 2:
I added the following auth_type: anonymous for basic testing into my ejabberd.yml stun listener:
-
port: 3478
ip: "::"
transport: udp
module: ejabberd_stun
use_turn: true
auth_type: anonymous
When running icetest.info with URL: turn:203.0.113.3:3479 Username: abc Credential: abc I can obtain relay candidates.
Note: 203.0.113.3 is my public IP address -> turn_ipv4_address .
Thank you. I will go over my configuration one more time.