I'm road testing the Harting MICA Complete IIoT Starter Kit. It comes with a MQTT Broker Container. It's the heart of most examples available for the MICA. It's installed out of the box on my MICA. But: it is an open service. Everyone that can IP the network can send and get messages (and trigger hardware). I'm not angry. I'm disappointed . It's 2019.
I have two choices - securing the one that's provided by Harting or creating a certificate-protected one from scratch. I chose option two. In this post I show how I created a more secure MQTT broker, starting from an empty Linux container.
I'm using the Linux Debian Stretch Container here - a reasonable lightweight yet complete MICA option to deploy Linux solutions. |
Update December 6 2020: version 2.5 of the MQTT container can be configured for secure access. The blog is still useful if you want to run your own, but the MICA team has now provided a better container that allows you to set up server certificates from the management console. |
Setting up the MQTT Broker
If you don't know how to create a new Linux container on the MICA, check this post.
It explains how to create one, and how to connect to it via SSH (PuTTy).
Step 1 is to deploy a fresh Debian Stretch Container on the MICA.
Name: MQTTRoadtest
At start time, the size of this container is:
At the end of this post, when we've added SSL and MQTT support, let's check what the total deploy size of the container is.
After starting the container, I used PuTTY to log on and immediately changed the password by executing the passwd command.
In a later exercise, I may create a dedicated non-root user to run the service.
I'll need to study some more to see what it takes to get the service running under a dedicated account.
Then I followed a mix of these three web pages to get everything set up. All the steps are documented in this post.
https://obrienlabs.net/how-to-setup-your-own-mqtt-broker/
https://dzone.com/articles/mqtt-security-securing-a-mosquitto-server
Configuring the MQTT Publish and Subscribe Nodes in Node-Red
You will find that some parts of this post are literal instructions and commands from the pages above. I hope that by referencing them here I give them the right credit.
There's no full overlap with them. To get only secure connections working and reject insecure ones (except from localhost), you need a combination of steps from all three.
Step 2, let's install our MQTT server.
(in my network I have to disable the proxy to make apt work)
cd /etc/apt/apt.conf.d mv 99proxy 99proxy.bak
Install Mosquitto:
apt update apt-get install mosquitto mosquitto-clients
test the installation without security:
service mosquitto start
At this moment, we have a working MQTT service with similar security settings as the standard one.
Step 3, you can test if the MQTT server has basic functionality.
Here, I'm doing that with MQTT Lens:
If you change the server name to MQTTRoadtest in the CISSGateway, Node Red and GPIO examples, things will also work with the new service because our server is unsecured.
From now on, we'll add security. The examples will not work with the service anymore.
You'll be able to talk to it from your own code though, and from Node Red. But things will be closed for anyone who does not have a correct certificate.
Securing the MQTT Broker
Time to stop the service again.:
service mosquitto stop
Step 1, we create all the keys and certificates
Get openssl. We'll need it to generate the certificates and keys.
apt-get install openssl
Make a directory for certificates, etc ...
mkdir ~/mosquittossl cd ~/mosquittossl
Create a 2048-bit key called mosq-ca.key
openssl genrsa -out mosq-ca.key 2048
Create an X509 certificate that uses the private key generated in the previous step
openssl req -new -x509 -days 365 -key mosq-ca.key -out mosq-ca.crt
Create the MQTT Server Certificate.
openssl genrsa -out mosq-serv.key 2048
Next, create a CSR (Certificate Signing Request)
openssl req -new -key mosq-serv.key -out mosq-serv.csr
Now, make the certificate to use in our MQTT Mosquitto Server.
openssl x509 -req -in mosq-serv.csr -CA mosq-ca.crt -CAkey mosq-ca.key -CAcreateserial -out mosq-serv.crt -days 365 -sha256
Verify:
openssl x509 -in mosq-serv.crt -out readme.txt cat readme.txt rm readme.txt
Step 2, we configure the Mosquitto Server to Secure MQTT with the certificates.
Edit the Config file.
nano /etc/mosquitto/mosquitto.conf
Add these entries:
listener 8883 cafile /root/mosquittossl/mosq-ca.crt certfile /root/mosquittossl/mosq-serv.crt keyfile /root/mosquittossl/mosq-serv.key
I think that the proper way to do this is to create an own config file in the /etc/mosquitto/conf.d directory. Comment below if you know it.
Next restart the server.
service mosquitto restart
The default unsecured listener in port 1883 is still running now. But we've added the secure service on 8883.
We'll refine later.
Step 3 is to download the certificates. In our case, you only need mosq-ca.crt.
You need to find a way to get the certificates that you need for client setup.
I installed the sFTP server for that.
apt install openssh-server service ssh restart
you could also use the sdcard (check MICA's NAS Container documentation) or other file transfer options to move the certificate you need.
Step 4 is to test it from your pc, with the certificate.
The MQTT testbed I use to try out communication with certificates can be downloaded here: MQTT.fx .
Configure it as shown below, then connect.
Subscribe to topic /TESTSecure. Then Publish to that same topic /TESTSecure with message Secure MQTT.
You should see the message arriving at the bottom of the window. It has gone via the MICA over secure communication.
Step 5 is to revoke the unsecured 1883 listener.
Disable the 1883 port for anyone except the container itself.
edit the msquitto.conf file.
Add
listener 1883 localhost
before the 8883 listener.
Restart the service.
Step 6 is to test with the NodeRed container with a self-made flow.
Create a new NodeRed process, with a MQTT and a Debug block:
Edit the mqtt node. Replicate the settings as shown below:
Deploy, and then it's time to test.
As a preparation, open the debug window in the Node Red editor:
You can use the Selected Node filter to only see debug messages for this flow. Do that in case you have the CISSGateway running - we don't want to see those messages now).
Use the same MQTT.fx connection we used before, but publish some message to the topic /SecureTopic (the same one used in the Node Red process).
Go back to the Node Red editor. You should see the message in the debug log:
The space occupied by the container, after installation and first start of the service:
Things for myself to consider later on:
- create a non-root user for mqtt
- what about certificate expiry?
- investigate certificate validation
- server keys and certificates should be stored in /etc/mosquitto/certs , only readable by mosquitto user
- enable the ws listener
Thanks for reading. If you see flaws and mistakes, please comment.
Top Comments