How to setup a secured MQTT broker

Shyaman Jayasundara
5 min readJul 26, 2018

--

What is MQTT?

MQTT(MQ Telemetry Transport) is a machine-to-machine (M2M)/IOT connectivity protocol.”

MQTT is a extremely light weight publisher/subscriber messaging protocol. Constrained Application Protocol (CoAP) and Advanced Message Queuing Protocol (AMQP) are two of the MQTT replaceable transport protocols.

Figure 1: How it works?

MQTT broker is the intermediate handler of all the messages. It can handle up to thousands of clients concurrently. It is responsible for receiving all messages, filtering those messages, determining who is subscribed to each message, and sending the message to those subscribed clients.

For a MQTT broker you have two options. Either you can use an online broker or setup a local MQTT broker. In here we are going to setup an own MQTT broker. It may be on a Raspberry pi ,on a virtual machine on cloud (AWS, DO etc.) or on your own machine (not preferred).

Mosquitto is a popular open source message broker that has great community support. As it is easy to install and configure, we are going to use it here. From this comparison you can find out a message broker that fits to your requirements.

Requirements:

  • A raspberry pi or virtual machine on cloud
  • A domain name pointed at your server

Step 1 — Installing Mosquitto broker

First install software packages for Mosquitto.

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

After installation, Mosquitto service will start automatically.

Step 2 — Configuring MQTT usernames and passwords

In Mosquitto software package, there is a utility called mosquitto_passwd to generate specific password file.

sudo mosquitto_passwd -c /etc/mosquitto/passwd your-username

This will prompts to enter a password. This specific username and password will be stored at /etc/mosquitto/passwd

After that we’ll have to create a new configuration file for Mosquitto.

sudo nano /etc/mosquitto/conf.d/default.conf

This will open up an empty file using nano command-line editor. Add following lines and save the file.

allow_anonymous false
password_file /etc/mosquitto/passwd

Making allow_anonymous to false will permit only authenticated users to connect to the broker. password_file directs where to find the password file.

Now to apply changes, we have to restart the mosquitto service

sudo systemctl restart mosquitto

We can test this setup by subscribing to the ‘test’ topic and publishing to it.

mosquitto_sub -h localhost -t test -u “your-username” -P “your-password

Now publish “hello world” to the ‘test’ topic on another terminal window.

mosquitto_pub -h localhost -t test -m “hello world” -u “your-username” -P “your-password

If you can see “hello world” on the subscribed terminal window then you have successfully configured username password authentication for Mosquitto. Due to unencrypted information exchange still the connection is not secure.

Step 3 — Securing MQTT with SSL

To secure MQTT connection with SSL, we need SSL certificates. Let’s Encrypt is a certificate authority which offers free SSL certificates. In order to have SSL certificates from this service you should have a domain name pointed at your MQTT server.

Installing Certbot

Certbot is the official Let’s Encrypt client. First, we have to add Certbot repository to download latest version of it.

sudo add-apt-repository ppa:certbot/certbot

Then we should update the package list. After that we can install Certbot.

sudo apt-get update
sudo apt-get install certbot

Fetching SSL certificates through Certbot

Cerbot uses port 80 to speak with the Let’s encrypt API. Therefore we should open the port 80 in firewall.

sudo ufw allow 80

Then run Cerbot with the following command. Here you have to replace mqtt.example.com with your domain name.

sudo certbot certonly --standalone --preferred-challenges http -d mqtt.example.com

This will ask for your email address. Finally, the certificates will be stored at /etc/letsencrypt/live/mqtt.example.com directory.

Configuring Mosquitto SSL

Open previously created Mosquitto configuration file to add SSL configurations.

sudo nano /etc/mosquitto/conf.d/default.conf

Add following lines by replacing mqtt.example.com with your domain name.

listener 1883 localhost

listener 8883
certfile /etc/letsencrypt/live/
mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/
mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/
mqtt.example.com/privkey.pem

listener 8083
protocol websockets
certfile /etc/letsencrypt/live/
mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/
mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/
mqtt.example.com/privkey.pem
  • Standard unencrypted port for MQTT is 1883. First, we are making localhost as the listener for that port. So this port is not externally accessible.
  • Port 8883 is the standard MQTT port over SSL also called as MQTTS. Here we are giving paths to the certfile, cafile and keyfile of the fetched Let’s encrypt files.
  • Finally, we have make port 8083 for MQTT over websockets.

Now we should open 8883and 8083 ports from firewall.

sudo ufw allow 8883
sudo ufw allow 8083

To apply configurations, Mosquitto service should be restart again.

sudo systemctl restart mosquitto

Configure to restart Mosquitto service on certificate renewal

Let’s encrypt certificates are valid only for 90 days. Certbot client will automatically renew these certificates before they expire. But we have to configure Certbot to restart Mosquitto service after the renewal of the certificates.

Open the Certbot renewal configuration file using nano command-line editor by replacing mqtt.example.com in the file name with your domain name.

sudo nano /etc/letsencrypt/renewal/mqtt.example.com.conf

Add the following at the end of the configuration file and save it.

renew_hook = systemctl restart mosquitto

You can run Certbot dry run and make sure there are no errors.

sudo certbot renew --dry-run

Step 4 — Testing secured Mosquitto MQTT broker over SSL

Testing secure SSL connection on port 8883

Finally, we can test our broker as we did before. Subscribe to ‘test’ topic by giving path to the root certificates which were installed by the operating system. Here you have to give username and password we created in step 2 and replace mqtt.example.com with your domain name.

mosquitto_sub -h mqtt.example.com -t test -p 8883 --capath /etc/ssl/certs/ -u "your-username" -P "your-password"

Now publish “hello word” from another terminal window.

mosquitto_pub -h mqtt.example.com -t test -m "hello world" -p 8883 --capath /etc/ssl/certs/ -u "your-username" -P "your-password"

Testing MQTT over websockets

You can test MQTT over websockets using Eclipse Paho JavaScript client Utility.

After connecting you can subscribe and publish to topics.

--

--

Shyaman Jayasundara
Shyaman Jayasundara

Written by Shyaman Jayasundara

Research Assistant | Computer Engineering👨‍🎓| University of Peradeniya

Responses (5)