Report this

What is the reason for this report?

How to connect to a backend secure socket server from a react front end running https?

Posted on August 16, 2020

When upgrading my front end react app to https using nginx, the backend socket server stopped working. The original call to the back end was done via W3CWebSocket(ws://x.x.x.x:xxxx) in react.

I added an additional location section in nginx:

          ...
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'upgrade';
          ...

However, upgrading the front end to https and changing to wss on the call to the server, I keep getting error messages about the certificates I loaded to the backend.

WebSocket connection to 'wss://159.203.191.30:5000/sga/' failed: Error in connection establishment: net::ERR_CERT_COMMON_NAME_INVALID

thread 'main' panicked at 'accept error: Ssl(Error { code: ErrorCode(1), cause: Some(Ssl(ErrorStack([Error { code: 336151574, library: "SSL routines", function: "ssl3_read_bytes", reason: "sslv3 alert certificate unknown", file: "../ssl/record/rec_layer_s3.c", line: 1528, data: "SSL alert number 46" }]))) }, X509VerifyResult { code: 0, error: "ok" })', tokio-native-tls/examples/echo.rs:34:34

The secure socket server is a rust tokio app and runs under pm2. I tried converting the certificates I used for the front end into p12 format, but cannot get past the connection handshake.

Do I need another set of certificates? I tried that, but letsencrypt asked me if I just wanted to upgrade the ones I already use in nginx.

How to I supply the backend with the correct certificates?

Any help will be appreciated!



This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

These answers are provided by our Community. If you find them useful, show some love by clicking the heart. If you run into issues leave a comment, or add your own answer to help others.

Hello,

Based on your error message, it looks like the client (browser) doesn’t trust the certificate used by the WebSocket server. You can’t use an IP address with an SSL certificate; SSL certificates are bound to domain names. The Common Name or Subject Alternative Name fields of the certificate should match the domain name you are using. This is why you’re seeing the net::ERR_CERT_COMMON_NAME_INVALID error.

You should have a domain name for your server and issue the certificate for this domain, then use the domain to access the server, instead of the IP address.

Here are the steps you can follow:

  1. Set up a domain name for your server. It doesn’t have to be a new one, you can use a subdomain like wss.yourdomain.com. You can usually configure subdomains with your domain registrar or DNS provider.

  2. Issue a certificate for this domain. If you’re using Let’s Encrypt, you’ll want to use this domain when you run certbot or whatever ACME client you’re using.

  3. Install and configure this certificate in your WebSocket server. You’ll want to use the .pem or .crt and .key files, not the .p12 one.

  4. Update your WebSocket URL in your React app to use wss://wss.yourdomain.com.

  5. Update your Nginx configuration to proxy WebSocket connections to this new domain. If your WebSocket server is running on the same machine as Nginx, you can proxy to localhost:5000 or wherever the WebSocket server is running.

Here’s an example of how the Nginx configuration might look:

server {
    listen 443 ssl;
    server_name wss.yourdomain.com;

    ssl_certificate /etc/letsencrypt/live/wss.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/wss.yourdomain.com/privkey.pem;

    location / {
        proxy_pass http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $host;
    }
}

For the SSL certificate itself, you can follow the steps here:

https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-ubuntu-20-04

Best,

Bobby

Heya,

To establish a secure WebSocket connection (wss://) from your React front end to your backend server, you need to ensure that the SSL/TLS setup is correctly configured on both ends. The error ERR_CERT_COMMON_NAME_INVALID indicates a problem with the SSL certificate on the server that your WebSocket client (front end) is trying to connect to.

Let’s address how to resolve this issue:

1. Correct SSL Certificate for Backend

  • The SSL certificate used by your backend WebSocket server should be valid for the domain you are connecting to. This means that the certificate’s common name (CN) or a subject alternative name (SAN) entry should match the domain name of your WebSocket server.

  • If your WebSocket server is accessed via an IP address (as in your example wss://159.203.191.30:5000/sga/), most browsers will not accept an SSL certificate as valid for an IP address unless it’s specifically included in the certificate as a SAN. It’s generally better to use a domain name with a valid SSL certificate.

  • You can use Let’s Encrypt to issue a free SSL certificate for your domain. Make sure your DNS records are properly set up to point to your server’s IP address.

2. Nginx Configuration for WebSocket Proxy

  • Ensure your Nginx configuration is correctly set up to proxy WebSocket connections. The proxy_set_header directives you’ve added are typically correct. Here’s an example for clarity:
location /ws {
    proxy_pass http://backend-server:port; # Your WebSocket server address
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
}
  • Adjust the proxy_pass directive to point to your WebSocket server (use the domain name if available).

3. Frontend WebSocket Connection

  • In your React application, when you create a WebSocket connection, use the wss:// protocol and ensure you are connecting to the correct domain. Example:
const socket = new WebSocket('wss://yourdomain.com/ws');

4. Loading Certificates in the Backend

  • For your Rust Tokio app, ensure that you load the correct SSL certificate and private key. If you’re using a .p12 (PKCS #12) file, ensure that it includes both the certificate and the private key.

  • The certificate should be the same one used in Nginx if the domain is the same, or a different valid certificate if the domain is different.

5. Test the Setup

  • After configuring the SSL certificates and updating Nginx and your Rust app, restart the services and test the WebSocket connection.

  • You can use online SSL verification tools to ensure your certificate is correctly installed and valid.

6. Check Firewall and Port Settings

  • Ensure that no firewall is blocking the WebSocket ports and that Nginx is correctly routing traffic to your WebSocket server.

By properly setting up the SSL certificates for both your frontend (Nginx) and backend (Rust WebSocket server) and ensuring that the Nginx reverse proxy is correctly configured for WebSocket traffic, you should be able to establish a secure WebSocket connection from your React app.

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.