La journalisation d'audit MQTT consiste à enregistrer qui s'est connecté, qui a échoué à se connecter, ce qui a changé dans la configuration et quelles actions ont compté, afin de pouvoir enquêter sur les incidents et démontrer aux auditeurs que les contrôles fonctionnent. Ce guide explique quels événements enregistrer, quels champs chaque entrée doit contenir, combien de temps les conserver et comment assembler un pipeline de journaux autour d'un broker MQTT managé. Il porte sur les événements de sécurité et d'exploitation, pas sur le stockage de chaque payload.
Journaux d'audit et données de messages
Il est utile de distinguer trois types d'enregistrements :
- Journaux d'audit : événements pertinents pour la sécurité, comme les connexions, les échecs de connexion, les modifications d'identifiants et les actions d'administration. Petits, structurés, conservés pendant une durée définie.
- Journaux d'exploitation : coupures de connexion, erreurs, dépassements de quota et signaux de performance servant à maintenir le système en marche.
- Historique des messages : la télémétrie elle-même, généralement stockée dans une base de séries temporelles ou un historian pour l'analyse.
Les mélanger pose problème. Les archives de payloads sont volumineuses, peuvent contenir des données personnelles ou confidentielles, et noient les événements de sécurité dont vous avez réellement besoin lors d'une enquête. Gardez des journaux d'audit légers et ciblés.
Quoi enregistrer
| Événement | Pourquoi c'est important | Champs clés |
|---|---|---|
| Connexion réussie | Montre quelle identité était active, quand et d'où | Horodatage (UTC), client ID, nom d'utilisateur, IP source, version du protocole, TLS oui/non |
| Échec d'authentification | Détecte les tentatives de devinette, les identifiants divulgués et les appareils mal configurés | Horodatage, nom d'utilisateur tenté, client ID, IP source, code de raison |
| Déconnexion | Explique les pannes et les prises de contrôle de session | Horodatage, client ID, code de raison, durée de session |
| Refus d'autorisation | Montre les clients qui tentent d'atteindre des topics interdits | Client ID, filtre de topic, action, code de raison |
| Événement de quota ou de limite de débit | Identifie les appareils incontrôlés et les abus | Client ID, type de limite, code de raison (par exemple 0x97) |
| Blocages d'IP | Confirme que les défenses automatiques fonctionnent | IP source, déclencheur, durée |
| Cycle de vie des identifiants | Prouve que le provisionnement, la rotation et la révocation ont lieu | Identité, action, acteur, horodatage |
| Modifications d'administration | Qui a modifié des brokers, des offres, des règles d'alerte ou des utilisateurs | Acteur, action, objet, ancienne et nouvelle valeur |
| Messages de commande | Pour les topics de contrôle, qui a envoyé quelle commande | Topic, identité de l'émetteur, commande, résultat |
La dernière ligne mérite qu'on s'y attarde. La télémétrie a rarement besoin d'une piste d'audit, mais les commandes qui changent l'état d'un équipement en ont souvent besoin. Enregistrez la commande, l'identité émettrice et l'acquittement, pas seulement le fait qu'un message est passé.
Les champs nécessaires à chaque entrée
Quelle que soit la source, normalisez les entrées selon une structure cohérente :
{
"ts": "2026-10-16T09:41:07.312Z",
"event": "client.disconnected",
"source": "connectmq-monitor",
"client_id": "gw-plant1-01",
"username": "gw-plant1-01",
"ip": "203.0.113.24",
"reason_code": "0x8E",
"details": { "previous_state": "connected" }
}
Utilisez des horodatages UTC à la milliseconde, gardez des noms d'événements stables et ne journalisez jamais de mots de passe, de jetons ni de payloads complets contenant des données personnelles.
D'où viennent les événements
Dans une installation auto-hébergée, les fichiers journaux du broker sont la source principale. Mosquitto, par exemple, journalise les connexions, les déconnexions et les échecs d'authentification lorsque les options log_type concernées sont activées, et vous expédiez ces fichiers vers un système central.
Avec un broker MQTT managé, vous combinez ce que la plateforme expose avec ce que vos propres clients et applications enregistrent. Il est important d'être précis sur ce qui relève de chacun. Sur ConnectMQ, les sources visibles sont :
- Topics d'état de connexion :
$SYS/broker/connection/{clientId}/stateindique si un client est connecté ; vous pouvez vous y abonner et l'enregistrer. - Tableau de bord du portail et vue des appareils : visibilité opérationnelle sur les clients connectés et les topics.
- Règles d'alerte à seuil et journal des alertes : un historique des moments où les données ont franchi les seuils que vous avez définis.
- Codes de raison MQTT 5 : renvoyés aux clients en cas de refus, dont 0x97 pour un quota dépassé, que vos clients peuvent journaliser.
- Protections de la plateforme : la protection contre l'inondation et le blocage d'IP après des échecs de connexion répétés s'exécutent côté broker.
Ce sont des signaux d'exploitation, pas une piste d'audit de conformité. Pour une piste d'audit complète, enregistrez les événements côté client et côté application dans un stockage que vous maîtrisez, et documentez les procédures d'administration dans vos propres registres de modifications. C'est un partage de responsabilité courant avec les services managés ; le guide du broker MQTT managé cité plus haut montre comment les responsabilités se répartissent.
Construire un pipeline d'audit simple
Un petit service qui s'abonne aux topics d'état de connexion et écrit des lignes structurées dans un fichier ou un agent d'expédition de journaux vous donne un historique de connexion fiable. Cet exemple utilise paho-mqtt 2.x et surveille une liste connue de client IDs :
import json
import logging
from datetime import datetime, timezone
import paho.mqtt.client as mqtt
WATCHED_CLIENTS = ["gw-plant1-01", "gw-plant1-02", "dashboard-01"]
logging.basicConfig(filename="mqtt-audit.jsonl", level=logging.INFO, format="%(message)s")
def audit(event, **fields):
entry = {"ts": datetime.now(timezone.utc).isoformat(timespec="milliseconds"),
"event": event, "source": "connectmq-monitor", **fields}
logging.info(json.dumps(entry))
def on_connect(client, userdata, flags, reason_code, properties):
audit("monitor.connected", reason_code=str(reason_code))
for cid in WATCHED_CLIENTS:
client.subscribe(f"$SYS/broker/connection/{cid}/state", qos=1)
def on_message(client, userdata, msg):
cid = msg.topic.split("/")[3]
audit("client.state", client_id=cid, state=msg.payload.decode("utf-8", "replace"))
def on_disconnect(client, userdata, flags, reason_code, properties):
audit("monitor.disconnected", reason_code=str(reason_code))
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="YOUR_CLIENT_ID",
protocol=mqtt.MQTTv5)
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set()
client.on_connect = on_connect
client.on_message = on_message
client.on_disconnect = on_disconnect
client.reconnect_delay_set(min_delay=1, max_delay=60)
client.connect("YOUR_BROKER_HOST", 8883, keepalive=60)
client.loop_forever()
Le fichier de lignes JSON peut être collecté par n'importe quel agent d'expédition et transmis au SIEM ou à la plateforme de journaux que votre organisation utilise déjà. Notez que le moniteur journalise aussi ses propres déconnexions : les trous dans votre piste d'audit sont eux-mêmes des événements importants.
Journaliser aussi côté client
Les appareils et les applications voient des événements que le broker ne vous signale jamais, comme leurs propres tentatives de connexion échouées et les publications refusées. Faites journaliser par chaque client :
- Les tentatives de connexion avec le code de raison du résultat.
- Les abonnements refusés (codes SUBACK de 0x80 et plus).
- Les publications refusées, en particulier 0x97 quota dépassé et 0x87 non autorisé.
- Les commandes reçues, les résultats de validation et les actions entreprises.
- Les événements de rotation des identifiants.
Pour les passerelles en usine, expédiez ces journaux vers un collecteur central plutôt que de les garder uniquement sur l'appareil. Le guide de la sécurité OT avec MQTT explique comment le faire sans ouvrir de ports entrants.
Conservation, intégrité et confidentialité
Les journaux d'audit ne sont utiles que s'ils sont complets, dignes de confiance et légalement conservables.
- Conservation : fixez une durée selon vos besoins réglementaires, contractuels et d'enquête, et documentez-la. Supprimez les journaux à l'expiration de cette durée.
- Intégrité : écrivez dans un stockage en ajout seul ou un système qui restreint la suppression, et limitez qui peut modifier les journaux.
- Synchronisation de l'heure : utilisez NTP sur chaque hôte qui journalise ; des horloges désynchronisées rendent les chronologies inutilisables.
- Confidentialité : les adresses IP et les noms d'utilisateur peuvent être des données personnelles. Collectez ce dont vous avez besoin, protégez l'accès et appliquez votre politique de confidentialité.
- Accès : journalisez l'accès aux journaux eux-mêmes.
Transformer les journaux en alertes
Des journaux que personne ne lit n'améliorent pas la sécurité. Commencez par quelques alertes à forte valeur :
- De nombreux échecs d'authentification pour un même nom d'utilisateur ou depuis une même IP sur une courte période.
- Un appareil connu qui se connecte depuis un réseau inattendu.
- Une passerelle déconnectée plus longtemps que sa durée de panne maximale prévue.
- Des refus répétés pour quota ou limite de débit venant d'un même client.
- Toute commande sur un topic de contrôle en dehors des heures ouvrées ou depuis une identité inattendue.
Ces alertes rejoignent étroitement les idées de vérification continue du zero trust pour la messagerie IoT et les attentes de surveillance des événements de référentiels comme l'IEC 62443.
Checklist de journalisation d'audit
- Liste définie des événements de sécurité et responsables pour chaque source.
- Structure JSON cohérente avec horodatages UTC.
- État de connexion surveillé pour chaque client critique.
- Journalisation côté client des codes de raison, des refus et des commandes.
- Modifications d'administration enregistrées dans votre processus de gestion des changements.
- Stockage central, à accès contrôlé, avec une durée de conservation documentée.
- Alertes sur les échecs de connexion, les déconnexions inattendues et les anomalies de débit.
- Vérification régulière que le pipeline lui-même fonctionne.
Commencez à surveiller votre broker avec ConnectMQ
Créez un broker privé avec l'offre gratuite Serverless sur app.connectmq.com (sans carte bancaire), connectez le moniteur ci-dessus avec vos identifiants générés et regardez apparaître les événements de connexion. Si vous voulez d'abord expérimenter sans identifiants, essayez le serveur MQTT public gratuit, réservé aux tests et aux prototypes, avec des données de test. L'article sur les bonnes pratiques de sécurité MQTT présente les contrôles que vos journaux doivent vérifier.
Questions fréquentes
Faut-il journaliser chaque message MQTT pour l'audit ?
Généralement non. Journalisez les événements de sécurité et d'administration, ainsi que les commandes sur les topics de contrôle. Stockez la télémétrie séparément dans un historian ou une base de données si vous en avez besoin pour l'analyse.
Quel est l'événement MQTT le plus important à auditer ?
Les tentatives d'authentification échouées, car elles révèlent tôt les tentatives de devinette, les identifiants divulgués ou expirés et les appareils mal configurés.
Combien de temps conserver les journaux d'audit MQTT ?
Il n'y a pas de réponse unique. La durée de conservation dépend de vos exigences réglementaires, contractuelles et d'enquête : définissez une durée, documentez-la et appliquez la suppression à son terme.
Peut-on obtenir les événements de connexion d'un broker MQTT managé ?
Sur ConnectMQ, vous pouvez vous abonner à $SYS/broker/connection/{clientId}/state pour l'état de connexion et le combiner avec les journaux côté client des codes de raison afin de construire votre propre historique de connexion.



