Skip to main content

MQTT-BaCo - Installation MQTT

Debian 13: MQTT (Mosquitto) schnell & sehr sicher mit Zertifikats-Auth (mTLS) + TLS 1.3

Ziel: Ein Mosquitto-Broker, der nur verschlüsselte Verbindungen annimmt, bei denen sich auch der Client per Zertifikat ausweist (mutual TLS / mTLS). Zusätzlich: saubere Rechte, minimale Angriffsfläche, Firewall, und (optional) Systemd-Hardening.
Wichtig zu “500 Jahre Zertifikate”:
Ein Zertifikat, das 500 Jahre gültig ist, ist nicht “super sicher”. Nicht wegen Mathematik allein, sondern wegen Praxis: Schlüssel können kompromittiert werden, Algorithmen werden über Jahrzehnte schwächer, Geräte werden ersetzt, und manche Stacks/Policies mögen extrem lange Laufzeiten nicht.

Empfehlung: Root-CA sehr lang (ja, wenn du willst 500 Jahre), aber Server- und Client-Zertifikate kurz (z.B. 1–2 Jahre) und rotieren. Das ist der übliche “maximal sicher”-Ansatz. Unten ist beides dokumentiert.

1. Architektur-Entscheidung

  • Broker: Eclipse Mosquitto (leichtgewichtig, schnell, standardnah)
  • Transport: TLS 1.3 (MQTTS auf Port 8883)
  • Authentifizierung: Client-Zertifikate (require_certificate)
  • Autorisierung: ACL-Datei, Username aus Zertifikat (CN) via use_identity_as_username

2. Pakete installieren (Debian 13)

sudo apt update
sudo apt install -y mosquitto mosquitto-clients openssl ca-certificates
Mosquitto läuft als Systemdienst. Wir konfigurieren ihn so, dass er nur noch einen TLS-Listener bereitstellt.

3. Verzeichnisstruktur & Rechte

Wir legen ein PKI-Verzeichnis an, in dem der Broker seine Server-Zertifikate liest. Die Root-CA-Schlüssel sollten im Idealfall offline bleiben.

# PKI-Verzeichnis: lesbar für Gruppe "mosquitto", private Keys später restriktiv
sudo install -d -m 0750 -o root -g mosquitto /etc/mosquitto/pki

# Optional: eigenes Arbeitsverzeichnis für CA/Signing (nicht auf dem Broker lassen, wenn "super sicher")
sudo install -d -m 0700 -o root -g root /root/mqtt-pki

4. PKI erstellen (Root-CA + Server + Client)

4.1 Root-CA erstellen (Beispiel: 500 Jahre)

Wir nutzen ECDSA (P-384) für die Root-CA. Das ist effizient und stark.
Hinweis zu “500 Jahre”: Wenn du das am 24.12.2025 erstellst, entsprechen 500 Jahre 182621 Tagen.

cd /root/mqtt-pki
umask 077

# Root-CA Private Key
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:secp384r1 -out ca.key

# Root-CA Zertifikat (selbstsigniert)
# 500 Jahre ab 24.12.2025: -days 182621
openssl req -x509 -new -sha384 -days 182621 \
  -key ca.key -out ca.crt \
  -subj "/CN=MQTT Root CA/O=YourOrg/OU=IoT/C=DE" \
  -addext "basicConstraints=critical,CA:TRUE,pathlen:1" \
  -addext "keyUsage=critical,keyCertSign,cRLSign" \
  -addext "subjectKeyIdentifier=hash"
Super-sicher-Variante: Kopiere ca.key auf ein Offline-System (USB, Tresor, was auch immer Menschen so machen) und lasse auf dem Broker nur ca.crt.

4.2 Server-Zertifikat erstellen (TLS für den Broker)

Der Broker braucht ein Server-Zertifikat mit korrekten SANs (DNS/IP), damit Clients den Hostnamen prüfen können.

cd /root/mqtt-pki
umask 077

# Server Key (P-256 ist schneller, i.d.R. sehr kompatibel)
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -out server.key

# CSR mit SAN (DNS + optional IP) - passe mqtt.example.lan und IP an
openssl req -new -sha256 \
  -key server.key -out server.csr \
  -subj "/CN=mqtt.example.lan/O=YourOrg/OU=IoT/C=DE" \
  -addext "subjectAltName=DNS:mqtt.example.lan,IP:192.168.1.10"

# Extensions für Server-Zertifikat
cat > server.ext <<'EOF'
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature,keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName=DNS:mqtt.example.lan,IP:192.168.1.10
EOF

# Server-Zertifikat signieren
# Empfohlen: kurz (z.B. 825 Tage ~ 2,25 Jahre) statt 500 Jahre.
openssl x509 -req -sha256 -days 825 \
  -in server.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out server.crt -extfile server.ext
Wenn du wirklich “500 Jahre” auch für das Server-Zertifikat willst, ersetze -days 825 durch -days 182621. Das ist aber das Gegenteil von “Keys rotieren” und damit nicht “maximal sicher”.

4.3 Client-Zertifikat erstellen (mTLS-Clientauth)

Der Client authentifiziert sich per Zertifikat. Der Broker kann den CN als “Username” verwenden (für ACLs).

cd /root/mqtt-pki
umask 077

# Client Key
openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:prime256v1 -out client-sensor01.key

# CSR (CN entspricht später dem Username, wenn use_identity_as_username=true)
openssl req -new -sha256 \
  -key client-sensor01.key -out client-sensor01.csr \
  -subj "/CN=sensor01/O=YourOrg/OU=IoT/C=DE"

# Extensions für Client-Zertifikat
cat > client.ext <<'EOF'
basicConstraints=critical,CA:FALSE
keyUsage=critical,digitalSignature
extendedKeyUsage=clientAuth
EOF

# Client-Zertifikat signieren (empfohlen kurz, z.B. 365 Tage)
openssl x509 -req -sha256 -days 365 \
  -in client-sensor01.csr \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -out client-sensor01.crt -extfile client.ext

5. Zertifikate zum Broker installieren

Auf dem Broker brauchen wir:

  • ca.crt (die CA, der der Broker vertraut)
  • server.crt + server.key (Server-Identität)
# Kopieren
sudo cp /root/mqtt-pki/ca.crt /etc/mosquitto/pki/
sudo cp /root/mqtt-pki/server.crt /etc/mosquitto/pki/
sudo cp /root/mqtt-pki/server.key /etc/mosquitto/pki/

# Rechte: private Keys nur für mosquitto lesbar
sudo chown root:mosquitto /etc/mosquitto/pki/ca.crt /etc/mosquitto/pki/server.crt
sudo chown mosquitto:mosquitto /etc/mosquitto/pki/server.key
sudo chmod 0640 /etc/mosquitto/pki/ca.crt /etc/mosquitto/pki/server.crt
sudo chmod 0400 /etc/mosquitto/pki/server.key
Wichtig: Lass ca.key (Root-Private-Key) nicht auf dem Broker, wenn du es ernst meinst.

6. Mosquitto sicher konfigurieren (nur TLS + mTLS)

6.1 Hauptkonfiguration prüfen

In Debian liegt die Hauptdatei typischerweise unter /etc/mosquitto/mosquitto.conf und inkludiert Zusatzdateien aus /etc/mosquitto/conf.d/. Stelle sicher, dass dort ein include_dir /etc/mosquitto/conf.d existiert.

6.2 TLS/mTLS Listener anlegen

Neue Datei: /etc/mosquitto/conf.d/secure-tls.conf

# /etc/mosquitto/conf.d/secure-tls.conf

# Einstellungen pro Listener getrennt behandeln
per_listener_settings true

# Optional: $SYS Infos reduzieren (weniger Fingerprinting)
sys_interval 0

# TLS Listener (MQTTS)
listener 8883
protocol mqtt

# TLS 1.3 only (Minimum ist tlsv1.3)
tls_version tlsv1.3

# Server-Zertifikat + Key
cafile /etc/mosquitto/pki/ca.crt
certfile /etc/mosquitto/pki/server.crt
keyfile /etc/mosquitto/pki/server.key

# TLS 1.3 Ciphersuites (Defaults sind okay, explizit ist klarer)
ciphers_tls1.3 TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256

# mTLS: Client muss Zertifikat liefern
require_certificate true

# CN aus Client-Zertifikat als Username verwenden (für ACLs)
use_identity_as_username true

# Keine anonymen Clients
allow_anonymous false

# Autorisierung über ACL-Datei
acl_file /etc/mosquitto/aclfile

# Optional: Zertifikate sperren (CRL)
# crlfile /etc/mosquitto/pki/ca.crl

6.3 ACL-Datei erstellen

Datei: /etc/mosquitto/aclfile

# Standard: alles verbieten (explizit)
topic deny #

# Pattern-ACL: Jeder Client darf nur in seinen eigenen Namensraum
# %u ist der Username, der hier aus dem Zertifikats-CN kommt (use_identity_as_username)
pattern readwrite clients/%u/#

# Beispiel: Wenn du willst, dass jeder auch Status lesen kann:
# topic read clients/+/status
sudo chown root:mosquitto /etc/mosquitto/aclfile
sudo chmod 0640 /etc/mosquitto/aclfile

7. Dienst starten & prüfen

sudo systemctl enable --now mosquitto
sudo systemctl status mosquitto

Port prüfen (ohne “rumgrep’en”):

ss -ltnp | less
# Suche im less nach ":8883"

8. Firewall (nftables) minimal hart machen

Debian nutzt nftables. Ziel: Nur Port 8883 erlauben, idealerweise nur aus deinen Netzen/VPNs.

Datei: /etc/nftables.conf (in der input-Chain ergänzen)

# Beispiel (IPv4): Erlaube 8883 nur aus LAN 192.168.1.0/24
tcp dport 8883 ip saddr 192.168.1.0/24 accept

# Optional (IPv6) analog:
# tcp dport 8883 ip6 saddr fd00:1234:abcd::/64 accept
sudo systemctl enable --now nftables
sudo nft list ruleset | less

9. Systemd-Hardening (optional, aber sinnvoll)

Drop-in erstellen: /etc/systemd/system/mosquitto.service.d/hardening.conf

sudo install -d -m 0755 /etc/systemd/system/mosquitto.service.d

sudo tee /etc/systemd/system/mosquitto.service.d/hardening.conf >/dev/null <<'EOF'
[Service]
NoNewPrivileges=true
PrivateTmp=true
ProtectHome=true
ProtectSystem=strict
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
LockPersonality=true
RestrictNamespaces=true
MemoryDenyWriteExecute=true
UMask=0077

# Mosquitto braucht Schreibzugriff für Persistence/Logs (falls aktiviert)
ReadWritePaths=/var/lib/mosquitto /var/log/mosquitto
EOF

sudo systemctl daemon-reload
sudo systemctl restart mosquitto
Wenn du Persistence komplett deaktivierst (und Logs nur über journald laufen lässt), kannst du ReadWritePaths weiter einschränken.

10. Funktionstest mit mosquitto_pub / mosquitto_sub (mTLS)

Client-Dateien (auf dem Client-System):

  • ca.crt
  • client-sensor01.crt
  • client-sensor01.key
# Subscribe (TLS 1.3, mTLS)
mosquitto_sub -h mqtt.example.lan -p 8883 \
  --tls-version tlsv1.3 \
  --cafile ca.crt \
  --cert client-sensor01.crt \
  --key client-sensor01.key \
  -t 'clients/sensor01/#' -v
# Publish
mosquitto_pub -h mqtt.example.lan -p 8883 \
  --tls-version tlsv1.3 \
  --cafile ca.crt \
  --cert client-sensor01.crt \
  --key client-sensor01.key \
  -t 'clients/sensor01/test' -m 'hello mTLS'
Niemals --insecure benutzen, wenn du “super sicher” sagst. Das deaktiviert Zertifikatsprüfung.

11. Zertifikate rotieren (empfohlen) & Reload ohne Downtime

Mosquitto kann Server-Zertifikat und Key per SIGHUP neu laden. Das ist perfekt für Rotation.
# Neue server.crt/server.key nach /etc/mosquitto/pki/ kopieren (atomar ersetzen)
# dann:
sudo systemctl kill -s HUP mosquitto

12. Optional: Zertifikate sperren (CRL)

Mosquitto unterstützt eine CRL-Datei. Damit kannst du kompromittierte Client-Zertifikate “abschalten”, ohne die CA zu wechseln. Das erfordert aber, dass du deine CA “richtig” mit Datenbank (index.txt) betreibst.

# In /etc/mosquitto/conf.d/secure-tls.conf aktivieren:
# crlfile /etc/mosquitto/pki/ca.crl
Für eine saubere CRL-Pipeline lohnt sich ein kleines CA-Setup (openssl ca) oder ein dediziertes PKI-Tool.

13. Kurz-Checkliste “wirklich sicher”

  • Nur Port 8883 offen, ideal nur aus VPN/LAN.
  • TLS 1.3 only, mTLS Pflicht.
  • CA Private Key offline.
  • Client-Zerts kurzlebig + Rotation.
  • ACLs restriktiv, Default deny.
  • Regelmäßige Security Updates (unattended-upgrades, wenn passend).