Obsah

Mosquitto

Instalaci Mosquitto jsem provedl skrz Docker. Tady je docker-compose.yml:

version: '3.6'

networks:
  default:
    driver: bridge
    ipam:
      driver: default
  nextcloud:
    driver: bridge
    internal: true
    ipam:
      driver: default

services:
  mosquitto:
    container_name: mosquitto
    build:
      context: ./.templates/mosquitto/.
      args:
      - MOSQUITTO_BASE=eclipse-mosquitto:latest
    restart: unless-stopped
    environment:
    - TZ=${TZ:-Etc/UTC}
    ports:
    - "8883:8883"
    volumes:
    - ./volumes/mosquitto/config:/mosquitto/config
    - ./volumes/mosquitto/data:/mosquitto/data
    - ./volumes/mosquitto/log:/mosquitto/log
    - ./volumes/mosquitto/pwfile:/mosquitto/pwfile

Warning

V rámci instalace řeším rovnou SSL certifikáty a tomu odpovídá i porty v docker-compose.yml. Pokud bych chtěl nainstalovat verzi bez SSL, tak volím porty 1883:1883.

Vygenerování self-signed certifikátů

Protože budu Mosquitto provozovat pouze v domácí síti, budu potřebovat self signed certifikát. Podrobnosti jsem rozepsal zde, nicméně omezím se nyní na postup pouze pro náš účel.

K vytvoření nezbytných certifikátů pomůže tento skript, ve kterém je potřeba změnit IP adresu na IP adresu zařízení, na kterém MQTT server Mosquitto poběží.

#!/bin/bash
 
IP="192.168.1.22"
COUNTRY="CZ"
STATE="Brno"
LOCALITY="Brno"
ORG="majordomus"
 
SUBJECT_BASE="/C=$COUNTRY/ST=$STATE/L=$LOCALITY/O=$ORG"
SUBJECT_CA="$SUBJECT_BASE/OU=CA/CN=$IP"
SUBJECT_SERVER="$SUBJECT_BASE/OU=Server/CN=$IP"
SUBJECT_CLIENT="$SUBJECT_BASE/OU=Client/CN=$IP"
 
# Vytvořte konfigurační soubor san.cnf pro zahrnutí SAN
cat > san.cnf <<EOF
[ req ]
default_bits       = 2048
distinguished_name = req_distinguished_name
req_extensions     = req_ext
 
[ req_distinguished_name ]
countryName                = Country Name (2 letter code)
countryName_default        = $COUNTRY
stateOrProvinceName        = State or Province Name (full name)
stateOrProvinceName_default = $STATE
localityName               = Locality Name (eg, city)
localityName_default       = $LOCALITY
organizationName           = Organization Name (eg, company)
organizationName_default   = $ORG
commonName                 = Common Name (e.g. server FQDN or YOUR name)
commonName_default         = $IP
 
[ req_ext ]
subjectAltName = @alt_names
 
[ alt_names ]
IP.1 = $IP
EOF
 
function generate_CA () {
   echo "$SUBJECT_CA"
   openssl req -x509 -nodes -sha256 -newkey rsa:2048 -subj "$SUBJECT_CA"  -days 3650 -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 -config san.cnf
   openssl x509 -req -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650 -extensions req_ext -extfile san.cnf
}
 
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
}
 
 
generate_CA
generate_server

Platnost certifikátu jsem raději nastavil na 10 let. Po spuštění kódu budu mít ve více souborů. Nicméně pro MQTT server Mosquitto budu potřebovat:

Pro klienta (aby se připojil k MQTT serveru) mi bude stačit soubor:

Nastavení konfiguračního souboru Mosquitto

Podle docker file je konfigurační soubor umístěn v cestě ./volumes/mosquitto/config

Do této složky nahrajeme tedy vygenerované certifikáty:

Dbejme zejména práva k těmto souborům. Nastavit stejně, jako má soubor mosquitto.conf. Mosquitto v Dockeru musí mít možnost certifikáty číst.

Ve složce je také umístěný konfigurační soubor mosquitto.conf. Ten upravíme, aby povolil SSL a bude vypadat takto:

listener 8883

# persistence enabled for remembering retain flag across restarts
#
persistence true
persistence_location /mosquitto/data

# logging options:
#   enable one of the following (stdout = less wear on SD cards but
#   logs do not persist across restarts)
#log_dest file /mosquitto/log/mosquitto.log
log_dest stdout
log_timestamp_format %Y-%m-%dT%H:%M:%S
#log_type all

# password handling:
#   password_file commented-out allow_anonymous true =
#     open access
#   password_file commented-out allow_anonymous false =
#     no access
#   password_file activated     allow_anonymous true =
#     passwords omitted is permitted but
#     passwords provided must match pwfile
#   password_file activated     allow_anonymous false =
#     no access without passwords
#     passwords provided must match pwfile
#
password_file /mosquitto/pwfile/pwfile
allow_anonymous false

# certificates                       
cafile /mosquitto/config/ca.crt
certfile /mosquitto/config/server.crt
keyfile /mosquitto/config/server.key

#require_certificate true

# Uncomment to enable filters
#acl_file /mosquitto/config/filter.acl

Komentář ke konfiguračnímu souboru

Změna portu, na kterém Mosquitto běží:

listener 8883

Zapnutí souboru, ve kterém budou přihlašovací jména a hesla (vygenerujeme později) a zakázání anonymního připojení.

password_file /mosquitto/pwfile/pwfile
allow_anonymous false

Nastavení cest k certifikátům (cesta reflektuje, že Mosquitto poběží v Dockeru):

cafile /mosquitto/config/ca.crt
certfile /mosquitto/config/server.crt
keyfile /mosquitto/config/server.key

Nebudeme vyžadovat, aby se klient přihlašoval svým certifikátem - museli bychom totiž vygenerovat ještě certifikáty pro klienty a zároveň bychom mohli vypnout přihlašování jménem a heslem. Takže tuto položku mějme zakomentovanou nebo nastavenou na false.

#require_certificate true

Vygenerování uživatele a hesla do pwfile

Připojíme do kontejneru s Mosquitto a vytvořím uživatele s heslem:

docker exec -it mosquitto sh
mosquitto_passwd -c /mosquitto/pwfile/pwfile majordomus

Ověření funkčnosti

Pokud vše proběhlo správně, tak takto se připojíme na nějaký topic:

mosquitto_sub -u majordomus --pw 'passw0rd' -h 192.168.1.22 -p 8883 -v -t majordomus/detskypokojRS/ --cafile ca.crt

pro zapisování:

mosquitto_pub -u majordomus --pw 'passw0rd' -h 192.168.1.22 -p 8883 -v -t majordomus/detskypokojRS/ --cafile ca.crt