Search code examples
sslwebsocketnginx-reverse-proxy

nginx reverse proxy working with ws but not with wss


Lately i wrote an application that uses standard WebSockets to communicate.

Now i wanted to connect to the frontend with using SecureWebSockets (aka wss://...) and SSL. Therfore i set up a nginx reverse proxy on a linode server.

When i use just the ip as server_name and a standard WebSocket connection (aka ws://...) in the frontend everything works fine. As soon as i change the config to use SSL it breaks and i have no idea why.

The config for the standard WebSockets looks something like this:

server {
    listen 8080;
    server_name (ip_address);

    access_log /var/log/nginx/backend.log;
    error_log  /var/log/nginx/backend-error.log error;

    location / {
        proxy_pass http://127.0.0.1:8111;

        #WebSocket magic
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_redirect off;
    }
}

The config for the SecureWebSockets looks something like this:

server {
    listen 80;
    listen [::]:80 ipv6only=on;
    server_name (custom_domain.com);
    return 301 https://$host$request_uri;
}
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name (custom_domain.com);

    access_log /var/log/nginx/backend.log;
    error_log  /var/log/nginx/backend-error.log error;

    ssl_certificate /path/to/cert; # managed by Certbot
    ssl_certificate_key /path/to/key; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    location / {

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass http://127.0.0.1:8111;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        proxy_ssl_session_reuse off;
        proxy_set_header Host $http_host;
        proxy_redirect off;
    }
}

All relevant ports are set to allow in ufw and i already tested if the cert is correctly working. The odd thing is that there are no errors in the nginx logs and nothing in the access logs.

I have no idea what i could possibly try to get it working. This is kind of my last resort to get this working.

If anyone has an idea what i could try i would be really glad.

Thanks in advance :)

EDIT: The problem is, that i don't get any real errors. Neither from frontend nor the backend. I'm trying to provide the best "errors" i can.

I'm trying to access the websocket via react expo:

`client = new WebSocket("wss://custom_domain.com")`

(The backend is written in java and is just a basic WebSocket, that accepts the connection.)

I tried accessing from the frontend hosted locally and from a netlify instance.

When i send from localhost the WS Analysis looks something like this:

(there is literally nothing else (maybe the callstack, but i dont think thats neccessary)

Piture of Chrome WS Analysis

When i send via netlify nothing happens, no "messages" are sent. The connection just fails.

As mentioned above nginx doesn't throw any erros in the log, so i think the request doesn't even reach the server?

(I'm new to WebSockets aswell as StackOverflow, so sorry if my question isn't that percise)

openssl response (openssl s_client -connect yourhost:443) :


    subject=CN=custom_domain.com
    issuer=C=US, O=Let's Encrypt, CN=E6
    ---
    No client certificate CA names sent
    Peer signing digest: SHA256
    Peer signature type: ECDSA
    Server Temp Key: X25519, 253 bits
    ---
    SSL handshake has read 2400 bytes and written 409 bytes
    Verification error: unable to get local issuer certificate
    ---
    New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
    Protocol: TLSv1.3
    Server public key is 256 bit
    This TLS version forbids renegotiation.
    Compression: NONE
    Expansion: NONE
    No ALPN negotiated
    Early data was not sent
    Verify return code: 20 (unable to get local issuer certificate)
    ---
    ---
    Post-Handshake New Session Ticket arrived:
    SSL-Session:
        Protocol  : TLSv1.3
        Cipher    : TLS_AES_256_GCM_SHA384
        Session-ID: 1F6DBE1DE581C1FCC12938F19C71AC54E5AB76F31C3DCBF4C692276C82C2BFBC
        Session-ID-ctx:
        Resumption PSK: 
        PSK identity: None
        PSK identity hint: None
        SRP username: None
        TLS session ticket lifetime hint: 86400 (seconds)
        TLS session ticket:
        0000 - a0 39 f1 9b e5 0a 90 3d-80 24 5b 80 28 f1 3f e6   .9.....=.$[.(.?.
        0010 - 2b 1c c9 39 ef 1e d4 d9-c9 9f 91 ea 4f 5e 0e ce   +..9........O^..
    
        Start Time: 1730061634
        Timeout   : 7200 (sec)
        Verify return code: 20 (unable to get local issuer certificate)
        Extended master secret: no
        Max Early Data: 0
    ---
    read R BLOCK
    ---
    Post-Handshake New Session Ticket arrived:
    SSL-Session:
        Protocol  : TLSv1.3
        Cipher    : TLS_AES_256_GCM_SHA384
        Session-ID: 32CD15B2E389CE3526C3A834F8D1A1498160CBDC09987D28E5931E4F4F3BFD20
        Session-ID-ctx:
        Resumption PSK: 
        PSK identity: None
        PSK identity hint: None
        SRP username: None
        TLS session ticket lifetime hint: 86400 (seconds)
        TLS session ticket:
        0000 - 69 37 6d 62 65 3e 73 b1-87 1a 61 9a bb be b0 8c   i7mbe>s...a.....
        0010 - d3 6c df c6 0c f5 e3 d2-4b f9 30 02 84 f5 9b 8e   .l......K.0.....
    
        Start Time: 1730061634
        Timeout   : 7200 (sec)
        Verify return code: 20 (unable to get local issuer certificate)
        Extended master secret: no
        Max Early Data: 0
    ---
    read R BLOCK
    closed


Solution

  • Solved with the help of @SteffenUlrich. The problem was an internal error in the backkend.