0

I have a working websocket which can be reached from my clientside code like this: (Not using Socket.io or any library, just plain html5 websockets)

ws://localhost:9000/socket/connect

The Websocket is implemented in Java Play Framework

public WebSocket connect() {
    return WebSocket.Text.accept(request -> ActorFlow.actorRef(out -> SocketActor.props(out, jsonWebToken),
            actorSystem, materializer
    )
    );
}

Anyway this is working fine, however I now want to set up https for the website and am doing this on nginx. Switching to https I also need to use the wss protocol instead of ws, therefore I want to proxy wss calls as well through nginx and hereby I am facing issues.

I have configured my nginx for the websocket proxy as stated here https://www.nginx.com/blog/websocket-nginx/ My complete config looks like this

upstream backend {
        server backend:9000;
}

server {
        listen 80;
        server_name _;
        return 301 https://$host$request_uri;
}

server {
        listen 443 ssl;
        server_name legato;
        ssl_certificate /etc/nginx/ssl/legato.crt;
        ssl_certificate_key /etc/nginx/ssl/legato.key;

        location /api {
                return 302 /api/;
        }
        location /api/ {
                proxy_pass http://backend/;
        }
        location /statics {
                root /var/www;
        }
        location /socket/connect {
                proxy_pass http://backend/;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $connection_upgrade;
        }
        location / {
            root /var/www/frontend;
            index index.html;

            try_files $uri /index.html;
        }
}

so the /socket/connect route is forwarded to the websocket backend route.

From my clientside javascript code I am opening the websocket now like this

socket = new WebSocket(wss://192.168.155.177/socket/connect);

which gives me the error

WebSocket connection to 'wss://192.168.155.177/socket/connect' failed: Error during WebSocket handshake: Unexpected response code: 200

Can somebody explain to me what is wrong in this case?

Rich Dougherty
  • 3,231
  • 21
  • 24
Jakob Abfalter
  • 4,980
  • 17
  • 54
  • 94

1 Answers1

0

I found a little workaround for this issue, gonna leave it here for anybody in the future.

So I was trying:

  • Implement SSL encryption for the Websockets on NGINX. This didn't work because NGINX would connect to the websocket via http again. Since I am not using any socket.io this didn't work as the backend does not support it
  • Implement SSL on backend side. This was rather tricky to me. Switching to https on java involves using keystores, furthermore How to use TLS in Play!Framework WebSockets ("wss://") suggest that even if I could get https working it might be that wss still won't work. So after a few failed attempts I ditched this.

The solution was using stunnel which allowed me to open up a port, encrypt any incoming traffic and forward it to another port. So I am now ssl encrpyting traffic on port 9433 and forwarding it to the backends unecrypted ws Endpoint which made it work.

If you wan't to use it in an actual production environment you should do some research on the scaleability of this method, especially stunnel.

Jakob Abfalter
  • 4,980
  • 17
  • 54
  • 94