docker-ejabberd icon indicating copy to clipboard operation
docker-ejabberd copied to clipboard

Can't get built-in STUN/TURN server to work

Open gabriel-eladi opened this issue 1 year ago • 6 comments

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.

gabriel-eladi avatar May 29 '24 11:05 gabriel-eladi

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

sando38 avatar Jul 22 '24 09:07 sando38

Unfortunately, that still doesn't work. :/

gabriel-eladi avatar Jul 24 '24 14:07 gabriel-eladi

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"

sando38 avatar Jul 24 '24 18:07 sando38

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.

gabriel-eladi avatar Jul 24 '24 20:07 gabriel-eladi

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 .

sando38 avatar Jul 25 '24 15:07 sando38

Thank you. I will go over my configuration one more time.

gabriel-eladi avatar Jul 27 '24 15:07 gabriel-eladi