Hi folks,
I saw tonight an interesting proposal about an extra level of security for Node-RED via internet, by whitelisting a list of ip addresses.
Although it is a very interesting article, I don't think I will be able to use it because my ip addresses (that need access NR) are not fixed. Filtering on MAC addresses would solve my case, but you don't know the MAC address of the device that sends the request (if I am not mistaken).
So there need to be something else on my devices, that allows them to access my Node-RED web application. I am not a security expert, but I assume a client certificate is safe enough to do the job.
1. Setup SSL
Note that in order to be able to use a client certificate, you first need to setup SSL in Node-RED (i.e. https).
SSL works like this:
- Your device (e.g. browser on your smartphone) accesses your Node-RED system.
- Based on your server certificate, an SSL handshake will be executed between both devices.
- Your device browser receives the server certificate and will encrypt all data with it, before sending it to the Node-RED server.
- Your Node-RED server will decrypt the data using the corresponding private key.
- Which means all your data is transferred in a secure way between both devices.
On my Raspberry I had to execute following commands to create a private key, csr (certificate signing request) and corresponding (self signed) certificate:
cd /home/pi/.node-red/
openssl genrsa -out server-key.pem 2048
openssl req -new -sha256 -key server-key.pem -out server-csr.pem
openssl x509 -req -in server-csr.pem -signkey server-key.pem -out server-cert.pem
In the third command (to generate the csr file) you will get some questions which you need to answer. It is very important that for the CN (common name) you enter the hostname that you use in the url to access your Node-RED web application. Because when the CN of the server certificate does not match with the hostname in the url, your browser will reject the server certificate.
And you need to enable SSL in Node-RED, via the settings.js file by providing the key pair (i.e. private key and corresponding certificate):
https: {
// Server key pair
key: require("fs").readFileSync('/home/pi/.node-red/server-key.pem'),
cert: require("fs").readFileSync('/home/pi/.node-red/server-cert.pem'),
// Enable SSL (i.e. https)
requireHttps: true,
},
After restarting Node-RED, you should be able to access your flow editor via https.
2. Setup client authentication
As an extra step we will setup client authentication, which works like this:
- During the SSL handshake, the device browser client will need to send a client certificate to the Node-RED server.
- The SSL handshake will only be successfull if the client certificate is recognized by the Node-RED server.
Which means that the client can only access the Node-RED system when it has the correct client certificate.
To implement this, create a client certificate in a similar way. At the end we also do an extra step, to convert the pem file to a crt file (which can be loaded into a browser):
cd /home/pi/.node-red/
openssl genrsa -out client-key.pem 2048
openssl req -new -sha256 -key client-key.pem -out client-csr.pem
openssl x509 -req -in client-csr.pem -signkey client-key.pem -out client-cert.pem
openssl x509 -in client-cert.pem -outform pem -outform der -out client-cert.cer
In the third command (to generate the csr file) you will get some questions which you need to answer. It is very important that for the CN (common name) you enter the hostname that you use in the url to access your Node-RED web application. Because your browser will only pass (automatically) this client certificate to the Node-RED server, when you navigate to the hostname (that matches the CN of the client certificate).
And you need to let Node-RED know that it is only allowed to give access to the clients that have this client certificate
https: {
// See the SSL settings from the first section above...
// Only accept certificates from these certificate authorities
ca: require("fs").readFileSync('/home/pi/.node-red/client-cert.pem'),
// Requesting the client to provide a certificate, to authenticate.
requestCert: true,
// Server should not accept any unauthenticated traffic
rejectUnauthorized: true
},
After restarting Node-RED you should not able anymore to access your web application, because your browser does NOT send yet the client certificate to the Node-RED server:
So you need to import the client certificate into your browser. For Chrome on my Windows portable I did it like this:
-
Go to the Settings menu
-
Go to Security:
-
Go to Manage Certificates:
-
Import the client-cert.cer file that you have created in the last command
-
When you now navigate to the hostname of your Node-RED server, your browser should pass the client certificate in the request which should allow you to access your Node-RED web application again.
Of course you need to import the client certificate in the browsers on ALL your devices!
P.S. This was a very quick experiment, so it might not be complete. As always all constructive feedback is very welcome!
Bart