1190  MQTT Security

1190.1 Learning Objectives

By the end of this chapter, you will be able to:

  • Implement Transport Security: Configure TLS/SSL for encrypted MQTT communication
  • Configure Authentication: Set up username/password, certificates, and JWT-based authentication
  • Design Access Control: Create ACL policies for topic-level permissions
  • Deploy Securely: Follow production security best practices

1190.2 Prerequisites

Before diving into this chapter, you should be familiar with:

1190.3 Why MQTT Security Matters

Without proper security, attackers can:

  • Eavesdrop on sensor data (privacy breach)
  • Publish fake commands (actuator manipulation)
  • Deny service (flood broker with messages)
  • Impersonate devices (inject malicious data)
ImportantSecurity Is Not Optional

Every production MQTT deployment MUST implement:

  1. Encryption (TLS/SSL)
  2. Authentication (verify identity)
  3. Authorization (access control)

1190.4 Transport Layer Security (TLS/SSL)

Always use MQTTS (MQTT over TLS) in production:

Port Protocol Security
1883 MQTT Unencrypted (testing only)
8883 MQTTS TLS encrypted (production)

1190.4.1 Python Example with TLS

# Requires paho-mqtt 2.0+
import paho.mqtt.client as mqtt
import ssl

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)

# Configure TLS
client.tls_set(
    ca_certs="/path/to/ca.crt",      # Certificate Authority
    certfile="/path/to/client.crt",  # Client certificate
    keyfile="/path/to/client.key",   # Client private key
    tls_version=ssl.PROTOCOL_TLS_CLIENT
)

# Connect to secure port
client.connect("broker.example.com", 8883)

1190.4.2 ESP32 Example with TLS

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

// Root CA certificate (from broker)
const char* ca_cert = R"(
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIJAJC1...
-----END CERTIFICATE-----
)";

WiFiClientSecure espClient;
PubSubClient client(espClient);

void setup() {
    espClient.setCACert(ca_cert);
    client.setServer("broker.example.com", 8883);
}

1190.5 Authentication Methods

1190.5.1 Username/Password Authentication

The simplest authentication method:

client.username_pw_set("device_001", "SecurePassword123!")
client.connect("broker.example.com", 8883)

Best practices:

  • Use unique credentials per device
  • Store passwords securely (not in source code)
  • Rotate credentials periodically
  • Use strong passwords (16+ characters)

1190.5.2 Client Certificate Authentication

More secure than passwords - device identity proven by certificate:

client.tls_set(
    certfile="/path/to/device.crt",
    keyfile="/path/to/device.key"
)
# No username/password needed - certificate proves identity

Advantages:

  • No password to leak or brute-force
  • Device identity cryptographically verified
  • Easier to revoke (add to Certificate Revocation List)

1190.5.3 Token-Based Authentication (JWT)

Modern brokers support JWT tokens for scalable device authentication.

JSON Web Tokens provide a stateless authentication mechanism ideal for large-scale IoT deployments.

JWT Structure for MQTT:

Header.Payload.Signature

Header: {"alg": "RS256", "typ": "JWT"}
Payload: {
  "sub": "device_001",        # Device ID (subject)
  "iat": 1702834567,          # Issued at timestamp
  "exp": 1702838167,          # Expiration (1 hour later)
  "aud": "mqtt.example.com",  # Target broker
  "scope": ["publish:sensors/#", "subscribe:commands/#"]
}

Python implementation:

import jwt
import time
from cryptography.hazmat.primitives import serialization

# Load device private key
with open("device_private.pem", "rb") as key_file:
    private_key = serialization.load_pem_private_key(
        key_file.read(), password=None
    )

def generate_mqtt_token():
    payload = {
        "sub": "sensor_001",
        "iat": int(time.time()),
        "exp": int(time.time()) + 3600,  # 1 hour validity
        "aud": "mqtt.example.com",
        "scope": ["publish:sensors/temperature", "subscribe:commands/#"]
    }
    return jwt.encode(payload, private_key, algorithm="RS256")

# Connect with JWT
token = generate_mqtt_token()
client.username_pw_set("", token)  # Empty username, token as password

Security best practices:

Practice Recommendation
Algorithm Use RS256/ES256 (asymmetric), not HS256
Expiration 1-24 hours max
Scope claims Implement fine-grained topic permissions
Key rotation Rotate signing keys quarterly

1190.6 Access Control Lists (ACLs)

Restrict which topics each client can access:

# Mosquitto ACL file example (/etc/mosquitto/acl.conf)

# Sensor can only publish its own data
user sensor_001
topic read home/+/temperature
topic write home/sensor_001/#

# Actuator can only receive commands and publish status
user actuator_001
topic read home/commands/actuator_001
topic write home/status/actuator_001

# Dashboard can read everything but write nothing
user dashboard
topic read home/#

Security principle: Least privilege - devices only access topics they need.

1190.6.1 ACL Patterns

Pattern Example Description
Exact match topic read sensors/temp Only this specific topic
Single wildcard topic write sensors/+/data Any device’s data topic
Multi wildcard topic read sensors/# All under sensors/
Pattern substitution topic write sensors/%u/data %u = username

1190.7 Production Security Checklist

WarningBefore Deploying MQTT in Production

1190.8 Broker Hardening

1190.8.1 Mosquitto Configuration Example

# /etc/mosquitto/mosquitto.conf

# Require authentication
allow_anonymous false
password_file /etc/mosquitto/passwd

# Enable TLS
listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key

# Disable unencrypted listener
# listener 1883  # COMMENTED OUT - DO NOT ENABLE IN PRODUCTION

# Access control
acl_file /etc/mosquitto/acl.conf

# Limit message size
message_size_limit 102400  # 100KB max

# Connection limits
max_connections 10000
max_inflight_messages 100

# Logging for security monitoring
log_dest file /var/log/mosquitto/mosquitto.log
log_type error
log_type warning
log_type notice
log_type information

1190.9 Common Security Pitfalls

CautionPitfall: Hardcoded Credentials

The Mistake: Embedding MQTT credentials directly in source code or firmware.

Why It’s Dangerous:

  • Credentials visible in version control
  • Can’t rotate without firmware update
  • If one device is compromised, all are compromised

The Fix:

# BAD: Hardcoded credentials
MQTT_USER = "admin"
MQTT_PASS = "password123"

# GOOD: Environment variables or secure storage
import os
MQTT_USER = os.environ.get("MQTT_USER")
MQTT_PASS = os.environ.get("MQTT_PASS")

# BETTER: Hardware security module or secure element
from secure_element import get_credentials
MQTT_USER, MQTT_PASS = get_credentials()
CautionPitfall: Overly Permissive ACLs

The Mistake: Giving devices wildcard access like topic readwrite #

Why It’s Dangerous:

  • Compromised sensor can read all data (privacy breach)
  • Compromised sensor can publish fake commands (safety hazard)
  • Lateral movement within IoT network

The Fix: Implement least-privilege ACLs:

# WRONG: Too permissive
user sensor_001
topic readwrite #

# CORRECT: Minimal permissions
user sensor_001
topic write sensors/sensor_001/data
topic read commands/sensor_001
CautionPitfall: No Certificate Validation

The Mistake: Disabling certificate validation for “convenience”

# DANGEROUS: Disables certificate verification
client.tls_insecure_set(True)  # NEVER DO THIS IN PRODUCTION

Why It’s Dangerous:

  • Allows man-in-the-middle attacks
  • Attacker can intercept all traffic
  • Defeats purpose of TLS entirely

The Fix: Always validate certificates:

# CORRECT: Full certificate validation
client.tls_set(
    ca_certs="/path/to/ca.crt",
    cert_reqs=ssl.CERT_REQUIRED  # Enforce validation
)

1190.10 Summary

Security essentials:

Layer Implementation
Transport TLS on port 8883
Authentication Unique credentials per device
Authorization Topic-level ACLs
Monitoring Log analysis and anomaly detection

Remember:

  • Never use port 1883 in production
  • Never disable certificate validation
  • Always implement least-privilege ACLs
  • Rotate credentials regularly

1190.11 What’s Next

Now that you understand MQTT security: