de Mosquitto MQTT Messaging Broker te installeren en te beveiligen op Ubuntu 20.04

Mosquitto is een open-source message broker die gebruik maakt van het Message Queuing Telemetry Transport (MQTT) protocol. Het protocol is ontworpen om lichtgewicht communicatie te bieden aan het Internet of Things (IoT) apparaten. Het wordt vaak gebruikt voor GPS-tracking van voertuigen, domotica, omgevingssensoren en grootschalige gegevensverzameling.

Het MQTT protocol draait bovenop het TCP/IP model. Omdat het lichtgewicht is, kun je met zijn kleine code toepassingen maken voor apparaten met minimale middelen. Het is gebaseerd op het publish/subscribe model. In dit model maakt de client verbinding met de Mosquitto server, die fungeert als makelaar om informatie te sturen naar andere clients die op een kanaal zijn geabonneerd.

In deze tutorial zul je Mosquitto installeren en de broker instellen om SSL te gebruiken om de communicatie te beschermen.

Voorwaarden

  • Een Ubuntu 20.04 server met een niet-root gebruiker met sudo rechten.
  • Een domeinnaam (myqtt.example.com) gericht op je server.

Stap 1 – Installeer Mosquitto Server en Client

Ubuntu wordt geleverd met de oudere 1.6 versie van Mosquitto. Om de nieuwste versie te installeren, voeg je de officiële Mosquitto repository toe.

$ sudo add-apt-repository ppa:mosquitto-dev/mosquitto-ppa

Installeer de Mosquitto server en de client.

$ sudo apt install mosquitto mosquitto-clients

Controleer de status van de server.

$ sudo systemctl status mosquitto
? mosquitto.service - Mosquitto MQTT Broker
     Loaded: loaded (/lib/systemd/system/mosquitto.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2022-01-25 09:18:40 UTC; 25s ago
       Docs: man:mosquitto.conf(5)
             man:mosquitto(8)
   Main PID: 119694 (mosquitto)
      Tasks: 1 (limit: 2274)
     Memory: 1.0M
     CGroup: /system.slice/mosquitto.service
             ??119694 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

Jan 25 09:18:39 <userid> systemd[1]: Starting Mosquitto MQTT Broker...
Jan 25 09:18:40 <userid> systemd[1]: Started Mosquitto MQTT Broker.

Stap 2 – Configureer MQTT wachtwoordverificatie

Mosquitto wordt geleverd met een hulpprogramma om een wachtwoordbestand te genereren met de naam mosquitto_passwd. Mosquitto slaat alle configuraties op in de map /etc/mosquitto.

Voer het volgende commando uit om een versleuteld wachtwoordbestand te genereren op /etc/mosquitto/passwd voor de gebruikersnaam username. Voer een wachtwoord naar keuze in.

$ sudo mosquitto_passwd -c /etc/mosquitto/passwd username
Password:
Reenter password:

Maak vervolgens een bestand default.conf aan in de map /etc/mosquitto/conf.d en open het voor bewerking.

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

Plak de volgende regels om de locatie van het wachtwoordbestand op te geven. Als je het listener veld weglaat, wordt er altijd anoniem verbinding gemaakt, ongeacht de configuratie.

listener 1883
password_file /etc/mosquitto/passwd

Sla het bestand op door op Ctrl + X te drukken en Y in te voeren als daarom wordt gevraagd.

Herstart de Mosquitto server om de wijziging door te voeren.

$ sudo systemctl restart mosquitto

Stap 3 – Test de Mosquitto-client

Afhankelijk van het gebruik kun je de Mosquitto client gebruiken om berichten over verschillende onderwerpen te versturen en te ontvangen. Een client is een abonnee of een uitgever.

De volgende stap is het abonneren op een onderwerp. In het MQTT protocol verwijst een topic naar een string die door de server/broker wordt gebruikt om berichten te filteren voor de aangesloten clients. Hier zijn enkele voorbeeldonderwerpen die je kunt gebruiken in een domoticatoepassing.

  • home/verlichting/zitkamer
  • home/verlichting/keuken
  • home/lights/master_bedroom
  • home/lights/kids_slaapkamer

Om je op een onderwerp te abonneren voer je het commando mosquitto_sub -t uit, gevolgd door het onderwerp. Om je bijvoorbeeld te abonneren op het onderwerp home/lights/kitchen voer je het volgende commando uit.

$ mosquitto_sub -u username -P YOUR_PASSWORD -t "home/lights/kitchen"

Sluit het bestaande venster niet. Open een nieuw terminalvenster om een bericht te publiceren naar het home/lights/kitchen onderwerp met het volgende commando.

$ mosquitto_pub -u username -P YOUR_PASSWORD -m "ON" -t "home/lights/kitchen"

Ga terug naar het eerste terminalvenster, en je ontvangt ON payload.

ON

Stuur vervolgens het OFF bericht naar hetzelfde onderwerp vanaf de tweede terminal.

$ mosquitto_pub -u username -P YOUR_PASSWORD -m "OFF" -t "home/lights/kitchen"

De eerste terminal toont het nieuw gepubliceerde bericht.

ON
OFF

Als je een niet-geauthenticeerd commentaar probeert te sturen, zal dat mislukken. Probeer bijvoorbeeld het volgende commando.

$ mosquitto_sub -t "home/lights/sitting_room"
Connection error: Connection Refused: not authorised.

Het wordt niet aanbevolen, maar je moet de volgende regel toevoegen aan het bestand /etc/mosquitto/conf.d/default.conf als je de commando’s zonder authenticatie wilt uitvoeren.

allow_anonymous true

Stap 4 – SSL installeren

Om een SSL-certificaat te installeren met Let’s Encrypt, moeten we het hulpprogramma Certbot downloaden. We zullen daarvoor het Snapd package installer gebruiken.

Installeer Snapd installatieprogramma.

$ sudo apt install snapd

Zorg ervoor dat je versie van Snapd up-to-date is.

$ sudo snap install core 
$ sudo snap refresh core

Installeer Certbot.

$ sudo snap install --classic certbot

Gebruik het volgende commando om ervoor te zorgen dat het Certbot commando draait door een symbolische link te maken naar de /usr/bin directory.

$ sudo ln -s /snap/bin/certbot /usr/bin/certbot

Genereer een SSL-certificaat.

$ sudo certbot certonly --standalone --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d mqtt.example.com

Het bovenstaande commando zal een certificaat downloaden naar de /etc/letsencrypt/live/mqtt.example.com directory op je server.

Genereer een Diffie-Hellman groepscertificaat.

$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Maak een challenge web root directory voor Let’s Encrypt auto-renewal.

$ sudo mkdir -p /var/lib/letsencrypt

Maak een Cron Job om de SSL te vernieuwen. Deze zal elke dag draaien om het certificaat te controleren en zo nodig te vernieuwen. Maak daarvoor eerst het bestand /etc/cron.daily/certbot-renew aan en open het voor bewerking.

$ sudo nano /etc/cron.daily/certbot-renew

Plak de volgende code.

#!/bin/sh
certbot renew --cert-name mqtt.example.com --webroot -w /var/lib/letsencrypt/

Sla het bestand op door op Ctrl + X te drukken en Y in te voeren als daarom wordt gevraagd.

Wijzig de rechten op het taakbestand om het uitvoerbaar te maken.

$ sudo chmod +x /etc/cron.daily/certbot-renew

Stap 5 – Configureer MQTT SSL

Nu we de SSL-certificaten klaar hebben, moeten we Mosquitto er toegang toe geven. Hiervoor moeten we de certificaten kopiëren naar een locatie waar Mosquitto toegang toe heeft.

$ sudo cp /etc/letsencrypt/live/mqtt.example.com/fullchain.pem /etc/mosquitto/certs/server.pem
$ sudo cp /etc/letsencrypt/live/mqtt.example.com/privkey.pem /etc/mosquitto/certs/server.key

Verander het eigendom van de /etc/mosquitto/certs directory in de mosquitto gebruiker die tijdens de installatie is aangemaakt.

$ sudo chown mosquitto: /etc/mosquitto/certs

De volgende stap om de SSL-encryptie voor Mosquitto in te schakelen is het opgeven van de locatie van de SSL-certificaten. Open het configuratiebestand om het te bewerken.

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

Plak de volgende code aan het eind van het bestand.

. . .
listener 8883
certfile /etc/mosquitto/certs/server.pem
cafile  /etc/ssl/certs/ISRG_Root_X1.pem
keyfile /etc/mosquitto/certs/server.key
dhparamfile /etc/ssl/certs/dhparam.pem

Sla het bestand op door op Ctrl + X te drukken en Y in te toetsen als daarom wordt gevraagd. Zorg ervoor dat je een newline achterlaat aan het eind van het bestand.

Het gedeelte listener 8883 stelt de versleutelde luisteraar in. Dit is de standaardpoort voor MQTT + SSL, aangeduid als MQTTS. De volgende vier regels specificeren de locatie van de SSL-bestanden.

Herstart Mosquitto om de instellingen bij te werken.

$ sudo systemctl restart mosquitto

Je moet de firewall bijwerken om verbindingen naar poort 8883 toe te staan.

$ sudo ufw allow 8883

Vervolgens moeten we de functionaliteit testen met het commando mosquitto_pub.

$ mosquitto_pub -h mqtt.example.com -t "home/lights/kitchen" -m "hello" -p 8883 --capath /etc/ssl/certs/ -u username -P YOUR_PASSWORD

Zoals je kunt zien, hebben we bepaalde extra parameters opgenomen, waaronder het poortnummer en het pad naar de SSL-certificaten. Wanneer je SSL moet gebruiken, moet je altijd de volledige hostnaam opgeven, dus mqtt.example.com in plaats van localhost, anders zou het een fout geven.

Je moet ook telkens de richtlijn --capath toevoegen. Deze vertelt de Mosquitto cliënt om te zoeken naar root-certificaten die door het besturingssysteem zijn geïnstalleerd.

Stap 6 – SSL vernieuwing instellen

Certbot zal automatisch je certificaat vernieuwen voordat het verloopt. Maar je moet hem vertellen om de vernieuwde certificaten te kopiëren naar de /etc/mosquitto/certs directory en de Mosquitto service te herstarten.

Dat gaan we doen door een shellscript te maken. Maak een bestand mosquitto-copy.sh aan in de map /etc/letsencrypt/renewal-hooks/deploy.

$ sudo nano /etc/letsencrypt/renewal-hooks/deploy/mosquitto-copy.sh

Plak er de volgende code in. Vervang de waarde van de variabele MY_DOMAIN door jouw domein. De variabele ${RENEWED_LINEAGE} wijst bij vernieuwing naar de map /etc/letsencrypt/live/mqtt.example.com.

# Set which domain this script will be run for
MY_DOMAIN=mqtt.example.com
# Set the directory that the certificates will be copied to.
CERTIFICATE_DIR=/etc/mosquitto/certs

if [ "${RENEWED_DOMAINS}" = "${MY_DOMAIN}" ]; then
	# Copy new certificate to Mosquitto directory
	cp ${RENEWED_LINEAGE}/fullchain.pem ${CERTIFICATE_DIR}/server.pem
	cp ${RENEWED_LINEAGE}/privkey.pem ${CERTIFICATE_DIR}/server.key

	# Set ownership to Mosquitto
	chown mosquitto: ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key

	# Ensure permissions are restrictive
	chmod 0600 ${CERTIFICATE_DIR}/server.pem ${CERTIFICATE_DIR}/server.key

	# Tell Mosquitto to reload certificates and configuration
	pkill -HUP -x mosquitto
fi

Sla het bestand op door op Ctrl + X te drukken en Y in te voeren als daarom wordt gevraagd.

Maak het bestand uitvoerbaar.

$ sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/mosquitto-copy.sh

Dit script wordt automatisch uitgevoerd bij elke succesvolle vernieuwing van het certificaat.

Als je Mosquitto en een webserver zoals Nginx draait, moet je Certbot opdragen de server te stoppen voor de vernieuwing en weer te starten als hij klaar is. Open daarvoor het bestand etc/letsencrypt/renewal/mqtt.example.com.conf.

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

Voeg de volgende regels toe aan het einde van het bestand. Verander de commando’s overeenkomstig de webserver die je gebruikt.

pre_hook = systemctl stop nginx
post_hook = systemctl start nginx

Sla het bestand op door op Ctrl + X te drukken en Y in te voeren als daarom wordt gevraagd.

Voer een Certbot testrun uit om te controleren.

$ sudo certbot renew --dry-run

Als je geen fouten ziet, betekent dit dat alles is ingesteld.

Stap 7 – Websockets configureren

Je kunt Mosquitto configureren om het MQTT protocol te gebruiken vanuit browsers met behulp van Javascript door gebruik te maken van de Websockets functionaliteit. Om dit in te schakelen, open je het configuratiebestand.

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

Plak de volgende regels aan het eind van het bestand.

. . .
listener 8083
protocol websockets
certfile /etc/mosquitto/certs/server.pem
cafile  /etc/ssl/certs/ISRG_Root_X1.pem
keyfile /etc/mosquitto/certs/server.key
dhparamfile /etc/ssl/certs/dhparam.pem

Sla het bestand op door op Ctrl + X te drukken en Y in te voeren als daarom wordt gevraagd.

Als je merkt, is het hetzelfde blok als dat wat we gebruikten voor het inschakelen van SSL, behalve de poortnummer- en protocolvelden. 8083 is de meest gebruikte poort voor MQTT om met WebSockets te praten.

Start de Mosquitto service opnieuw op.

$ sudo systemctl restart mosquitto

Open poort 8083.

$ sudo ufw allow 8083

We moeten een browser-gebaseerde MQTT client gebruiken om de WebSockets functionaliteit te testen. Er zijn veel clients beschikbaar, maar wij zullen voor ons doel de HiveMQ Websocket client gebruiken. Start de client in je browser, en je ziet het volgende.

HiveMQ Websockets-cliënt

Vul de velden in zoals in de bovenstaande schermafbeelding.

  • De host moet het domein van je Mosquitto server zijn, mqtt.example.com.
  • De poort moet 8083 zijn.
  • Het ClientID veld kun je zo laten.
  • De gebruikersnaam moet je Mosquitto gebruikersnaam zijn.
  • Het wachtwoord is het wachtwoord dat je hierboven hebt aangemaakt.
  • Vink het vakje SSL aan.

Druk op de Connect knop, en de HiveMQ client wordt verbonden met je Mosquitto server.

Zodra je verbonden bent, voer je home/lights/kitchen in als onderwerp, voer je een willekeurig bericht in en druk je op Publiceren.

Mosquitto Websocket publiceren

Het bericht verschijnt in je mosquitto_sub terminalvenster en bevestigt de succesvolle verbinding.

Mosquitto Websockets Terminal Antwoord

Hieruit blijkt dat de Websockets implementatie succesvol is.