Jitsi meet in DMZ behind NAT and Nginx reverse proxy

Hello everybody o/

I try to setup Jitsi meet in my DMZ with meet.domain.tld.
I follow the guide here : Self-Hosting Guide - Debian/Ubuntu server · Jitsi Meet Handbook
When I start new room and I join with anothers clients, both from LAN and WAN, nobody can see and hear each other.

I have a firewall which do NAT to an nginx reverse proxy.
UDP test (Tip: how to check UDP/10000 connectivity) work great, both from LAN and WAN.

My reverse proxy setings :

location / {
                proxy_pass http://INTERNAL_IP;
                proxy_set_header X-Forwarded-For $remote_addr;
                proxy_set_header Host $http_host;
        }

        # BOSH
        location = /http-bind {
                proxy_pass http://INTERNAL_IP:5280/http-bind?prefix=$1&$args;
                proxy_set_header X-Forwarded-For $remote_addr;
                proxy_set_header Host $http_host;
        }

        # xmpp websockets
        location = /xmpp-websocket {
                proxy_pass http://INTERNAL_IP:5280/xmpp-websocket?prefix=$1&$args;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_set_header Host $http_host;
                tcp_nodelay on;
        }

        # colibri websockets
        location ~ ^/colibri-ws/default-id/(.*) {
                proxy_pass http://INTERNAL_IP:9090/colibri-ws/default-id/$1$is_args$args;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                tcp_nodelay on;
        }

In my jitsi nginx config, I comment all the http 80 block, change the 443 block to listen to 80 and comment the certificate config line.

On my Firewall, I NAT port TCP 80, 443 and UDP 10000 to my reverse proxy, and forward from my reverse proxy TCP 80, 5280, 9090 and UDP 10000 to my Jitsi VM.

What am I doing wrong ?

Regards.

jitsi doesn’t work without https

Not sure whether prosody listens by default on all interfaces or on localhost only, check that

Hello,

I completly reinstall jitsi on a fresh debian 10 with my certificate from letsencrypt, wich is already used on the reverse proxy.
According to the prosody documentation, by default it listen to all local interfaces. To be sure, I add in the config the line :

interfaces = { "*" }

Now from LAN, I have the sound but not the video.
From WAN, no sound and no video.

I have this error in jvb.log :

JVB 2021-07-19 16:16:23.277 GRAVE: [24] HealthChecker.run#175: Health check failed in PT0.000142S:
java.lang.Exception: Address discovery through STUN failed
at org.jitsi.videobridge.health.JvbHealthChecker.check(JvbHealthChecker.kt:40)
at org.jitsi.videobridge.health.JvbHealthChecker.access$check(JvbHealthChecker.kt:25)
at org.jitsi.videobridge.health.JvbHealthChecker$healthChecker$1.invoke(JvbHealthChecker.kt:32)
at org.jitsi.videobridge.health.JvbHealthChecker$healthChecker$1.invoke(JvbHealthChecker.kt:25)
at org.jitsi.health.HealthChecker.run(HealthChecker.kt:145)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor.run(RecurringRunnableExecutor.java:216)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor.runInThread(RecurringRunnableExecutor.java:292)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor.access$000(RecurringRunnableExecutor.java:36)
at org.jitsi.utils.concurrent.RecurringRunnableExecutor$1.run(RecurringRunnableExecutor.java:328)

You might want to check your firewall to make sure all required ports are open and properly forwarded.

TCP 80, 443, 5280, 9090, 5349 and UDP 10000, 3478 are open from LAN and WAN to reverse proxy and from reverse proxy to jitsi.
UDP 10000 check is fine both from LAN and WAN.

Ok some news here.

With the nginx reverse proxy, Chrome client with Android client works in p2p mode, Firefox doesn’t work in p2p mode and 3 cllients failed.

I bypass my reverse proxy to directly connect to jitsi on LAN.
3 LAN clients, everythings work great.
I can reproduce the problem when I block UDP 10000 in this no reverse proxy config.

So the problem come from the nginx reverse proxy, not the firewall.
Here my config (changed from first post) :

server_names_hash_bucket_size 64;

types {
        application/wasm     wasm;
}

server {
        listen  80;
        server_name meet.domain.tld;
        return 301 https://meet.domain.tld$request_uri;
}

server {
        server_name meet.domain.tld;
        listen 443 ssl http2;

        ssl_certificate /etc/letsencrypt/live/meet.domain.tld/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/meet.domain.tld/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        #add_header Strict-Transport-Security "max-age=63072000" always;

        access_log /var/log/nginx/meet.access.log;
        error_log /var/log/nginx/meet.error.log;

        location / {
                proxy_pass https://@JITSI_IP:443;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;

                # WebSocket support
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
        }
}

upstream jitsi_upstreams {
        server @JITSI_IP:10000;
}

server {
        listen 10000 udp;
        proxy_pass jitsi_upstreams;
        proxy_timeout 1s;
        proxy_responses 0;
        error_log /var/log/nginx/dns.log;
}

Did someone have already deal with nginx reverse proxy ?

If you block UDP traffic, you need to use TURN to relay media. So you’ll need a TURN server.

UDP it’s not blocked.

But I think I found the problem.

I do a tcpdump on my firewall and I see the UDP packets forwarded to the jitsi VM instead of reverse proxy.
So the udp never arrived in my jitsi VM because I only autorized UDP to go to reverse proxy.
Do you know how to change that ?

The UDP traffic should go directly to JVB (jitsi VM).

Yes, that’s finally what I did and everything work.
For the sake, here my working config (SSL is handled by @RPROXY and @JITSI is only HTTP 80 backend):

@RPROXY :

server_names_hash_bucket_size 64;

types {
        application/wasm     wasm;
}

server {
        listen  80;
        server_name meet.domain.tld;
        return 301 https://meet.domain.tld$request_uri;
}

server {
        server_name meet.domain.tld;
        listen 443 ssl http2;

        ssl_certificate /etc/letsencrypt/live/meet.domain.tld/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/meet.domain.tld/privkey.pem;
        include /etc/letsencrypt/options-ssl-nginx.conf;
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        add_header Strict-Transport-Security "max-age=63072000" always;

        access_log /var/log/nginx/meet.access.log;
        error_log /var/log/nginx/meet.error.log;

        location / {
                proxy_pass https://@JITSI_IP:443;

                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;

                # WebSocket support
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
        }
}

@JITSI :

server_names_hash_bucket_size 64;

types {
    application/wasm     wasm;
}

server {
    listen 80;
    #listen [::]:443 ssl;
    server_name meet.domain.tld;

    set_real_ip_from @RPROXY_IP;
    real_ip_header X-Real-IP;

    # Mozilla Guideline v5.4, nginx 1.17.7, OpenSSL 1.1.1d, intermediate con$
    #ssl_protocols TLSv1.2 TLSv1.3;
    #ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:E$
    #ssl_prefer_server_ciphers off;

    #ssl_session_timeout 1d;
    #ssl_session_cache shared:SSL:10m;  # about 40000 sessions
    #ssl_session_tickets off;

    #add_header Strict-Transport-Security "max-age=63072000" always;
    set $prefix "";

    #ssl_certificate /etc/ssl/fullchain.pem;
    #ssl_certificate_key /etc/ssl/privkey.pem;

    root /usr/share/jitsi-meet;

    # ssi on with javascript for multidomain variables in config.js
    ssi on;
    ssi_types application/x-javascript application/javascript;

    index index.html index.htm;

    ALL DEFAULT BELOW
}

/etc/jitsi/videobridge/sip-communicator.properties :

#org.ice4j.ice.harvest.DISABLE_AWS_HARVESTER=true
#org.ice4j.ice.harvest.STUN_MAPPING_HARVESTER_ADDRESSES=meet-jit-si-turnrela$
org.ice4j.ice.harvest.NAT_HARVESTER_LOCAL_ADDRESS=@JITSI_IP
org.ice4j.ice.harvest.NAT_HARVESTER_PUBLIC_ADDRESS=@PUBLIC_IP

On the JITSI VM, nslookup meet.domain.tld resolv to @RPROXY_IP

And on the firewall :

  • Redirect LAN & WAN 443 to @RPROXY_IP
  • Redirect LAN UDP 10000 to @JITSI
  • PAT WAN UDP 10000 to @JITSI

Thanks for the help :slight_smile: