MQTT con TLS e gestione flotta IoT: sicurezza end-to-end per dispositivi embedded

Un dispositivo IoT che comunica senza TLS espone ogni dato trasmesso alla rete. Su una flotta di cento dispositivi industriali, la superficie di attacco è enorme. Questo articolo copre l'architettura di sicurezza completa: TLS e mTLS su MQTT, gestione del ciclo di vita dei certificati, provisioning zero-touch e aggiornamenti OTA firmati.

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

# /etc/mosquitto/conf.d/tls.conf
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

CA
CA Root — offline, archiviata in luogo sicuro. Firma solo i certificati intermedi. Non viene mai esposta online.
CA2
CA Intermedia — firma i certificati dispositivo e il certificato del broker. Può essere revocata senza compromettere la Root CA.
SRV
Certificato broker — CN = hostname del broker MQTT. Rinnovato annualmente. Cambio trasparente ai dispositivi se la CA intermedia non cambia.
DEV
Certificato dispositivo — CN = device_id univoco (es. BW-PLANT01-SENS042). Scadenza 2 anni. Rinnovato via OTA prima della scadenza.

Provisioning zero-touch per la flotta

Il provisioning zero-touch elimina la necessità di configurare manualmente ogni dispositivo prima del deployment. Il flusso:

  1. 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.
  2. 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.
  3. Il provisioning server genera e firma il certificato definitivo, lo consegna al dispositivo via connessione TLS sicura.
  4. Il dispositivo sostituisce il bootstrap cert con il definitivo, si disconnette dal provisioning server, e si connette al broker MQTT di produzione.
  5. 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
Ciclo di vita dei certificati

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:

# /etc/mosquitto/aclfile
# 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.