Il problema con MQTT senza TLS
MQTT è un protocollo di messaggistica leggero e publish/subscribe, nato per ambienti a banda limitata. Nella sua configurazione base, trasmette dati in chiaro su TCP — il che significa che chiunque sulla stessa rete può intercettare i messaggi, iniettare dati falsi, o impersonare un dispositivo.
In ambienti di test su rete locale privata, è accettabile. In produzione — soprattutto su reti Wi-Fi industriali o connessioni cellulari 4G — non lo è mai.
TLS vs mTLS: la differenza operativa
TLS unidirezionale: solo il server ha un certificato. Il client verifica l'identità del broker. Il broker non verifica il client — si fida del client_id e delle credenziali username/password. È il modello standard HTTPS.
mTLS (mutual TLS): sia il server che il client hanno un certificato. Il broker verifica il certificato del dispositivo prima di accettare la connessione. Non esistono credenziali username/password da gestire, rubare o dimenticare — l'identità è nel certificato. Per flotte IoT industriali, mTLS è lo standard che raccomandiamo.
Configurazione Mosquitto con mTLS
listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate true
use_identity_as_username true
# TLS 1.2 minimo, preferire 1.3
tls_version tlsv1.2
Con require_certificate true e use_identity_as_username true, il CN del certificato client diventa l'identità del dispositivo sul broker — usabile nelle ACL per limitare a quale topic ogni dispositivo può pubblicare o ricevere.
Gerarchia certificati per una flotta
Provisioning zero-touch per la flotta
Il provisioning zero-touch elimina la necessità di configurare manualmente ogni dispositivo prima del deployment. Il flusso:
- In fabbrica o in magazzino, ogni dispositivo viene programmato con: CA Root certificate (solo lettura), un certificato di bootstrap temporaneo, e l'indirizzo del provisioning server.
- Al primo avvio sul campo, il dispositivo si connette al provisioning server via TLS con il bootstrap cert, si autentica, e richiede il proprio certificato definitivo con il device_id definitivo.
- Il provisioning server genera e firma il certificato definitivo, lo consegna al dispositivo via connessione TLS sicura.
- Il dispositivo sostituisce il bootstrap cert con il definitivo, si disconnette dal provisioning server, e si connette al broker MQTT di produzione.
- Il bootstrap cert viene revocato nel provisioning server.
Questo pattern permette di mettere in campo cento dispositivi senza configurarli manualmente uno per uno — il provisioning avviene automaticamente al primo avvio.
OTA firmato: aggiornamenti sicuri del firmware
Un aggiornamento OTA non firmato è un vettore di attacco critico: chiunque riesca a raggiungere il dispositivo potrebbe installarvi firmware arbitrario. La firma ECDSA sul payload OTA risolve il problema.
- Il firmware build server firma il binario con la chiave privata ECDSA (mai esposta fuori dal build environment)
- La chiave pubblica corrispondente è nel firmware del dispositivo, in area protetta da scrittura
- Prima di flashare il nuovo firmware, il dispositivo verifica la firma — se la verifica fallisce, il download viene scartato e si riporta l'errore al backend
- Il rollback automatico è obbligatorio: se il nuovo firmware non completa il boot in 60 secondi, si torna al firmware precedente
Fleet monitoring con Last Will and Testament
MQTT ha una feature nativa per il monitoring della flotta: Last Will and Testament (LWT). Ogni dispositivo, quando si connette, dichiara un messaggio che il broker dovrà pubblicare su un topic specifico se la connessione cade in modo anomalo (senza DISCONNECT esplicito).
La struttura tipica:
- Topic:
fleet/{device_id}/status - LWT payload:
{"status": "offline", "ts": null}— pubblicato dal broker se il dispositivo si disconnette senza preavviso - Heartbeat ogni 30 secondi:
{"status": "online", "ts": 1751234567, "rssi": -68, "fw": "2.1.4"} - Il backend aggrega questi messaggi in una dashboard di stato flotta in tempo reale
Il problema più comune nei sistemi IoT in produzione è la scadenza dei certificati che non viene gestita. Implementare alert automatici 60 e 30 giorni prima della scadenza di ogni certificato — sia broker che dispositivi — e automatizzare il rinnovo prima che scadano. Un dispositivo con certificato scaduto è un dispositivo offline, senza possibilità di aggiornamento remoto.
ACL per isolare i dispositivi in flotta
Con mTLS e use_identity_as_username true, il CN del certificato è l'username del dispositivo. Le ACL di Mosquitto possono usarlo per limitare ogni dispositivo al proprio namespace di topic:
# Ogni dispositivo legge e scrive solo il proprio namespace
user BW-PLANT01-SENS042
topic readwrite fleet/BW-PLANT01-SENS042/#
topic read fleet/+/ota/command
Il dispositivo BW-PLANT01-SENS042 può pubblicare e ricevere solo sul proprio topic, e può ricevere (non pubblicare) i comandi OTA broadcast. Non può impersonare altri dispositivi né leggere i loro dati.