WSS not able to connect

Hello I’m following the guide for OpenVidu CE on premise also trying to establish a connection using openvidu-tutorials\openvidu-react.

I’m able to create a Session but when I connect I get the following error: org.springframework.web.socket.server.support.DefaultHandshakeHandler - Handshake failed due to invalid Upgrade header:

I’m fairly confident the issue is with the proxy configuration but I can’t quite figure out what the configuration should look like.

I’m using apache as a proxy and here is the vhost config for that:

<VirtualHost *:443>
    ServerName video.***.com
    
    SSLEngine On
    SSLCertificateFile /home/com.crt
    SSLCertificateKeyFile /home/com.key
    SSLCertificateChainFile /home/ServerCA.crt
    LogLevel trace4
    Timeout 60
    ProxyTimeout 60

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyVia Full

    <Proxy *>
        Require all granted
    </Proxy>

    SSLProxyEngine on

    # ProxyPass for WebSocket
    <Location "/wss">
        ProxyPass "wss://192.168.254.11:3478/"
        ProxyPassReverse "wss://192.168.254.11:3478/"
        RewriteEngine On
        RewriteCond %{HTTP:Upgrade} websocket [NC]
        RewriteCond %{HTTP:Connection} upgrade [NC]
        RewriteRule /wss/(.*) "ws://192.168.254.11:3478/$1" [P]
    </Location>

    # ProxyPass for HTTP
    <Location "/">
        ProxyPass "http://192.168.254.11:5443/"
        ProxyPassReverse "http://192.168.254.11:5443/"
    </Location>

    <Directory "/opt/openvidu/">
        AllowOverride All
    </Directory>

    KeepAliveTimeout 60
    KeepAlive On
</VirtualHost>

I am using owncert and I believe its working because I am able to create a Session just fine. Also I have full control of what ports are open and have opened the ports as described on the docs.

Any help would be immensely appreciated.

Websocket connection goes through “/openvidu” path over port 5443.

Why don’t you use the openvidu-proxy from the official deployment and connect directly to the OpenVidu CE Machine? What kind of setup you want to achieve?

I think your setup would not work over the public internet. OpenVidu CE needs to be installed in a machine with a public IP and port 3478 TCP/UDP needs to be open for WebRTC media. Even we recommend ports 40000-65535 to be open to not relay all traffic over Coturn and make WebRTC connections goes directly over that range of ports.

I deduce from your Apache, that maybe you want to deploy a machine and proxy all the traffic from that Machine to OpenVidu Server. Am I right?

If that’s your use case, you need to:

  1. Fix your apache. I understand better nginx, but I think you just need to remove de /wss path and modify the / path like this (I did not test it):

    <Location "/">
            # Proxy for HTTP
            ProxyPass http://192.168.254.11:5443/
            ProxyPassReverse http://192.168.254.11:5443/
    
            # Enable rewrite engine
            RewriteEngine On
    
            # Proxy for WebSocket
            RewriteCond %{HTTP:Upgrade} =websocket [NC]
            RewriteRule /(.*) ws://192.168.254.11:5443/$1 [P,L]
            RewriteCond %{HTTP:Upgrade} !=websocket [NC]
            RewriteRule /(.*) http://192.168.254.11:5443/$1 [P,L]
    </Location>
    

    This is because websocket goes through http path /openvidu at the same port 5443

  2. Deploy Coturn in the same machine as apache at port 3478. This port should not be proxied and reachable through the public IP of that machine and Coturn should be reachable by OpenVidu Server and viceversa.

  3. Configure OpenVidu Server to use that Coturn. You can do it with the property OPENVIDU_WEBRTC_ICE_SERVERS (Allow users behind firewalls - OpenVidu Docs):

    With a fixed user will be:

    OPENVIDU_WEBRTC_ICE_SERVERS=["url=turn:<TURN_DOMAIN_NAME>:3478,username=<your_username>,credential=<your_credential>"]
    

    With a shared secret it would be:

    OPENVIDU_WEBRTC_ICE_SERVERS=["url=turn:<TURN_DOMAIN_NAME>:3478,staticAuthSecret=<TURN_STATIC_AUTH_SECRET>"]
    
  4. DOMAIN_OR_PUBLIC_IP property should be the domain configured in your Apache server.

In this way, HTTP and websocket requests would go through the Apache proxy 443 and proxied to OpenVidu, and Media through the Coturn 3478 port and relayed to the media server.

But it is fairly easy to just deploy OpenVidu CE in a machine with a public IP. Or with ports correctly redirected to the private machine if you’re in a NAT environment. Make everything goes through another machine complicate things a little bit.

First off thank you for taking the time to reply!! My goal is to use the coturn server that is deployed with OpenVidu’s docker image. With that in mind here is my setup. I host several websites so I have the need for a reverse proxy. I’ve tried both Apache and nginx with the exact same result. I only have one server and there is no NAT.

external_ip → router (fowards port 443 to server)-> Apache (depending on website forwards to correct service) → OpenVidu

Doing telnet 3478 external_ip it connects without issues. I also have ports 40000-65535 open.
I tried testing using this online tool but not sure where I create/set the userName/password for the coturn server. If I’m not mistaken the included coturn server that is deployed with OpenVidu’s docker image has a file called shared-secret-key and with in there there is a value COTURN_SHARED_SECRET_KEY. Is that the staticAuthSecret??

As for the proxy configs… The one you posted above ends up giving me a CORS error on the front end and not sure how I’d configure CORS on OpenVidu. I have the following config on apache that does reach OpenVidu and creates a token but when the websocket tries to connect something is either misconfigured or is not able to reach something? (I’m guessing is not able to reach coturn):

<VirtualHost *:443>
    ServerName video.****.com
    ServerAlias www.video.***.com
    ServerAlias video.***.com

     SSLEngine On
    SSLCertificateFile /home/com.crt
    SSLCertificateKeyFile /home/com.key
    SSLCertificateChainFile /home/ServerCA.crt
    LogLevel debug
    Timeout 60
    ProxyTimeout 60

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyVia Full

    <Proxy *>
        Require all granted
    </Proxy>

    SSLProxyEngine on

     # ProxyPass for HTTP
    <Location "/">
        ProxyPass "http://192.168.254.11:5443/"
        ProxyPassReverse "http://192.168.254.11:5443/"

    </Location>

     # ProxyPass for WebSocket
    <Location "/wss">
        ProxyPass "ws://192.168.254.11:5443/"
        ProxyPassReverse "ws://192.168.254.11:5443/"
        RewriteEngine On
        RewriteCond %{HTTP:Upgrade} websocket [NC]
        RewriteCond %{HTTP:Connection} upgrade [NC]
        RewriteRule .* "http://192.168.254.11:5443/$1" [P]
    </Location>


    <Directory "/opt/openvidu/">
        AllowOverride All
    </Directory>

    KeepAliveTimeout 60
    KeepAlive On
</VirtualHost>

I also turned off apache thinking it was a bug with wstunnel and here is my nginx config that gave me the exact same result as apache (able to create a session and a token but the websocket is unable to connect):

server {
    listen 443 ssl;
    server_name video.****.com www.video.****.com;

    ssl_certificate /home/com.crt;
    ssl_certificate_key /home/com.key;
    ssl_trusted_certificate /home/ServerCA.crt;

    ssl_session_timeout 5m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    location /wss {
        proxy_pass https://192.168.254.11:5443/;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }

    location / {
        proxy_pass http://192.168.254.11:5443/;
    }

    location /opt/openvidu/ {
        allow all;
        satisfy any;
        allow 127.0.0.1;
        deny all;
        auth_basic "Restricted";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }

    keepalive_timeout 60s;
    keepalive_requests 100;

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

My OpenVidu .env has:

DOMAIN_OR_PUBLIC_IP=video.****.com

CERTIFICATE_TYPE=owncert

#added but I really don't think i need this because coturn is deployed with OpenVidu docker image
OPENVIDU_WEBRTC_ICE_SERVERS=["url=turn:video.****.com:3478,staticAuthSecret=*******"]

Everything else in that .env file is as it came when I downloaded OpenVidu. I’m fairly confident the certs are working because when I first installed OpenVidu I had an issue with them and I wasn’t even able to create a token. After fixing the certs I was able to create a token when calling OpenVidu.

Here is logs from OpenVidu using the proxy config above:

openvidu-openvidu-server-1  | [INFO] 2023-06-09 14:27:15,414 [http-nio-0.0.0.0-5443-exec-5] io.openvidu.server.rest.SessionRestController - REST API: POST /openvidu/api/sessions/SessionA/connection {id=SessionA, object=session, sessionId=SessionA, createdAt=1686320835288, recording=false, broadcasting=false, mediaMode=ROUTED, recordingMode=MANUAL, defaultRecordingProperties={name=, hasAudio=true, hasVideo=true, outputMode=COMPOSED, recordingLayout=BEST_FIT, resolution=1280x720, frameRate=25, shmSize=536870912}, customSessionId=SessionA, forcedVideoCodec=MEDIA_SERVER_PREFERRED, allowTranscoding=false, connections={numberOfElements=0, content=[]}}
openvidu-openvidu-server-1  | [INFO] 2023-06-09 14:27:15,427 [http-nio-0.0.0.0-5443-exec-5] io.openvidu.server.rest.SessionRestController - Generated token wss://video.****.com?sessionId=SessionA&token=tok_AADGgKBEHWUWUu2M
openvidu-openvidu-server-1  | [INFO] 2023-06-09 14:28:40,461 [http-nio-0.0.0.0-5443-exec-7] io.openvidu.server.config.HttpHandshakeInterceptor - New HttpSession 401270C46746A9055AC2EB40194DF785
openvidu-openvidu-server-1  | [ERROR] 2023-06-09 14:28:40,462 [http-nio-0.0.0.0-5443-exec-7] org.springframework.web.socket.server.support.DefaultHandshakeHandler - "Handshake failed due to invalid Upgrade header: null"
openvidu-openvidu-server-1  | [INFO] 2023-06-09 14:28:51,480 [http-nio-0.0.0.0-5443-exec-8] io.openvidu.server.config.HttpHandshakeInterceptor - New HttpSession 1398A4D5E6EF075FF1059D20B7668BC1
openvidu-openvidu-server-1  | [ERROR] 2023-06-09 14:28:51,480 [http-nio-0.0.0.0-5443-exec-8] org.springframework.web.socket.server.support.DefaultHandshakeHandler - "Handshake failed due to invalid Upgrade header: null"


On the front-end I get the following error:

WebSocket connection to 'wss://video.****.com/openvidu?sessionId=SessionA' failed: 
	WebSocketWithReconnection @ webSocketWithReconnection.js:45
	JsonRpcClient @ jsonrpcclient.js:136
	OpenVidu.startWs @ OpenVidu.ts:884
	(anonymous) @ Session.ts:1599
	Session.connectAux @ Session.ts:1598
	(anonymous) @ Session.ts:178
	Session.connect @ Session.ts:168
	(anonymous) @ App.js:126

Is this enough information that will help you help me?? My goal is to use as much out of the box as possible since OpenVidu is pretty rad.

Why are you proxying /wss ? Websocket connection in OpenVidu goes through /openvidu.

In fact your front-end complains about not being able to connect via websocket to wss://video.****.com/openvidu?sessionId=SessionA.

Maybe that’s the main issue.

Note: You are correct with ICE server config. COTURN_SHARED_SECRET_KEY is the configured secret for that Coturn. In fact, if OpenVidu Server has its own public IP, it autodiscover it and configure it as the ICE server and sends it to the clients. If that’s the case as I can see, you don’t need to define OPENVIDU_WEBRTC_ICE_SERVERS

I commented out the /wss part from the vhost. Still get the same result where it cannot reach wss://video.****.com/openvidu?sessionId=SessionA

My theory was that it wasn’t able to reach it because it needed the proxy to route it. But clearly that was not it.

I also remove the ICE server from the openvidu .env file. Not really sure what else to try with this implementation.

From some more digging around I think the problem is that is not reaching the Kurento server for some reason.

`023-06-09T15:22:58,595467 1 0x00007f58c5348280 info KurentoServerMethods ServerMethods.cpp:88 ServerMethods() Using above 80% of system limits will throw NOT_ENOUGH_RESOURCES exception

2023-06-09T15:22:58,595495 1 0x00007f58c5348280 info KurentoServerMethods ServerMethods.cpp:107 ServerMethods() System limits: unlimited threads, 1048576 files

2023-06-09T15:22:58,595582 1 0x00007f58c5348280 info KurentoWorkerPool WorkerPool.cpp:67 WorkerPool() Worker thread pool size: 16

2023-06-09T15:22:58,596547 1 0x00007f58c5348280 info KurentoServerMethods ServerMethods.cpp:143 ServerMethods() RPC Request Cache is ENABLED
2023-06-09T15:22:58,596680 1 0x00007f58c5348280 info KurentoWebSocketTransport WebSocketTransport.cpp:203 initWebSocket() WebSocket server (ws://) listening on address ‘::’, port 8888

2023-06-09T15:22:58,596705 1 0x00007f58c5348280 info KurentoWebSocketTransport WebSocketTransport.cpp:89 WebSocketTransport() Secure WebSocket server (wss://) not enabled

2023-06-09T15:22:58,597031 1 0x00007f58c5348280 info KurentoMediaServer main.cpp:259 main() Kurento Media Server started

2023-06-21T03:39:19,839012 1 0x00007f58b87e9700 error KurentoWebSocketTransport WebSocketTransport.cpp:583 openHandler() Invalid path “/”, closing connection`

The very last entry was my attempt at going through wscat to port 8888. I’m not sure if there is something that I need to configure further for the Kurentor server to be “discoverable”? Perhaps I also need to make Kurento accept wss connections?

Well, is the websocket at least working? Until the websocket connection is connected (the browser->openvidu connection, not the openvidu->kurento), and the process of connection is not established, the browser will not try to connect to the Kurento Media Server.

Have you installed openvidu here - http://192.168.254.11:5443?

Is this issue resolved?

This is not an issue itself, it’s just a complicated deployment setup.

If you have a problem with your deployment, just create a new issue.

I will close this one.