processone / docker-ejabberd

Set of ejabberd Docker images
95 stars 77 forks source link

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

Open gabriel-eladi opened 3 months ago

gabriel-eladi commented 3 months ago

Hello! I recently installed and set up the docker version of Ejabberd from docker.io/ejabberd/ecs. Here is my docker-compose.yml file:

```yaml 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:

```yaml ... 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:

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.

sando38 commented 1 month ago

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
gabriel-eladi commented 1 month ago

Unfortunately, that still doesn't work. :/

sando38 commented 1 month ago

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"
gabriel-eladi commented 1 month ago

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.

sando38 commented 1 month ago

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 .

gabriel-eladi commented 1 month ago

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