How to Install and Secure Mosquitto MQTT Messaging Broker on Debian 9
MQTT is a machine-to-machine messaging protocol designed to provide lightweight publish/subscribe communication for "Internet of Things" devices. It is commonly used in geo-tracking fleets, home automation, environmental sensor networks and...
Categories: Debian Miscellaneous Operating System Programming Language Debian 9
2019-05-30 15:45:50
introduce
MQTT is a machine-to-machine messaging protocol designed to provide lightweight publish/subscribe communication for "Internet of Things" devices. It is commonly used in geo-tracking fleets, home automation, environmental sensor networks, and utility-scale data collection.
Mosquitto is a popular MQTT server (or broker in MQTT ) with excellent community support and easy to install and configure.
In this tutorial, we'll install Mosquitto and set up our broker to use SSL to secure password-protected MQTT communications.
prerequisites
Before starting this tutorial, you will need:
-
A Debian 9 server with a non-root, sudo-enabled user and basic firewall setup as detailed in the Debian 9 server setup tutorial .
-
The domain name points to your server, as described in our DigitalOcean DNS product documentation . This tutorial will always be used
mqtt.example.com
. -
An auto-renewing Let's Encrypt SSL certificate for your domain and Mosquitto, generated using the Certbot tool. You can learn how to set it up in How to Retrieve a Let's Encrypt SSL Certificate on Debian 9 Using Certbot Standalone Mode
.systemctl restart mosquitto
You can add as in step 4renew_hook
. Make sure to use the same domain that was configured in the previous prerequisite steps.
Step 1 - Install Mosquitto
Debian 9 has a fairly recent version of Mosquitto in its default software repository, so we can install it from there.
First, log in as a non-root user and use apt update
the package list:
sudo apt update
Now, apt install
install Mosquitto using:
sudo apt install mosquitto mosquitto-clients
By default, Debian will start the Mosquitto service after installation. Let's test the default configuration. We'll subscribe to our broker's topic using one of the Mosquitto clients we just installed.
Topics are labels to which you publish messages and subscribe. They are arranged hierarchically, so you can use sensors/outside/temp
and sensors/outside/humidity
. How you arrange your topics is up to you and your needs. In this tutorial, we'll use a simple test subject to test our configuration changes.
Log in to your server a second time, so you have two terminals side by side. In a new terminal, mosquitto_sub
subscribe to a test topic with:
mosquitto_sub -h localhost -t test
-h
It is used to specify the host name of the MQTT server, -t
which is the topic name. After clicking ENTER
you will see no output as it mosquitto_sub
is waiting for the message to arrive. Switch back to your other terminal and post the message:
mosquitto_pub -h localhost -t test -m "hello world"
mosquitto_pub
The options are mosquitto_pub
the same as for , but this time we use additional -m
options to specify our message. Click ENTER
, and you should see another terminal pop up with hello world . You have sent your first MQTT message!
Type in a second terminal CTRL+C
to exit mosquitto_sub
, but keep the connection to the server open. We'll use it again for another test in step 5.
Next, we'll secure our installation with password-based authentication.
Step 2 - Configure the MQTT password
Let's configure Mosquitto to use a password. Mosquitto includes a utility for generating mosquitto_passwd
special password files called . This command will prompt you for the password for the specified username and place the result in /etc/mosquitto/passwd
.
sudo mosquitto_passwd -c /etc/mosquitto/passwd sammy
Now we'll open a new configuration file for Mosquitto and tell it to use this password file to require logins for all connections:
sudo nano /etc/mosquitto/conf.d/default.conf
This should open an empty file. Paste as follows:
/etc/mosquitto/conf.d/default.conf
allow_anonymous false
password_file /etc/mosquitto/passwd
Be sure to leave a trailing newline at the end of the file.
allow_anonymous false
will disable all unauthenticated connections, password_file
the line tells Mosquitto where to look for user and password information. Save and exit the file.
Now we need to restart Mosquitto and test our changes.
sudo systemctl restart mosquitto
Try posting without a password:
mosquitto_pub -h localhost -t "test" -m "hello world"
The message should be rejected:
OutputConnection Refused: not authorised.
Error: The connection was refused.
Before we try the password again, switch to the second terminal window again and subscribe to the "test" topic with username and password:
mosquitto_sub -h localhost -t test -u "sammy" -P "password"
It should connect and sit, waiting for messages. You can keep this terminal open and connected for the rest of this tutorial, as we'll be sending test messages periodically.
Now post a message with your other terminal using username and password again:
mosquitto_pub -h localhost -t "test" -m "hello world" -u "sammy" -P "password"
The message should follow step 1. We have successfully added password protection to Mosquitto. Unfortunately, we send passwords unencrypted over the internet. We'll tackle the next step by adding SSL encryption to Mosquitto.
Step 3 - Configure MQTT SSL
To enable SSL encryption, we need to tell Mosquitto where to store Let's Encrypt certificates. Open the configuration file we started earlier:
sudo nano /etc/mosquitto/conf.d/default.conf
Paste the following at the end of the file, leaving the two lines we've already added:
/etc/mosquitto/conf.d/default.conf
. . .
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
Also, make sure to leave a trailing newline at the end of the file.
We added two separate listener
blocks to the configuration. The first one, listener 1883 localhost
, updates 1883
the default MQTT listener on the port, which is what we've connected to so far. 1883
is the standard unencrypted MQTT port. That localhost
part of the line instructs Mosquitto to bind this port only to the localhost interface, so it cannot be accessed from the outside. Our firewall blocks external requests anyway, but being explicit is fine.
listener 8883
8883
Set up an encrypted listener on the port . This is the standard port of MQTT+SSL, often referred to as MQTTS. The next three lines, certfile
, cafile
and keyfile
, all point Mosquitto to the appropriate Let's Encrypt file to set up an encrypted connection.
Save and exit the file, then restart Mosquitto to update the settings:
sudo systemctl restart mosquitto
Update your firewall to allow connections to the port 8883
.
sudo ufw allow 8883
OutputRule added
Rule added (v6)
Now we use mosquitto_pub
the test again, with some different SSL options:
mosquitto_pub -h mqtt.example.com -t test -m "hello again" -p 8883 --capath /etc/ssl/certs/ -u "sammy" -P "password"
Note that we are using the full hostname instead of localhost
. Because our SSL certificate was issued against mqtt.example.com
, if we try to localhost
establish a secure connection with , we get an error message stating that the hostname does not match the certificate hostname (even though they both point to the same Mosquitto server).
--capath /etc/ssl/certs/
to mosquitto_pub
enable SSL, and tell it where to look for root certificates. These are usually installed by your operating system, so the paths are different for Mac OS, Windows, etc. mosquitto_pub
Use a root certificate to verify that the Mosquitto server's certificate is properly signed by a Let's Encrypt Certificate Authority. It's important to note that mosquitto_pub
without this option (or a similar --cafile
one), mosquitto_pub
and mosquitto_sub
will not attempt an SSL connection, even if you're connecting to 8883
a standard secure port.
If all goes well with the test results, we will see hello again in another terminal. This means your server is fully set up! If you want to extend the MQTT protocol to use websockets, you can follow the last step.mosquitto_sub
Step 4 - Configure MQTT over Websockets (optional)
To speak MQTT using JavaScript in a web browser, the protocol works over standard websockets. If you don't need this functionality, you can skip this step.
We need to add one more block to the Mosquitto configuration listener
:
sudo nano /etc/mosquitto/conf.d/default.conf
Add the following at the end of the file:
/etc/mosquitto/conf.d/default.conf
. . .
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
Also, make sure to leave a trailing newline at the end of the file.
protocol websockets
This is pretty much the same as the previous block except for the port number and line. MQTT has no official standardized port over websockets, 8083
but is the most common.
Save and exit the file, then restart Mosquitto.
sudo systemctl restart mosquitto
Now, open the port in the firewall 8083
.
sudo ufw allow 8083
To test this functionality, we will use a browser-based public MQTT client. There are a few, but the Eclipse Paho JavaScript Client is simple and easy to use. Open the Paho client in your browser . You will see the following:
Fill in the connection information as follows:
- Host should be your Mosquitto server's domain,
mqtt.example.com
. - The port should be
8083
. - ClientId can be left as the default js-utility-DI1m6 .
- Path can be left as default /ws .
- The username should be your Mosquitto username; here, we used sammy .
- The password should be the one you choose.
The rest of the fields can be left with their default values.
After pressing Connect , the Paho browser-based client will connect to your Mosquitto server.
To post a message, navigate to the Post a Message pane, fill in the Subject as Test , and enter any message in the Message section. Next, press Publish . The message will be displayed in your mosquitto_sub
terminal.
in conclusion
We have now set up a secure, password-protected, and SSL-protected MQTT server. This can serve as a powerful and secure messaging platform for any project you can dream up. Some popular software and hardware that work well with the MQTT protocol include:
- OwnTracks , an open source geo-tracking application that can be installed on mobile phones. OwnTracks will periodically report location information to your MQTT server, which you can then store and display on a map, or create alerts and activate IoT hardware based on your location.
- Node-RED is a browser-based graphical interface for "connecting" the Internet of Things together. You drag the output of one node to the input of another, and can route information through filters, between various protocols, databases, and more. Node-RED supports MQTT very well.
- ESP8266 is a cheap wifi microcontroller with MQTT capability. You could hook up one to publish temperature data to a topic, or perhaps subscribe to a barometric pressure topic and beep when a storm is coming!
These are just a few popular examples in the MQTT ecosystem. There are more hardware and software protocols that can be said. If you already have a favorite hardware platform or software language, it probably has MQTT capabilities. Have fun making your "things" communicate with each other!