Sécurité MQTT

Configuration TLS MQTT : guide pratique du port 8883

Découvrez comment fonctionne réellement TLS avec MQTT, ce que les clients doivent vérifier et comment configurer des clients Python, Node.js, ESP32 et mosquitto pour une connexion chiffrée sur le port 8883.

Schéma de configuration TLS MQTT montrant un appareil IoT qui vérifie la chaîne de certificats du broker avant d'envoyer des messages chiffrés sur le port 8883
Essayez-le sur votre propre broker MQTTObtenez un broker MQTT privé et managé avec l’offre Free et partez d’exemples de code prêts à l’emploi.
Essayer gratuitement Exemples de code Aucune carte bancaire requise

Une configuration TLS MQTT correcte est ce qui fait passer MQTT d'un protocole en clair à un protocole que l'on peut utiliser sans risque sur Internet. Dans ce guide, vous verrez ce que le client vérifie réellement pendant le handshake, quels réglages comptent et comment configurer des clients Python, Node.js, ESP32 et en ligne de commande pour se connecter sur le port 8883. Chaque exemple se connecte à un vrai broker, vous pouvez donc tester au fil de la lecture.

Pourquoi MQTT a besoin de TLS

MQTT ne chiffre rien par lui-même. Sur le port 1883, le paquet CONNECT, nom d'utilisateur et mot de passe compris, circule en octets lisibles, tout comme chaque payload PUBLISH. N'importe qui sur le même Wi-Fi, un routeur compromis ou un FAI curieux peut lire et même modifier ce trafic. Pour un panorama plus large des menaces au-delà de l'écoute, lisez notre synthèse des bonnes pratiques de sécurité MQTT.

TLS (Transport Layer Security) enveloppe la connexion TCP dans un tunnel chiffré et authentifié avant tout échange d'octets MQTT. MQTT ne change pas du tout ; le broker écoute simplement sur un autre port, par convention 8883, et le client effectue d'abord un handshake TLS. Vous obtenez ainsi trois propriétés :

  • Confidentialité : le trafic est chiffré, les identifiants et les payloads ne peuvent donc pas être lus en transit.
  • Intégrité : les paquets altérés sont détectés et la connexion est coupée.
  • Authentification du serveur : le client prouve qu'il parle au vrai broker, et non à un imposteur.

La troisième propriété est celle que les configurations bâclées cassent le plus souvent, et c'est le sujet du reste de cet article.

Ce que le client vérifie pendant le handshake

Lorsque votre client ouvre une connexion TLS, le broker envoie son certificat ainsi que les éventuels certificats intermédiaires. Le client effectue alors ces contrôles :

  1. Chaîne de confiance : le certificat du serveur doit être signé par un intermédiaire, lui-même signé par une AC racine à laquelle le client fait déjà confiance (son magasin d'AC ou un fichier d'AC que vous fournissez).
  2. Période de validité : l'heure actuelle doit se situer entre les dates « not before » et « not after » du certificat. C'est pourquoi les appareils sans horloge temps réel ont besoin de NTP avant de se connecter.
  3. Correspondance du nom d'hôte : le nom d'hôte auquel vous vous êtes connecté doit figurer dans la liste Subject Alternative Name du certificat. Se connecter par adresse IP à un certificat émis pour un nom d'hôte échouera, et c'est normal.
  4. Possession de la clé : le handshake prouve que le broker détient la clé privée correspondant au certificat.

Deux détails connexes piègent souvent. D'abord, SNI (Server Name Indication) : le client envoie le nom d'hôte dans le handshake pour qu'un serveur hébergeant plusieurs noms puisse présenter le bon certificat. Les bibliothèques modernes envoient SNI automatiquement quand vous passez un nom d'hôte. Ensuite, la vérification du nom d'hôte est distincte de la vérification de la chaîne dans certaines bibliothèques. Un client peut accepter un certificat parfaitement valide pour le mauvais domaine si la vérification du nom d'hôte est désactivée, ce qui annule tout l'intérêt de TLS.

Les réglages de configuration TLS MQTT en un coup d'œil

Le tableau ci-dessous associe les transports courants aux ports et aux schémas d'URL. Les ports indiqués sont ceux utilisés par ConnectMQ et par la plupart des brokers qui suivent les conventions.

Transport Port Schéma d'URL Chiffré Client typique
MQTT sur TCP 1883 mqtt:// Non Tests en laboratoire uniquement
MQTT sur TLS 8883 mqtts:// Oui Appareils, backends, CLI
MQTT sur WebSocket 8083 ws:// Non Tests locaux dans le navigateur
MQTT sur WebSocket sécurisé 8084 wss:// (chemin /mqtt) Oui Navigateurs, réseaux restrictifs

Pour l'ancre de confiance, vous avez trois options :

  • Magasin d'AC du système : le choix par défaut pour Python, Node.js, Go et la plupart des clients de bureau ou serveur. Fonctionne lorsque le broker utilise un certificat reconnu publiquement.
  • Fichier d'AC explicite : vous passez un fichier PEM contenant l'AC racine. Indispensable pour les AC privées et pour la plupart des microcontrôleurs.
  • Épinglage : vous ne faites confiance qu'à une AC ou une clé précise. Plus robuste mais plus fragile ; consultez notre guide sur l'épinglage de certificat sur ESP32.

Le broker ConnectMQ utilise un certificat Let's Encrypt, qui remonte à la racine ISRG Root X1 présente dans tous les systèmes d'exploitation courants ainsi que dans les bundles d'AC de Python (via certifi) et de Node.js. Sur les postes de travail et les serveurs, vous n'avez normalement besoin de fournir aucun fichier d'AC.

Tester la connexion avant d'écrire du code

Avant de toucher au code applicatif, vérifiez le chemin réseau et le certificat avec OpenSSL :

openssl s_client -connect broker.connectmq.com:8883 -servername broker.connectmq.com -brief </dev/null

Cherchez Verification: OK et la version de protocole négociée. Si vous voyez ici une erreur de vérification, aucune bibliothèque cliente ne réussira non plus ; notre article sur la résolution des échecs de handshake TLS MQTT passe en revue chaque erreur.

Essayez ensuite un véritable aller-retour MQTT avec les clients mosquitto. Ouvrez deux terminaux et choisissez un préfixe de topic unique :

# Terminal 1 : s'abonner via TLS avec le répertoire d'AC du système (Linux/macOS)
mosquitto_sub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
  -i tls-sub-7f3a -t "connectmq/demo/7f3a/#" -v

# Terminal 2 : publier via TLS
mosquitto_pub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
  -i tls-pub-7f3a -t "connectmq/demo/7f3a/hello" -m "encrypted hello"

Sous Windows, mosquitto ne sait pas lire le magasin du système : téléchargez le PEM ISRG Root X1 depuis Let's Encrypt et passez-le avec --cafile isrgrootx1.pem. Le serveur MQTT public gratuit, réservé aux tests et aux prototypes, accepte les connexions anonymes, ces commandes fonctionnent donc immédiatement. N'oubliez pas que l'espace public est lisible par tous : n'y envoyez jamais de données réelles.

Configuration du client Python (paho-mqtt 2.x)

Avec paho-mqtt 2.x, tls_set() sans argument charge les certificats d'AC par défaut du système, active la vérification du nom d'hôte et exige un certificat valide. C'est exactement ce que vous voulez.

import ssl
import time
import paho.mqtt.client as mqtt

BROKER = "broker.connectmq.com"
PORT = 8883
TOPIC = "connectmq/demo/7f3a/python"

def on_connect(client, userdata, flags, reason_code, properties):
    print("Connected:", reason_code)
    client.subscribe(TOPIC, qos=1)

def on_message(client, userdata, msg):
    print(f"{msg.topic}: {msg.payload.decode()}")

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="py-tls-7f3a")
client.on_connect = on_connect
client.on_message = on_message

# Magasin d'AC du système, certificat exigé, nom d'hôte vérifié,
# version TLS la plus récente prise en charge des deux côtés
client.tls_set(cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLS_CLIENT)

# Pour un broker ConnectMQ privé, ajoutez les identifiants du portail :
# client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")

client.connect(BROKER, PORT, keepalive=60)
client.loop_start()
time.sleep(1)
client.publish(TOPIC, "hello over TLS", qos=1)
time.sleep(2)
client.loop_stop()
client.disconnect()

Si le magasin d'AC de votre plateforme est cassé ou obsolète, passez plutôt ca_certs=certifi.where(). Ne « corrigez » jamais une erreur avec tls_insecure_set(True) : cela désactive la vérification du nom d'hôte et supprime silencieusement l'authentification du serveur. Pour les erreurs Python courantes, voir SSL CERTIFICATE_VERIFY_FAILED avec MQTT.

Configuration du client Node.js (MQTT.js v5)

MQTT.js utilise la pile TLS intégrée de Node, qui valide par rapport à la liste d'AC Mozilla embarquée dans Node et vérifie le nom d'hôte par défaut.

const mqtt = require("mqtt");

const client = mqtt.connect("mqtts://broker.connectmq.com:8883", {
  clientId: "node-tls-7f3a",
  protocolVersion: 5,
  // Pour un broker privé :
  // username: "YOUR_USERNAME",
  // password: "YOUR_PASSWORD",
  rejectUnauthorized: true, // valeur par défaut ; ne jamais mettre false en production
});

const topic = "connectmq/demo/7f3a/node";

client.on("connect", () => {
  console.log("Connected over TLS");
  client.subscribe(topic, { qos: 1 }, () => {
    client.publish(topic, "hello from Node.js", { qos: 1 });
  });
});

client.on("message", (t, payload) => {
  console.log(`${t}: ${payload.toString()}`);
  client.end();
});

client.on("error", (err) => console.error("MQTT error:", err.message));

Si vous devez faire confiance à une AC privée, ajoutez ca: fs.readFileSync("ca.pem") aux options. Dans le navigateur, utilisez wss://broker.connectmq.com:8084/mqtt ; le navigateur se charge de la validation du certificat.

Configuration du client ESP32

Les microcontrôleurs n'ont pas de magasin d'AC de système d'exploitation : vous embarquez donc le certificat racine. Avec le core Arduino, WiFiClientSecure associé à PubSubClient donne ceci :

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <time.h>

const char* WIFI_SSID = "your-ssid";
const char* WIFI_PASS = "your-password";
const char* BROKER = "broker.connectmq.com";

// Collez ici le PEM complet ISRG Root X1 provenant de letsencrypt.org
static const char ROOT_CA[] = R"EOF(
-----BEGIN CERTIFICATE-----
...ISRG Root X1 certificate body...
-----END CERTIFICATE-----
)EOF";

WiFiClientSecure net;
PubSubClient mqtt(net);

void setup() {
  Serial.begin(115200);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  while (WiFi.status() != WL_CONNECTED) delay(250);

  // Une horloge valide est nécessaire pour vérifier les dates du certificat
  configTime(0, 0, "pool.ntp.org");
  while (time(nullptr) < 1700000000) delay(250);

  net.setCACert(ROOT_CA);
  mqtt.setServer(BROKER, 8883);
}

void loop() {
  if (!mqtt.connected()) {
    if (mqtt.connect("esp32-tls-7f3a")) {
      mqtt.publish("connectmq/demo/7f3a/esp32", "hello over TLS");
    } else {
      Serial.printf("MQTT connect failed, state=%d\n", mqtt.state());
      delay(5000);
    }
  }
  mqtt.loop();
}

Pour un broker privé, utilisez mqtt.connect("YOUR_CLIENT_ID", "YOUR_USERNAME", "YOUR_PASSWORD"). Le tutoriel MQTT sur SSL avec l'ESP32 approfondit l'utilisation mémoire et le comportement de reconnexion.

Checklist de production

  1. Utilisez le port 8883 (ou 8084 pour les navigateurs) partout en dehors du laboratoire ; désactivez ou filtrez le port 1883 en clair pour les clients de production.
  2. Vérifiez la chaîne de certificats par rapport à une racine de confiance, et non en « acceptant tout ».
  3. Gardez la vérification du nom d'hôte activée et connectez-vous toujours par nom d'hôte, jamais par IP.
  4. Synchronisez l'heure (NTP) sur les appareils embarqués avant le handshake.
  5. Faites confiance à l'AC racine, pas au certificat feuille, car les certificats feuilles changent souvent.
  6. N'envoyez les identifiants que via TLS et stockez-les en dehors du code source.
  7. Anticipez les changements d'AC : rendez la racine de confiance actualisable à distance (OTA).
  8. Surveillez les connexions échouées ; des échecs TLS ou d'authentification répétés signalent généralement une mauvaise configuration ou une attaque.

Laissez un broker MQTT managé gérer le côté serveur

Le côté broker de TLS est la moitié la moins amusante : obtenir des certificats, les renouveler avant expiration, choisir les versions de protocole et les suites de chiffrement, et redémarrer les listeners sans déconnecter les clients. Un broker MQTT managé supprime ce travail. ConnectMQ termine TLS sur le port 8883 et le WebSocket sécurisé sur le port 8084 avec des certificats Let's Encrypt renouvelés automatiquement, de sorte que vos clients n'ont besoin que de la configuration standard présentée ci-dessus. Si vous comparez des options d'hébergement, notre guide du broker MQTT cloud explique les compromis.

Démarrer avec ConnectMQ

Créez un compte gratuit sur app.connectmq.com, choisissez l'offre Serverless (Free) sans carte bancaire, créez un broker et copiez le nom d'utilisateur, le mot de passe et le client ID générés. Pointez n'importe lequel des clients ci-dessus vers le port 8883 avec ces identifiants, et vous disposez en quelques minutes d'une connexion MQTT chiffrée et authentifiée.

Questions fréquentes

MQTT sur TLS est-il plus lent que MQTT en clair ?

Le handshake ajoute des allers-retours et du travail CPU à l'ouverture d'une connexion, mais les connexions MQTT durent longtemps, donc le surcoût en régime établi est faible. Gardez les connexions ouvertes et réutilisez les sessions au lieu de vous reconnecter pour chaque message.

Faut-il un certificat client pour utiliser MQTT sur TLS ?

Non. La plupart des déploiements utilisent TLS côté serveur avec un nom d'utilisateur et un mot de passe envoyés dans le tunnel chiffré. Les certificats clients (TLS mutuel) sont une option supplémentaire que prennent en charge certains brokers auto-hébergés.

De quel certificat d'AC ai-je besoin pour ConnectMQ ?

Le certificat du broker est émis par Let's Encrypt et remonte à ISRG Root X1. Les clients de bureau et serveur lui font déjà confiance ; les appareils embarqués doivent intégrer ce PEM racine.

Pourquoi mon client échoue-t-il quand je me connecte par adresse IP ?

Le certificat liste des noms d'hôte, pas des adresses IP, donc la vérification du nom d'hôte échoue. Connectez-vous toujours avec broker.connectmq.com ou le nom d'hôte de votre broker.

Articles liés

Rotation des identifiants MQTT sans interruption de service

Une stratégie à double identifiant, étape par étape, pour la rotation des noms d'utilisateur et mots de passe MQTT sur un parc : préparer le nouvel identifiant, basculer avec repli, vérifier, puis seulement révoquer l'ancien.

8 min de lecture

Tous les articles →

Votre broker MQTT privé, à quelques clics

Créez un compte, récupérez les identifiants de votre broker et connectez votre premier appareil — aucun serveur à installer, mettre à jour ou dimensionner.