Running Jitsi Meet behind a reverse proxy when 10000/UDP is blocked by client's network

First of all I want to give thanks for the great work on Jitsi Meet. Especially the Jitsi Meet Handbook is very helpful when starting with Jitsi Meet.

I know there are already lots of topics about firewalling problems. I decided to start a new topic because I couldn’d find a solution for my problem.

We are running a Jitsi Meet instance behind a corporate firewall. It is configured according to the Self-Hosting Guide. We also applied the steps provided unter advanced configuration.

Our firewall proxies external (only HTTP - it can’t handle pure TCP connections) requests to the Jitsi server which arrive my external gateway via 443/TCP and 80/TCP. 10000/UDP is forwarded to the Jitsi server. 4443/TCP is NOT opened as I think this was only in earlier configuration but is no more used according to the Self-Hosting Handbook.

This configuration runs like a charm from

  • the internal network
  • external non restricted networks (e.g. 10000/UDP opened)

When somebody tries to connect from within an external network with restricted firewall settings, especially if outgoing 10000/UDP is blocked, video/audio is not working.

In my understanding Jitsi then should fall back on 443/TCP. Is this right?
Falling back on 443/TCP from external networks won’t work for me as my reverse proxy is only able to handle HTTP/S. Correct?

If my presumptions are true, what would be best practise to get external restricted clients running as well? Or is there no way to get it working then?

Many thanks in advance!

If configured. The default setup in latest stable defaults running coturn on default ports 5347 for tls connections and is not using port 443. You need a second DNS to configure this: https://jitsi.github.io/handbook/docs/devops-guide/turn#use-turn-server-on-port-443

Thanks for your help. I tried it out but ist doesn’t work either.

I guess that it fails because the reverse proxy at my internet gateway isn’t able to handle http/2. So HTTPS passes through the gateway but TCP fallback to 443/TCP (which is NO HTTPS as I assume?) drops. Is that possible? If so, I could try to circumvent the reverse proxy at my gateway. I’ll change dns to a dedicated ip address where I can portforward 443/TCP instead of proxying it. Would you agree with me @damencho that this should work?

Yep

I tested it out with two different dns entries. I’ve made further progress on it but it still doesn’t work.

Now turnserver log shows me the client’s local IP address where I would expect its external address.

Dec  8 08:25:37 jitsi turnserver: 403462: handle_udp_packet: New UDP endpoint: local addr 192.168.5.60:3478, remote addr 172.16.30.37:50778
Dec  8 08:25:37 jitsi turnserver: 403462: session 003000000000000005: realm <jitsi.mydomain.com> user <>: incoming packet BINDING processed, success
Dec  8 08:25:37 jitsi turnserver: 403462: session 003000000000000005: realm <jitsi.mydomain.com> user <>: incoming packet message processed, error 401: Unauthorized
Dec  8 08:25:37 jitsi turnserver: 403462: IPv4. Local relay addr: 192.168.5.60:57449
Dec  8 08:25:37 jitsi turnserver: 403462: session 003000000000000005: new, realm=<jitsi.mydomain.com>, username=<1607502335>, lifetime=600
Dec  8 08:25:37 jitsi turnserver: 403462: session 003000000000000005: realm <jitsi.mydomain.com> user <1607502335>: incoming packet ALLOCATE processed, success
Dec  8 08:25:44 jitsi turnserver: 403469: A peer IP 192.168.101.107 denied in the range: 192.168.0.0-192.168.255.255
Dec  8 08:25:44 jitsi turnserver: 403469: session 003000000000000005: realm <jitsi.mydomain.com> user <1607502335>: incoming packet CREATE_PERMISSION processed, error 403: Forbidden IP
Dec  8 08:25:44 jitsi turnserver: 403469: session 003000000000000005: realm <jitsi.mydomain.com> user <1607502335>: incoming packet message processed, error 403: Forbidden IP

I’ll doublecheck the configuration.

coturn does not support proxy protocol.

The external client (192.168.101.107) is directly connected to the internet, there is no proxy. 172.16.30.37 is an internal client. 192.168.5.60 is my jitsi server (located in DMZ).

I do not understand this at all - how can you be on the internet with a private IP address ?

I can’t.

192.168.101.107 is the internal address of a client in a home network. In fact there’s a home router between the client and the internet. “Directly connected” was inartfully expressed. :slight_smile: It was related to a possible proxy.

was not the thread about a proxy ? this is dizzying - should I really get a headache trying to understand your setup ?

Right, it was not the thread about a proxy. It is a thread about running jitsi behind a reverse proxy, not about connecting a client behind a proxy.

Hope this helps to clarify…

jitsi.mydomain.com is public ip address of my jitsi server.
turn-jitsi.mydomain.com points to the same public ip address.

HTTPS coming to jitsi.mydomain.com is handled by reverse proxy.

443/TCP coming to turn-jitsi.mydomain.com is port forwarded to 192.168.5.60.

If 10000/UDP at client side is unrestricted everything works fine.
If 10000/UDP is blocked by firewall restriction at client side it doesn’t.

Can you share

  • the Nginx config which manages the TURN traffic

  • /etc/turnserver.conf

  • /etc/prosody/conf.d/YOUR-DOMAIN.cfg.lua

/etc/nginx/sites-enabled/jitsi.mydomain.com.conf

server_names_hash_bucket_size 64;

server {
    listen 80;
    listen [::]:80;
    server_name jitsi.mydomain.com;

    location ^~ /.well-known/acme-challenge/ {
       default_type "text/plain";
       root         /usr/share/jitsi-meet;
    }
    location = /.well-known/acme-challenge/ {
       return 404;
    }
    location / {
       return 301 https://$host$request_uri;
    }
}
server {
    listen 4444 ssl;
    listen [::]:4444 ssl;
    server_name jitsi.mydomain.com;

[…]

/etc/nginx/modules-enabled/jitsi-multiplex-turnserver.conf

stream {
    map $ssl_preread_server_name $name {
        jitsi.mydomain.com web_backend;
        turn-jitsi.mydomain.com turn_backend;
    }

    upstream web_backend {
        server 127.0.0.1:4444;
    }

    upstream turn_backend {
        server <MY_PUBLIC_IP>:443;
    }

    server {
        listen 443;
        listen [::]:443;

        # since 1.11.5
        ssl_preread on;

        proxy_pass $name;

        # Increase buffer to serve video
        proxy_buffer_size 10m;
    }
}

/etc/turnserver.conf

# jitsi-meet coturn config. Do not modify this line
use-auth-secret
keep-address-family
static-auth-secret=<SECRET>
realm=jitsi.mydomain.com
cert=/etc/coturn/certs/turn-jitsi.mydomain.com.fullchain.pem
pkey=/etc/coturn/certs/turn-jitsi.mydomain.com.privkey.pem
no-multicast-peers
no-cli
no-loopback-peers
no-tcp-relay
no-tcp
listening-port=3478
tls-listening-port=5349
no-tlsv1
no-tlsv1_1
# https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=intermediate&openssl=1.1.0g&guideline=5.4
cipher-list=ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
# jitsi-meet coturn relay disable config. Do not modify this line
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=172.16.0.0-172.31.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=192.88.99.0-192.88.99.255
denied-peer-ip=192.168.0.0-192.168.255.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
denied-peer-ip=240.0.0.0-255.255.255.255
syslog

/etc/prosody/conf.d/jitsi.mydomain.com.cfg.lua

plugin_paths = { "/usr/share/jitsi-meet/prosody-plugins/" }

-- domain mapper options, must at least have domain base set to use the mapper
muc_mapper_domain_base = "jitsi.mydomain.com";

turncredentials_secret = "<SECRET_same_as_in_turnserver.conf>";

turncredentials = {
  { type = "stun", host = "jitsi.mydomain.com", port = "3478" },
--  { type = "turn", host = "jitsi.mydomain.com", port = "3478", transport = "udp" },
--  { type = "stun", host = "turn-jitsi.mydomain.com", port = "443" },
  { type = "turn", host = "jitsi.mydomain.com", port = "3478", transport = "udp" },
  { type = "turns", host = "turn-jitsi.mydomain.com", port = "443", transport = "tcp" }
};

cross_domain_bosh = false;
consider_bosh_secure = true;
-- https_ports = { }; -- Remove this line to prevent listening on port 5284

-- https://ssl-config.mozilla.org/#server=haproxy&version=2.1&config=intermediate&openssl=1.1.0g&guideline=5.4
ssl = {
  protocol = "tlsv1_2+";
  ciphers = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384"
}

VirtualHost "jitsi.mydomain.com"
        -- enabled = false -- Remove this line to enable this host
        authentication = "anonymous"
        -- Properties below are modified by jitsi-meet-tokens package config
        -- and authentication above is switched to "token"
        --app_id="example_app_id"
        --app_secret="example_app_secret"
        -- Assign this host a certificate for TLS, otherwise it would use the one
        -- set in the global section (if any).
        -- Note that old-style SSL on port 5223 only supports one certificate, and will always
        -- use the global one.
        ssl = {
                key = "/etc/prosody/certs/jitsi.mydomain.com.key";
                certificate = "/etc/prosody/certs/jitsi.mydomain.com.crt";
        }
        speakerstats_component = "speakerstats.jitsi.mydomain.com"
        conference_duration_component = "conferenceduration.jitsi.mydomain.com"
        -- we need bosh
        modules_enabled = {
            "bosh";
            "pubsub";
            "ping"; -- Enable mod_ping
            "speakerstats";
            "turncredentials";
            "conference_duration";
            "muc_lobby_rooms";
        }
        c2s_require_encryption = false
        lobby_muc = "lobby.jitsi.mydomain.com"
        main_muc = "conference.jitsi.mydomain.com"
        -- muc_lobby_whitelist = { "recorder.jitsi.mydomain.com" } -- Here we can whitelist jibri to enter lobby enabled rooms

Component "conference.jitsi.mydomain.com" "muc"
    storage = "none"
    modules_enabled = {
        "muc_meeting_id";
        "muc_domain_mapper";
        -- "token_verification";
    }
    admins = { "focus@auth.jitsi.mydomain.com" }
    muc_room_locking = false
    muc_room_default_public_jids = true

-- internal muc component
Component "internal.auth.jitsi.mydomain.com" "muc"
    storage = "none"
    modules_enabled = {
      "ping";
    }
    admins = { "focus@auth.jitsi.mydomain.com", "jvb@auth.jitsi.mydomain.com" }
    muc_room_locking = false
    muc_room_default_public_jids = true

VirtualHost "auth.jitsi.mydomain.com"
    ssl = {
        key = "/etc/prosody/certs/auth.jitsi.mydomain.com.key";
        certificate = "/etc/prosody/certs/auth.jitsi.mydomain.com.crt";
    }
    authentication = "internal_plain"

Component "focus.jitsi.mydomain.com"
    component_secret = "<ANOTHER_SECRET>"

Component "speakerstats.jitsi.mydomain.com" "speakerstats_component"
    muc_component = "conference.jitsi.mydomain.com"

Component "conferenceduration.jitsi.mydomain.com" "conference_duration_component"
    muc_component = "conference.jitsi.mydomain.com"

Component "lobby.jitsi.mydomain.com" "muc"
    storage = "none"
    restrict_room_creation = true
    muc_room_locking = false
    muc_room_default_public_jids = true

Versions:

nginx version: nginx/1.14.0 (Ubuntu)

Prosody 0.10.0

Version Coturn-4.5.0.7 'dan Eider'

Package Versions:

jitsi-meet             2.0.5142-1
jitsi-meet-prosody     1.0.4466-1
jitsi-meet-turnserver  1.0.4466-1
jitsi-meet-web         1.0.4466-1
jitsi-meet-web-config  1.0.4466-1
jitsi-videobridge2     2.1-376-g9f12bfe2-1

Can you try to set the local IP on the Nginx’s turn_backend

upstream turn_backend {
    server 192.168.5.60:5349;
}

And allow the related IP in turnserver.conf

listening-ip=192.168.5.60
allowed-peer-ip=192.168.5.60
no-udp

Assuming the certificate is OK for coturn and JVB is on the same server

1 Like

I’ll test it out, thanks a lot.

Certificate is LE according to https://jitsi.github.io/handbook/docs/devops-guide/turn

All components run on the same server.

OK, recognise one suspicious thing which I don’t fully understand.

My (standard) configuration file has also

no-tcp-relay
no-tcp

Do I have to comment one of these entries?

No. you have dtls

This does the magic! Thank you so much!

I still see the local addresses in my logs an there are several permission denied and fobidden ip entries but now it works.

Dec 11 12:40:34 jitsi turnserver: 263: IPv4. tcp or tls connected to: 192.168.5.60:37260
Dec 11 12:40:34 jitsi turnserver: 263: session 000000000000000003: realm <jitsi.mydomain.com> user <>: incoming packet message processed, error 401: Unauthorized
Dec 11 12:40:34 jitsi turnserver: 263: IPv4. Local relay addr: 192.168.5.60:52514
Dec 11 12:40:34 jitsi turnserver: 263: session 000000000000000003: new, realm=<jitsi.mydomain.com>, username=<1607776833>, lifetime=600, cipher=TLS_AES_256_GCM_SHA384, method=UNKNOWN
Dec 11 12:40:34 jitsi turnserver: 263: session 000000000000000003: realm <jitsi.mydomain.com> user <1607776833>: incoming packet ALLOCATE processed, success
Dec 11 12:40:34 jitsi turnserver: 263: IPv4. tcp or tls connected to: 192.168.5.60:37262
Dec 11 12:40:34 jitsi turnserver: 263: session 003000000000000002: realm <jitsi.mydomain.com> user <>: incoming packet message processed, error 401: Unauthorized
Dec 11 12:40:34 jitsi turnserver: 263: IPv4. Local relay addr: 192.168.5.60:56360
Dec 11 12:40:34 jitsi turnserver: 263: session 003000000000000002: new, realm=<jitsi.mydomain.com>, username=<1607776833>, lifetime=600, cipher=TLS_AES_256_GCM_SHA384, method=UNKNOWN
Dec 11 12:40:34 jitsi turnserver: 263: session 003000000000000002: realm <jitsi.mydomain.com> user <1607776833>: incoming packet ALLOCATE processed, success
Dec 11 12:40:34 jitsi turnserver: 263: session 003000000000000002: peer 192.168.5.60 lifetime updated: 300
Dec 11 12:40:34 jitsi turnserver: 263: session 003000000000000002: realm <jitsi.mydomain.com> user <1607776833>: incoming packet CREATE_PERMISSION processed, success
Dec 11 12:40:34 jitsi turnserver: 263: session 003000000000000002: peer xxx.xxx.xxx.xxx lifetime updated: 300
Dec 11 12:40:34 jitsi turnserver: 263: session 003000000000000002: realm <jitsi.mydomain.com> user <1607776833>: incoming packet CREATE_PERMISSION processed, success
Dec 11 12:40:34 jitsi turnserver: 263: session 003000000000000002: peer 192.168.5.60 lifetime updated: 600
Dec 11 12:40:34 jitsi turnserver: 263: session 003000000000000002: realm <jitsi.mydomain.com> user <1607776833>: incoming packet CHANNEL_BIND processed, success
Dec 11 12:40:34 jitsi turnserver: 264: A peer IP 172.16.30.37 denied in the range: 172.16.0.0-172.31.255.255
Dec 11 12:40:34 jitsi turnserver: 264: session 000000000000000003: realm <jitsi.mydomain.com> user <1607776833>: incoming packet CREATE_PERMISSION processed, error 403: Forbidden IP
Dec 11 12:40:34 jitsi turnserver: 264: session 000000000000000003: realm <jitsi.mydomain.com> user <1607776833>: incoming packet message processed, error 403: Forbidden IP

Is this still an issue to solve?

The documentation should be updated. How can I tell to update the Handbook?

 upstream turn_backend {
        server __your_public_ip__:5349;
    }

should be

 upstream turn_backend {
        server __your_local_ip__:5349;
    }