Eclipse Mosquitto Secure MQTT Broker Docker Installation
In diesem Tutorial erkläre ich wie man mittels Docker Compose den MQTT Broker Mosquitto von Eclipse deployt und diesen mittels openssl Self Signed Zertifikaten absichert. Mehr Informationen rund um das Thema MQTT findet ihr hier:
- MQTT - What to know about it?
- Kategorie: MQTT
Wie man Docker und Docker Compose Installiert hier:
- Docker Installation unter Debian Linux
- Docker Installation unter MacOS
- Docker Compose Installation unter Debian Linux
SSL Zertifikate erstellen
Zuerst erstellen wir unseren Compose Projekt Ordner und den SSL Zertifikats Ordner:
mkdir -p /opt/mosquitto/certs
mkdir -p /opt/mosquitto/data/mosquitto/conf/certs
nun erstellen wir im certs
Ordner ein kleines Skript welches uns die Zertifikate erstellt:
Download hier möglich: https://raw.githubusercontent.com/alaub81/scripts/master/generate-certs.sh
/opt/mosquitto/certs/generate-certs.sh
#!/usr/bin/env bash
#########################################################################
#Name: generate-certs.sh
#Subscription: This Script generates ssl certs
##by A. Laub
#andreas[-at-]laub-home.de
#
#License:
#This program is free software: you can redistribute it and/or modify it
#under the terms of the GNU General Public License as published by the
#Free Software Foundation, either version 3 of the License, or (at your option)
#any later version.
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
#or FITNESS FOR A PARTICULAR PURPOSE.
#########################################################################
#Set the language
export LANG="en_US.UTF-8"
#Load the Pathes
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# set the variables
# Just change to your belongings
COMPOSE_PROJECT_DIR="/opt/mosquitto"
IP="FQDN / IP ADRESS"
SUBJECT_CA="/C=SE/ST=Berlin/L=Berlin/O=himinds/OU=CA/CN=$IP"
SUBJECT_SERVER="/C=SE/ST=Berlin/L=Berlin/O=himinds/OU=Server/CN=$IP"
SUBJECT_CLIENT="/C=SE/ST=Berlin/L=Berlin/O=himinds/OU=Client/CN=$IP"
### Do the stuff
function generate_CA () {
echo "$SUBJECT_CA"
openssl req -x509 -nodes -sha256 -newkey rsa:2048 -subj "$SUBJECT_CA" -days 3650 -keyout $COMPOSE_PROJECT_DIR/certs/ca.key -out $COMPOSE_PROJECT_DIR/certs/ca.crt
}
function generate_server () {
echo "$SUBJECT_SERVER"
openssl req -nodes -sha256 -new -subj "$SUBJECT_SERVER" -keyout $COMPOSE_PROJECT_DIR/certs/server.key -out $COMPOSE_PROJECT_DIR/certs/server.csr
openssl x509 -req -sha256 -in $COMPOSE_PROJECT_DIR/certs/server.csr -CA $COMPOSE_PROJECT_DIR/certs/ca.crt -CAkey $COMPOSE_PROJECT_DIR/certs/ca.key -CAcreateserial -out $COMPOSE_PROJECT_DIR/certs/server.crt -days 3650
}
function generate_client () {
echo "$SUBJECT_CLIENT"
openssl req -new -nodes -sha256 -subj "$SUBJECT_CLIENT" -out $COMPOSE_PROJECT_DIR/certs/client.csr -keyout $COMPOSE_PROJECT_DIR/certs/client.key
openssl x509 -req -sha256 -in $COMPOSE_PROJECT_DIR/certs/client.csr -CA $COMPOSE_PROJECT_DIR/certs/ca.crt -CAkey $COMPOSE_PROJECT_DIR/certs/ca.key -CAcreateserial -out $COMPOSE_PROJECT_DIR/certs/client.crt -days 3650
}
function copy_keys_to_broker () {
cp $COMPOSE_PROJECT_DIR/certs/ca.crt $COMPOSE_PROJECT_DIR/data/mosquitto/conf/certs/
cp $COMPOSE_PROJECT_DIR/certs/server.crt $COMPOSE_PROJECT_DIR/data/mosquitto/conf/certs/
cp $COMPOSE_PROJECT_DIR/certs/server.key $COMPOSE_PROJECT_DIR/data/mosquitto/conf/certs/
}
generate_CA
generate_server
generate_client
copy_keys_to_broker
sollte openssl nicht installiert sein:
apt install openssl -y
nun vergeben wir das execute Recht und starten unser Script, damit es uns die Zertifikate erstellt:
chmod +x /opt/mosquitto/certs/generate-certs.sh
/opt/mosquitto/certs/generate-certs.sh
Die Zertifikate die der MQTT Brocker benötigt liegen dann unter /opt/mosquitto/data/mosquitto/conf/certs
Mosquitto via Docker Compose
Um Mosquitto via docker-compose zu deployen, brauchen wir folgendes docker-compose.yml
und .env
File:
/opt/mosquitto/.env
# Config File for Mosquitto MQTT Application
# Port Configuration Mosquitto MQTT
MQTT_PORT=1883
MQTT_TLS_PORT=8883
# Timezone
TZ="Europe/Berlin"
/opt/mosquitto/docker-compose.yml
version: '3.7'
services:
mosquitto:
image: eclipse-mosquitto:latest
restart: always
volumes:
- "./data/mosquitto/conf:/mosquitto/config"
- mosquitto_data:/mosquitto/data
- mosquitto_log:/mosquitto/log
ports:
- "${MQTT_PORT}:1883"
- "${MQTT_TLS_PORT}:8883"
environment:
TZ: ${TZ}
labels:
com.centurylinklabs.watchtower.enable: "true"
#network_mode: host
networks:
frontend-nw:
aliases:
- mqtt
networks:
frontend-nw:
driver: bridge
driver_opts:
com.docker.network.bridge.name: br-mosquitto
volumes:
mosquitto_data:
mosquitto_log:
Möchte man das Ganze zum Beispiel wie ich direkt mit openHAB deployen, dann einfach die Zeilen in das dortige docker-compose.yml
und .env
file kopieren. Im Kapitel openHAB Integration
Nun brauchen wir noch die mosquitto.conf
, die den Broker nach unseren Bedürfnissen konfiguriert:
/opt/mosquitto/data/mosquitto/conf/mosquitto.conf
listener 1883
listener 8883
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
allow_anonymous false
password_file /mosquitto/config/mosquitto.passwd
cafile /mosquitto/config/certs/ca.crt
certfile /mosquitto/config/certs/server.crt
keyfile /mosquitto/config/certs/server.key
# By default a TLS enabled listener will operate in a similar fashion to a
# https enabled web server, in that the server has a certificate signed by a CA
# and the client will verify that it is a trusted certificate. The overall aim
# is encryption of the network traffic. By setting require_certificate to true,
# the client must provide a valid certificate in order for the network
# connection to proceed. This allows access to the broker to be controlled
# outside of the mechanisms provided by MQTT.
#require_certificate true
Jetzt legen wir noch eine Dummy Passwort Datei an, da sonst der Docker Container nicht startet:
touch /opt/mosquitto/data/mosquitto/conf/mosquitto.passwd
nun starten wir das Ganze:
cd /opt/mosquitto
docker-compose up -d
jetzt sollte der Aufruf docker ps
einen laufenden Mosquitto Docker Container zeigen:
docker ps
####
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f6e4a6840aa6 eclipse-mosquitto:latest "/docker-entrypoint.…" 7 seconds ago Up 5 seconds 0.0.0.0:1883->1883/tcp, 0.0.0.0:8883->8883/tcp
Nun legen wir noch einen oder mehrere Benutzer an, mit denen unsere Clients sich in Zukunft am MQTT Brocker anmelden können. Dafür nehmen wir den laufenden Docker Container:
docker-compose exec mosquitto mosquitto_passwd -c /mosquitto/config/mosquitto.passwd mosquitto
Testing mittels python Script
Da unser Broker nun läuft, mittels angelegtem Benutzer und Passwort geschützt ist und zusätzlich noch eine SSL Verschlüsselte Übertragung bietet, können wir diesen nun testen. Dafür reicht folgendes einfaches python Script, welches den paho MQTT client verwendet. Dafür müssen wir diesen, wie auch python3 installieren:
apt update && apt install python3 python3-pip python3-paho-mqtt -y
# oder via pip3
apt update && apt install python3 python3-pip
pip3 install paho-mqtt
nun erstellen wir das folgende Test Script.
Download hier möglich: https://raw.githubusercontent.com/alaub81/scripts/master/mqtt-test.py
/root/mqtt-test.py
#!/usr/bin/env python3
import ssl, time, random
import paho.mqtt.client as paho
# set the variables
broker='FQDN / IP of Broker'
port=8883
clientid=f'python-mqtt-{random.randint(0, 1000)}'
username='mosquitto'
password='password'
insecure=True
qos=1
retain_message=True
# do the stuff
client=paho.Client(clientid)
client.username_pw_set(username, password)
client.tls_set(cert_reqs=ssl.CERT_NONE) #no client certificate needed
client.tls_insecure_set(insecure)
##### define callback
def on_message(client, userdata, message):
time.sleep(1)
print("received message =",str(message.payload.decode("utf-8")))
##### Bind function to callback
client.on_message=on_message
#####
print(clientid,"is connecting to broker",broker, port)
client.connect(broker, port) #connect
client.loop_start() #start loop to process received messages
print("subscribing ")
client.subscribe("house/+") #subscribe to all house topics
time.sleep(4)
print("publishing ")
client.publish("house/bulb1","ON",qos,retain_message) #publish
client.publish("house/bulb2","OFF",qos,retain_message) #publish
client.publish("house/bulb3","NONE",qos,retain_message) #publish
time.sleep(4)
client.disconnect() #disconnect
client.loop_stop() #stop loop
nun geben wir dem Script noch das execute Recht und starten es einfach:
chmod +x /root/mqtt-test.py
/root/mqtt-test.py
Testing mittels MQTT Explorer
Der MQTT Explorer ist ein super Tool um grafisch zu sehen, was auf einem Broker los ist. Verfügbar ist er für alle Plattformen. Ich habe ihn einfach im Apple App Store auf meinen Mac heruntergeladen. Man kann mit diesem nicht nur eine subscription machen sonder auch publishen. Aber zunächst zeigt er uns ersteinmal, ob unser Broker online ist und man sich zu ihm verbinden kann. Dafür einfach die folgenden Verbindungen anlegen und schauen ob man sich verbinden kann:
Nach dem die Verbindung hergestellt wurde, sieht man $SYS bereits. Bei Publish kann man nun eine neue Message publizieren.
openHAB Integration
Möchte man den Mosquitto MQTT Broker in das openHAB docker compose Projekt einfügen, muss man ein paar Dinge beachten:
- openHAB nutzt kein docker Netzwerk sondern im besten Fall die host network mode.
- Das ändern der Ports muss somit im
mosquitto.conf
stattfinden da beim host network mode keine Ports publiziert werden
das ganze sieht im docker-compose.yml
dann wie folgt aus:
...
mosquitto:
image: eclipse-mosquitto:latest
restart: always
volumes:
- "./data/mosquitto/conf:/mosquitto/config"
- mosquitto_data:/mosquitto/data
- mosquitto_log:/mosquitto/log
environment:
TZ: ${TZ}
labels:
com.centurylinklabs.watchtower.enable: "true"
network_mode: host
...
...
volumes:
mosquitto_data:
mosquitto_log:
das .env
File ist nur noch für die TimeZone verantwortlich, da diese bereits im openHAB .env ist, brauchen wir hier nichts mehr zu machen.
in der mosquito.conf
müssen nun ggf. die Ports angepasst werden. Dies geht bei den listener
Einstellungen
Ein docker-compose up -d
deployed dann unseren Mosquitto.
Wie man Items via MQTT in openHAB bekommt könnt ihr hier nachlesen: