In this previous post I used Certbot & Letsencrypt to secure a node-RED server, and wanted to use the same Letsencrypt certificates to secure MQTT communication with a remote server.
I also wanted to ensure that all local network devices could continue to communicate with the server without encryption.
To be clear, the mosquitto 'Broker' is to be installed & running on my Raspberry Pi, and the remote 'Client' is another node-RED instance running in a Oracle VM.
Secure MQTT normally uses port 8883, so using port-forwarding, open up port 8883 on your Raspberry Pi (broker). It is not necessary to open port 8883 on the client instance.
The Broker
Install mosquitto on the broker;
sudo apt install -y mosquitto mosquitto-clients
We must then tell mosquitto to listen to port 8883 and use TLS to handshake with the client. This is done by creating a mosquitto configuration file;
sudo nano /etc/mosquitto/conf.d/TLSconfig.conf
and paste into it;
# Local MQTT
listener 1883
# Secure MQTT
listener 8883
## This is standard and should always be this
cafile /etc/ssl/certs/DST_Root_CA_X3.pem
## These are from your installation of LE
certfile /home/pi/.node-red/certs/fullchain.pem
keyfile /home/pi/.node-red/certs/privkey.pem
## Forces use of modern version of TLS to avoid security issues
tls_version tlsv1.2
## Force all clients in this listener to provide a valid certificate, change the node config to allow this from NR
#require_certificate true
## Stop all unauthorised connections
#allow_anonymous false
## Use password file
#password_file /etc/mosquitto/passwordfile
Save the file, then restart mosquitto - sudo systemctl restart mosquitto
Note the paths to the certificates. These can be changed if your certificates are at a different location, but use the full path to them.
The Client
Because the Mosquitto configuration (above) is not enforcing that clients must present a valid certificate, you will be able to connect to the broker without any certification whatsover, but by changing the Mosquitto broker configuration to;
## Force all clients in this listener to provide a valid certificate, change the node config to allow this from NR
require_certificate true
..and restarting Mosquitto, that rule will now be enforced, and any MQTT client must present a valid certificate before the broker will allow it to connect.
To prepare a node-RED MQTT node to use a SSL/TLS connection, the client must also have valid certificates of it's own, and add them to the MQTT node like this;
Then add a new tls-config;
That is all the configuration that you need to do in the MQTT node, apart from setting the topic, QoS & Retain options. It should now connect to your broker.
The default mosquitto MQTT listener is port 1883, which allows local network connection to be made without certification, yet because you haven't opened up port 1883 (port forwarding) in the brokers router, all external messages on port 1883 will not get through the firewall, only TLS encrypted 8883 traffic.
Enforce Security
By now, you should have a working TLS encrypted connection between Client & Broker, but to ensure that only your own authorised Clients are able to subscribe to your Broker, we first of all create a username/password pair, to authorise the client.
So back to the Broker - cd /etc/mosquitto
and create a username/password pair by sudo mosquitto_passwd -c passwordfile username
where 'username' is a name of your choosing. The command will ask you to also enter, and confirm, a password of your choice.
To ensure that it has been successfully created - cat passwordfile
to view the username and hashed string password.
Now, we update the Mosquitto config file that we created earlier - sudo nano /etc/mosquitto/conf.d/TLSconfig.conf
, and enforce the rules by un-commenting;
-
require_certificate true
- to only accept clients that use TLS -
allow_anonymous false
- to disallow clients who do not have the username/password -
password_file /etc/mosquitto/passwordfile
- provide a link to the password file
Restart Mosquitto to read in the new settings - sudo systemctl restart mosquitto
and your Broker should now only allow subscribers who are TLS enabled and present the correct username/password.
To add those details to a client, simply add your username & password (the plain text password NOT the hashed string password) to the 'Security' tab in the node-RED MQTT node.