Mosquitto
Jak funguje MQTT
V tutoriálu je srozumitelně popsané, jak MQTT funguje.
Podrobnější logování v Mosquitto
Do konfiguračního souboru lze dle zdroje přidat tyto řádky:
# Types of messages to log. Use multiple log_type lines for logging # multiple types of messages. # Possible types are: debug, error, warning, notice, information, # none, subscribe, unsubscribe, websockets, all. # Note that debug type messages are for decoding the incoming/outgoing # network packets. They are not logged in "topics". log_type error log_type warning log_type notice log_type information
Zabezpečení Mosquitto v Dockeru
Zapnutí autentizace
Vycházím z návodu Configuring the Mosquitto MQTT Docker container for use with Home Assistant, který popisuje zapnutí autentizace pro Mosquitto. Další informace jsem pak čerpal z tohoto článku: Deploying Mosquitto MQTT broker on Linux using Docker
V konfiguračním souboru mosquitto.conf nastavím/změním toto:
password_file /mosquitto/pwfile/pwfile allow_anonymous false
Pak se připojím do kontejneru s mosquitto a vytvořím uživatele s heslem:
docker exec -it mosquitto sh mosquitto_passwd -c /mosquitto/pwfile/pwfile majordomus
Nakonec retartovat kontejner s Mosquitto.
Příkaz pro čtení s autentizací:
$ mosquitto_sub -u henry --pw 'passw0rd' -h localhost -p 1883 -v -t test/message
Příkaz pro publikaci s autentizací:
$ mosquitto_pub -u henry -P 'passw0rd' -h localhost -p 1883 -t test/message -m 'Hello World!'
Zapnutí komunikace přes SSL
Nejprve jsem postupoval podle návodu Secure MQTT broker (TLS) and Docker Compose.
Jako první jsem použil tento skript pro vygenerování certifikátů:
#!/bin/bash IP="192.168.1.22" SUBJECT_CA="/C=CZ/ST=Brno/L=Brno/O=majordomus/OU=CA/CN=$IP" SUBJECT_SERVER="/C=CZ/ST=Brno/L=Brno/O=majordomus/OU=Server/CN=$IP" SUBJECT_CLIENT="/C=CZ/ST=Brno/L=Brno/O=majordomus/OU=Client/CN=$IP" function generate_CA () { echo "$SUBJECT_CA" openssl req -x509 -nodes -sha256 -newkey rsa:2048 -subj "$SUBJECT_CA" -days 365 -keyout ca.key -out ca.crt } function generate_server () { echo "$SUBJECT_SERVER" openssl req -nodes -sha256 -new -subj "$SUBJECT_SERVER" -keyout server.key -out server.csr openssl x509 -req -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 } function generate_client () { echo "$SUBJECT_CLIENT" openssl req -new -nodes -sha256 -subj "$SUBJECT_CLIENT" -out client.csr -keyout client.key openssl x509 -req -sha256 -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365 } function generate_der () { echo "generate DER certificates for ESP8266" openssl x509 -in client.crt -out cert.der -outform DER openssl rsa -in client.key -out key.der -outform DER } function generate_server_pem () { echo "generate PEM certificates for Node RED" openssl x509 -in server.crt -out server-cert.pem openssl rsa -in server.key -out server-key.pem } generate_CA generate_server generate_client generate_der generate_server_pem
Kód jsem si trochu upravil. Určitě je potřeba tam dát IP adresu zařízení serveru a dále jsem změnil to, že certifikáty se vygenerují s platností na delší dobu než 365 dní.
Dále jsem přidal kód pro vygenerování DER certifikátů serveru kvůli ESP8266. V diskusi jsem se dočetl, že DER je binární formát a ten právě potřebuje ESP8266.
V dalším kroku jsem nahrál soubory ca.crt, server.crt a server.key do konfigurační složky mosquitto a nastavil konfigurační soubor:
cafile /mosquitto/config/ca.crt certfile /mosquitto/config/server.crt keyfile /mosquitto/config/server.key require_certificate true #use_identity_as_username true
Parametr use_identity_as_username jsem zakomentoval. Pokud by byl aktivní, tak by nebylo potřeba používat přihlašovací jméno a heslo. Stačil by pouze klientský certifikát. Ale takové použití mi nevyhovuje a nevím, jestli by to nedělalo s ESP8266 problém, když klientský certifikát nevyužívá.
Jako poslední jsem upravil port, na kterém mosquitto běží, protože zabezpečené připojení se očekává na portu 8883.
listener 8883
V dalším kroku jsem ještě editoval docker-compose.yml a změnil port pro mosquitto také:
ports: - "8883:8883"
docker-compose up -d
Pro otestování zabezpečeného připojení mi pomohl tento návod.
mosquitto_sub -h 192.168.1.22 -u 'majordomus' --pw 'supertajneheslo' -t 'dum/pracovna/vlhkost' -p 8883 -d --cafile ca.crt --cert client.crt --key client.key Client (null) sending CONNECT Client (null) received CONNACK (0) Client (null) sending SUBSCRIBE (Mid: 1, Topic: dum/pracovna/vlhkost, QoS: 0, Options: 0x00) Client (null) received SUBACK Subscribed (mid: 1): 0
ESP8266, microPython a Mosquito přes SSL
Po dlouhém bádání jsem se dopracoval k tomu, že je potřeba certifikát v binárním formátu DER. Nainstaloval jsem si mpfshell a nahrál do ESP8266 vygenerované certifikáty cert.der a key.der. Ještě je dobré si uvědomit, že by nemělo být připojeno nic jiného k portu s ESP8266, jinak to nebude fungovat.
sudo pip3 install mpfshell mpfshell -c "open ttyUSB0" ls put cert.der put key.der ls
Pak jsem musel upravid kód v microPythonu, aby načetl certifikáty a použil je při autentizaci.
with open("key.der", 'rb') as f: key = f.read() with open("cert.der", 'rb') as f: cert = f.read() ssl_params = dict() ssl_params["cert"] = cert ssl_params["key"] = key mqttc = MQTTClient(CLIENT_NAME, BROKER_ADDR, 8883, USER, PASSWORD, ssl=True, ssl_params=ssl_params, keepalive=60)
zdroje, ze kterých jsem čerpal: