MQTT broker with secure (TLS) communication on Ubuntu 18.04 LTS and an ESP32 MQTT-client

Suru Dissanaike
6 min readMay 1, 2019

--

Photo by Kaley Dykstra on Unsplash

In our previous article “Workshop on our Open Source Wireless Environmental Sensor” we fell short when we tried to connect to the test.mosquitto.org using TLS from our ESP32 MQTT client.

Question: Do you remember why we couldn’t connect to the test.mosquitto.org from our ESP32?

Answer: The mbed TLS which is used by ESP32 enforces a 2048-bit key usage, but the online generation of certificates for test.mosquitto.org only supports RSA-1024.

One way forward is to install our MQTT broker and sign all the certificates on our own, let us explore that! 🔎

Installing the MQTT broker

When installing the Mosquitto broker on Ubuntu, you have the option of using either snap or apt package manager. If you use snap it is good to know that the default location of the mosquitto.conf file is here:

/var/snap/mosquitto/common/mosquitto.conf

In my example I am using apt package manager, so I type the following:

sudo apt-get install mosquitto
sudo apt-get install mosquitto-clients

Now I have installed mosquitto version 1.4.15, and I want to start the broker; I want to run it as a demon, so I type the following:

sudo systemctl start mosquitto.service

Open two terminals and type the following in the first terminal:

$ mosquitto_sub -h localhost -t “#” -d
Client mosqsub|14677-ps sending CONNECT
Client mosqsub|14677-ps received CONNACK
Client mosqsub|14677-ps sending SUBSCRIBE (Mid: 1, Topic: #, QoS: 0)
Client mosqsub|14677-ps received SUBACK
Subscribed (mid: 1): 0
Client mosqsub|14677-ps received PUBLISH (d0, q0, r0, m0, ‘test’, … (5 bytes))
hello
Client mosqsub|14677-ps sending PINGREQ

And in the other terminal type:

$ mosquitto_pub -h localhost -t "test" -m "hello" -d
Client mosqpub|14678-ps sending CONNECT
Client mosqpub|14678-ps received CONNACK
Client mosqpub|14678-ps sending PUBLISH (d0, q0, r0, m1, 'test', ... (5 bytes))
Client mosqpub|14678-ps sending DISCONNECT

mosquitto_sub and mosquitto_pub are excellent tools for verification and troubleshooting of your mqtt broker. In the example above the second terminal send the message “hello” to the first terminal.

Ubuntu 18.04 LTS firewall settings

In the previous example, we used localhost as the host, but if you are using the external IP, you need to open up the ports manually (they are closed by default in the firewall). This is what you need to know to get started.

open TCP port in the firewall

Open incoming TCP port 1883 to any source IP address:

sudo ufw allow from any to any port 1883 proto tcp

In this article, we use the TLS port.

sudo ufw allow from any to any port 8883 proto tcp

List All UFW rules

sudo ufw status

Delete UFW rule

sudo ufw status numbered
sudo ufw delete <number>

Creating self-signed certificates (TLS) for mosquitto

The mosquitto manual for creating certificates is really good, you will find it here. We just need to make some small tweaks for it to work with our ESP32.

There is a lot of typing involved and you can easily make a mistake, I created a bash script to simplify the key generation and to move them to the correct directory.

Common Name (CN) is the domain name, host name or IP-address. In the example below, we use the IP “192.168.1.22” because it is in the private IP address range which is perfect for testing purposes.

Maybe you are wondering why I do not use an identical subject for all three certificates?

If you use an identical subject for the CA and server certificate, SSL will intepreate this as a single certificate solution and compare ca.crt and server.crt but because both have different SH1 thumbprint it will fail. I made this mistake and it cost me a lot of time. I finally found this explanation. Check out user “Vicky’s comment”. BTW thanks Vicky!

I am using the following mosquitto.conf; it is located in /etc/mosquitto/

Don’t forget to restart mosquitto after modifying mosquitto.conf.

sudo systemctl stop mosquitto.service
sudo systemctl start mosquitto.service
orsudo systemctl restart mosquitto.service

Testing our keys

Go to the folder that you have your generated certificates; it looks like this:

.
├── ca.crt
├── ca.key
├── ca.srl
├── client.crt
├── client.csr
├── client.key
├── make-keys.sh
├── server.crt
├── server.csr
└── server.key

Tail the log file in a terminal window.

$ sudo tail -f /var/log/mosquitto/mosquitto.log

Now it is time to use mosquitto_sub again.

mosquitto_sub --cafile ca.crt -h 192.168.1.22 -t "#" -p 8883 -d --cert client.crt --key client.key

The terminal window that you tailed the log file will look like this:

$ sudo tail -f /var/log/mosquitto/mosquitto.log 
1556717194: mosquitto version 1.4.15 (build date Wed, 13 Feb 2019 00:27:01 +0000) starting
1556717194: Config loaded from /etc/mosquitto/mosquitto.conf.
1556717194: Opening ipv4 listen socket on port 8883.
1556717194: Opening ipv6 listen socket on port 8883.
1556717195: New connection from 192.168.1.22 on port 8883.
1556717195: New client connected from 192.168.1.22 as mosqsub|6284-sudi-vm (c1, k60, u’192.168.1.22').
1556717417: New connection from 192.168.1.22 on port 8883.

Now it is time to use mosquitto_pub again.

$ mosquitto_pub -h 192.168.1.22 -t "test" -m "hello" -p 8883 -d --cert client.crt --key client.key --cafile ca.crt 
Client mosqpub|8757-sudi sending CONNECT
Client mosqpub|8757-sudi received CONNACK
Client mosqpub|8757-sudi sending PUBLISH (d0, q0, r0, m1, 'test', ... (5 bytes))
Client mosqpub|8757-sudi sending DISCONNECT

Just as before we see the “hello” message in the terminal where we are running mosquitto_sub

$ mosquitto_sub --cafile ca.crt -h 192.168.1.22 -t "#" -p 8883 -d --cert client.crt --key client.key
Client mosqsub|8746-sudi sending CONNECT
Client mosqsub|8746-sudi received CONNACK
Client mosqsub|8746-sudi sending SUBSCRIBE (Mid: 1, Topic: #, QoS: 0)
Client mosqsub|8746-sudi received SUBACK
Subscribed (mid: 1): 0
Client mosqsub|8746-sudi sending PINGREQ
Client mosqsub|8746-sudi received PINGRESP
Client mosqsub|8746-sudi received PUBLISH (d0, q0, r0, m0, 'test', ... (5 bytes))
hello

But this time the communication is encrypted using TLS!!! 👏🏻

C-code example for verifying the keys

If you want to verify that your keys work before you try them on your ESP32 you can use the following code:

In order to run the code you need to install the libmosquitto-dev package:

sudo apt-get install libmosquitto-dev

Now you can build the code:

$ make
gcc -c -o mosquitto-demo.o mosquitto-demo.c
gcc -o mosquitto-demo mosquitto-demo.o -lmosquitto -g -Wall

Copy the keys that you have created so that you have the following file structure:

├── keys
│ ├── ca.crt
│ ├── client.crt
│ └── client.key
├── Makefile
├── mosquitto-demo
├── mosquitto-demo.c
└── mosquitto-demo.o

Now you can run the code

$  ./mosquitto-demo

Connecting your ESP32 to the MQTT broker

In our previous article, we were not able to connect to the test.mosquitto.org broker using TSL from the ESP32 because RSA-1024 is not okay due to security reasons.

With our certificates, it is going to work because we have the correct bit length. Our RSA key pair uses a 2048-bit key.

Let us try it out, clone the following repo,

Copy the files you have created and replace the ca.crt, client.crt and client.key in the fs directory which looks like this:

├── fs│ ├── ca.crt│ ├── client.crt│ ├── client.key│ └── init.js

Now you can run the code… but first, you need to modify the mos.yml file.

Change the:

  • [“wifi.sta.enable”, true] — [“wifi.sta.ssid”, “YOUR-SSID”
  • [“wifi.sta.pass”, “YOUR-PASSKEY”]
  • [“mqtt.server”, “YOUR-BROKER-IP:8883”]
Sparkfun ESP32 Thing board

Now when you run it, it will work, and you see something like this in mosquitto_sub

Client mosqsub|3821-sudi received PUBLISH (d0, q0, r0, m0, 'himinds/', ... (47 bytes))
{"data":{"free_ram":213624,"total_ram":288552}}
Client mosqsub|3821-sudi received PUBLISH (d0, q0, r0, m0, 'himinds/', ... (47 bytes))
{"data":{"free_ram":213492,"total_ram":288552}}
Client mosqsub|3821-sudi received PUBLISH (d0, q0, r0, m0, 'himinds/', ... (47 bytes))
{"data":{"free_ram":211928,"total_ram":288548}}
Client mosqsub|3821-sudi received PUBLISH (d0, q0, r0, m0, 'himinds/', ... (47 bytes))
{"data":{"free_ram":211928,"total_ram":288548}}
Client mosqsub|3821-sudi received PUBLISH (d0, q0, r0, m0, 'himinds/', ... (47 bytes))
{"data":{"free_ram":211928,"total_ram":288548}}
Client mosqsub|3821-sudi received PUBLISH (d0, q0, r0, m0, 'himinds/', ... (47 bytes))
{"data":{"free_ram":216748,"total_ram":288560}}

In the mos tool debug console you will see something similar to this:

[May  1 18:01:55.949] mgos_mqtt.c:510         Publishing to himinds/ @ 1 (47): [{"data":{"free_ram":216968,"total_ram":288580}}]
[May 1 18:01:55.949] Published: yes topic: himinds/ message: {"data":{"free_ram":216968,"total_ram":288580}}
[May 1 18:01:55.949] mg_ssl_if_mbedtls.c:35 0x3ffc8f24 => write
[May 1 18:01:55.949] mg_ssl_if_mbedtls.c:35 0x3ffc8f24 grow out_buf 21 => 82
....[May 1 18:01:58.250] mg_ssl_if_mbedtls.c:35 0x3ffc8f24 <= read record
[May 1 18:01:58.250] mg_ssl_if_mbedtls.c:35 0x3ffc8f24 <= read
[May 1 18:01:58.250] mgos_mqtt.c:135 MQTT event: 203
[May 1 18:01:58.250] Topic: himinds/ message: {"data":{"free_ram":216968,"total_ram":288580}}

Summary

In this article, we installed the Eclipse Mosquitto MQTT broker on Ubuntu 18.04. We generated our certificates (self-signed) and configured Mosquitto to use them. We successfully connected to our MQTT broker using TLS from an MQTT-client running on our ESP32.

If you prefer to use Docker; this article could be of interest.

Thank you for reading! Take care and hope to see you soon. 🙏🏽

--

--

Suru Dissanaike
Suru Dissanaike

Written by Suru Dissanaike

IoT nerd with a passion for Test Automation, Embedded Linux and DevOps. https://www.linkedin.com/in/dissanaike/

Responses (2)