UsingTLS encrypted websocket

Hello,
I just went through the Getting Started page of openems and in the “Configure the Controller Api Backend Component” section it says “For a production setup you would want to use a TLS encrypted websocket with a wss:// uri.” I was just curious what you need to configure to switch websocket protocol from “ws://” to “wss://”.

Thank you,
Quynh Anh

1 Like

Thats a very very good question indeed !!

Pin :slight_smile:

Secure Backend communication seems to be a never ending story. I´m struggeling with Backend-UI communication for days now.

But I´ve got SSL for edge->Backend working. This is my Apache2-configuration over port 8284:


<VirtualHost *:8284>
    ServerName XXX.org
    ServerAdmin Thomas@klinki.com
    DocumentRoot "/usr/share/openems-backend/www"

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/XXX.org/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/XXX.org/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

    ProxyPass / ws://127.0.0.1:8081/
    ProxyPassReverse / ws://127.0.0.1:8081/

    <Directory "/usr/share/openems-backend/www">
        RewriteBase /
        RewriteRule ^index\.html$ - [L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule . /index.html [L]
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
    LogLevel proxy:debug
    ErrorLog "/var/log/apache2/openems-backend/BackError.log"
    CustomLog "/var/log/apache2/openems-backend/BackAccess.log" common
</VirtualHost>

The setting for edge´s backend-controller is

wss://XXX.org:8284

over the internet. Which works fine.
I´ve realized this with a let´s encrypt certificate.

XXX is the domain-name :wink:

I had to use this port because the standard port for https (443) is already in use.
The configuration on the backend is taken from the getting started guide - which is port 8081.

As I´ve mentioned: edge->backend is working but I could not establish a secure backend-ui connection over SSL. If the SSL stuff is commented out: everything works fine. With SSL it does not. But I post the faulty config also:

<VirtualHost *:8285>
    ServerName XXX.org
    ServerAdmin Thomas@klinki.com
    DocumentRoot "/usr/share/openems-backend/www"

    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/XXX.org/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/XXX.org/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf

    # WebSocket Proxy - Apply only to WebSocket requests
    <Location /openems-backend-ui>
        ProxyPass ws://127.0.0.1:8082/openems-backend-ui
        ProxyPassReverse ws://127.0.0.1:8082/openems-backend-ui
        Header set Connection upgrade
        Header set Upgrade websocket
    </Location>

    # HTTP Proxy - Apply to all other requests
    ProxyPass / http://127.0.0.1:8082/
    ProxyPassReverse / http://127.0.0.1:8082/

    <Directory "/usr/share/openems-backend/www">
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
</VirtualHost>

Maybe you can give me advice after you´ve taken the first steps connecting your edge device.

regards,
klinki

Hi @ayuyamo,

TLS encryption of the connection has to be handled outside of OpenEMS Backend using a HTTP Proxy.

I usually rely on NGINX for this job.

To receive a TLS certificate, you can use Let’s Encrypt.

NGINX and Let’s Encrypt work nicely together. You’ll end up with a NGINX configuration similar to this:

server {
    server_name example.com;
    listen 443 ssl default;

    # ssl
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    # OpenEMS UI
    root /var/www/openems-ui/;
    location / {
        index index.html;
        try_files $uri$args $uri$args/ /index.html;

        access_log /var/log/nginx/openems-ui.access.log;
        error_log /var/log/nginx/openems-ui.error.log;
    }

    # Proxy for OpenEMS Edge -> OpenEMS Backend
    location /edge-to-backend {
        proxy_pass http://172.0.0.1:8081;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        access_log /var/log/nginx/edge-to-backend.access.log;
        error_log /var/log/nginx/edge-to-backend.error.log;
    }

    # Proxy for OpenEMS UI -> OpenEMS Backend
    location /ui-to-backend {
        proxy_pass http://127.0.0.1:8082; #srv2
        proxy_ssl_server_name on;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        access_log /var/log/nginx/ui-to-backend.access.log;
        error_log /var/log/nginx/ui-to-backend.error.log;
    }
}

Regards,
Stefan

Hi Stefan,

I´ve tried your example - but without success. Maybe a stupid question: how can the backend jar-file know where to find the web-documents?

What I did:

  • ng build -c “openems,openems-backend-prod,prod” in VS Code to generate web documents for backend-UI. I’ve put them in “/usr/share/openems-backend/www”
  • The first approaches are with the apache-configuration I´ve found in this thread.
  • I’ve installed nginx with the configuration similar to the one you’ve posted:
    server_name example.org;
    listen 443 ssl;

    # SSL Configuration
    ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # Proxy for OpenEMS UI -> OpenEMS Backend
    location /openems-backend-ui {
        proxy_pass http://127.0.0.1:8082;
        proxy_ssl_server_name on;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        access_log /var/log/nginx/ui-to-backend.access.log;
        error_log /var/log/nginx/ui-to-backend.error.log;
    }

Now I am wondering how the WebDocuments can be found. If I get it right nginx directly passes requests from a browser (https) to port 8082 (http) , right?

regards,
klinki

@klinki: Serving the HTML/CSS/JavaScript files was not part of my documentation. Add added it above:

OpenEMS UI will be served on port 443 (HTTPS). Once opened in the browser, UI should open a connection to https://example.com/openems-backend-ui (this has to be configured in the UI environment file).

PS: It would be great if the information in this post would result in an extended documentation, e.g. for Deploy OpenEMS Backend :: Open Energy Management System

Regards,
Stefan

1 Like

That´s it!

Thank you, Stefan.

But isn’t that some kind of double SSL offloading? In my opinion, it would be sufficient to secure only the first connection to the UI. Anyway, I’ll keep experimenting and maybe I can get the Apache configuration working as well.

regards,
klinki

Great. :+1:

No, both connections need to be secured. One is to provide the HTML - there it’s good practice nowadays to have it TLS encrypted (https://). The other one is for the Websocket connection (wss://), which is critical, because it’s used for sensitive data. One could manually create a connection to wss:// even without the UI, see B2bWebsocketTest for an example.

Regards,
Stefan

right! didn`t think about that!

I’ve translated the nginx-configuration to an apache2-config


<VirtualHost *:8285>
    ServerAdmin webmaster@localhost

    ServerName example.org
    DocumentRoot /usr/share/openems-backend/www

    ErrorDocument 404 /index.html

    # Proxy settings
    ProxyPass /openems-backend-ui ws://127.0.0.1:8082/
    ProxyPassReverse /openems-backend-ui ws://127.0.0.1:8082/

    # SSL Configuration
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.org/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.org/privkey.pem
    Include /etc/letsencrypt/options-ssl-apache.conf
    SSLOpenSSLConfCmd DHParameters /etc/letsencrypt/ssl-dhparams.pem

    # Logging
    ErrorLog ${APACHE_LOG_DIR}/openems-backend.error.log
    CustomLog ${APACHE_LOG_DIR}/openems-backend.access.log combined

    <Directory /usr/share/openems-backend/www>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>

</VirtualHost>

Port 8285 and the webroot-directory are special - the rest can be used for other environments.

I agree. Shall I do this? As a pull request?

Regards,
klinki

1 Like