Mosquitto is a light-weight broker that powers cheap, low power, fast messaging on MQTT. MQTT (Message Queue Telemetry Transport) is amongst the most popular messaging service for low cost devices that talk over IP. We at Yatis use MQTT with a Mosquitto broker to power real time communications between devices, servers, mobile and web applications. In this document we will describe how to install Mosquitto on a AWS Ubuntu 16 machine and the additional steps we took to secure it and to make it robust.
What is Mosquitto
Mosquitto is a light-weight, open source implementation of an MQTT. Its can be installed on Unix machines. It can be secured via SSL and passwords, which we will describe below.
Step 1: Install Mosquitto
Log into the AWS Ubuntu 16/18 machine.
$ sudo apt-get update
Install
$ sudo apt-get install mosquitto mosquitto-clients
The command above installs both the mosquitto broker and the
publish / subscribe clients. The mosquitto broker is now installed and active. You can listen to declare any channel to subscribe and publish to test it.
Sample subscribe:
$ mosquitto_sub -h localhost -t mychanel
Sample publish:
$ mosquitto_pub -h localhost -t mychanel "Hello World"
Step 2: Enable Remote Access
To publish or subscribe using this broker from a remote machine, we need first open port 1883 in the security group setting. Using the AWS console, go to the security group and open port 1883 to everyone.
The default config file may permit connections from localhost only. The default conf file is can be opened
$ sudo vim /etc/mosquitto/conf.d/default.conf
The file should contain line following enable remote usage
listener 1883
Note that this port is currently unsecured, so if you don’t want to permit remote access:
listener 1883 localhost
Everytime you edit the conf file, you will have to restart the service for the settings to take effect.
$ sudo systemctl restart mosquitto
Step 3: Robust MQTT
We noticed that our MQTT broker crashed sometimes, disabling the real time communication. So we added a script that checked the state of the process and restarted Mosquitto in case it was down.
if [ "`ps -aux | grep /usr/sbin/mosquitto | wc -l`" == "1" ] then echo "mosquitto wasnt running so attempting restart" >> /home/ubuntu/cron.log systemctl restart mosquitto exit 0 fi echo "$SERVICE is currently running" >> /home/ubuntu/cron.log exit 0
This can script can be stored in a file say ‘mosquitto_restart.sh’.
This file needs to be made an executable and then put in a cron that runs every 5 minutes. The cron should be set as root.
$ chmod +x mosquitto_restart.sh $ sudo -i $ crontab -e
Add the following statement
*/5 * * * * /home/ubuntu/mosquitto_restart.sh
Close crontab. Now the script will execute every 5 minutes and restart mosquitto in case it is in active.
Step 4: SSL security
The SSL (Secure Shell Layer) is added to secure all communication between your server and other computers and mobile devices on the internet. We used letsencrypt certificates to secure our MQTT server. Letsencrypt certificates were free at the time of writing this article, so there should be no additional costs incurred. The commands to install letencrypt certbot are as follows.
$ sudo add-apt-repository ppa:certbot/certbot $ sudo apt-get update $ sudo apt-get install certbot
The next step is to complete the HTTP challenge. To do that you need to assign a domain/subdomain e.g. mqtt.example.com to this IP address. You should also open the HTTP port 80 in the security group. The subdomain e.g. mqtt.example.com should already be added as record in DNS settings with your domain name provider. If you are using GoDaddy this link explains how to add a subdomain.
$ sudo certbot certonly --standalone --standalone-supported-challenges http-01 -d mqtt.example.com
The above command run the HTTP challenge on its own. The option -standalone-supported-challenges http-01 specifies that it use the HTTP port 80 only, -d specifies the subdomain. You will be prompted to fill in your email address and agree to terms and conditions.
The certificates are permanent and need to renewed regularly. Such regular processes can set up using the cron as done in step 3. To setup cron run
$ sudo crontab -e
Add the above line to the crontab. This command will check the certificate everyday at 4 45 and renew them if needed. The post-hook statement will restart the broker if the certificates have been renewed.
45 4 * * * certbot renew --noninteractive --post-hook "systemctl restart mosquitto"
Step 5: Web Sockets
We use MQTT to enable live tracking and notifications on our web application. If your Angular / Javascript web application wants to communicate with MQTT, then web sockets needs to be enabled. Open the configuration file
$ sudo vim /etc/mosquitto/conf.d/default.conf
Add the following lines to the file
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
Open up port 8083 in the security group for this instance, and restart the MQTT broker. You can now access the MQTT service on port 8083 using secure web sockets (WSS).
Step 5: Password Protection
Adding password protection to the MQTT is strongly recommended. To add password run the following command
$ sudo mosquitto_passwd -c /etc/mosquitto/passwd <user>
You will now be prompted to add a <password>
The password word is created and this needs to specified in the configuration file. So open the configuration file
$ sudo nano /etc/mosquitto/conf.d/default.conf
Add the following lines in the beginning of the file
allow_anonymous false password_file /etc/mosquitto/passwd
Close the configuration file and restart the broker. You now need the specified user name and password to subscribe or publish on the MQTT broker.
$ mosquitto_sub -h localhost -t test -u "user" -P "password" $ mosquitto_pub -h localhost -t "test" -m "hello world" -u "user" -P "password"
Complete Conf file
A complete configuration file is published below for reference. It uses password protection, runs a MQTT on port 1883, MQTTS on port 1884, websockets on port 3033, and WSS on port 8083. Do not forget the open these ports in the security group.
allow_anonymous false password_file /etc/mosquitto/passwd listener 1883 listener 1884 certfile /etc/letsencrypt/live/mqtt.example.io/cert.pem cafile /etc/letsencrypt/live/mqtt.example.io/chain.pem keyfile /etc/letsencrypt/live/mqtt.example.io/privkey.pem listener 3033 protocol websockets listener 8083 protocol websockets certfile /etc/letsencrypt/live/mqtt.example.io/cert.pem cafile /etc/letsencrypt/live/mqtt.example.io/chain.pem keyfile /etc/letsencrypt/live/mqtt.example.io/privkey.pem