Last updated: 2026-05-15
Mosquitto TLS/SSL Configuration Guide
This guide provides recommended TLS/SSL settings for Eclipse Mosquitto MQTT broker to encrypt connections between clients and the broker. Securing MQTT with TLS is essential for IoT deployments where devices transmit sensitive telemetry and control data.
Prerequisites
- Eclipse Mosquitto 2.0 or later
- OpenSSL 1.1.1 or later
- SSL certificates (server certificate, private key, and CA certificate)
Certificate Setup
Place your certificates in a dedicated directory:
mkdir -p /etc/mosquitto/ssl
chmod 750 /etc/mosquitto/ssl
chown mosquitto:mosquitto /etc/mosquitto/ssl
cp server.crt /etc/mosquitto/ssl/server-cert.pem
cp server.key /etc/mosquitto/ssl/server-key.pem
cp ca.crt /etc/mosquitto/ssl/ca.pem
chmod 640 /etc/mosquitto/ssl/*.pem
chown mosquitto:mosquitto /etc/mosquitto/ssl/*.pem
Listener TLS Configuration
Configure a TLS-encrypted listener in mosquitto.conf. The standard MQTT-over-TLS port is 8883.
Basic TLS Listener
# TLS listener on port 8883
listener 8883
# Certificate files
cafile /etc/mosquitto/ssl/ca.pem
certfile /etc/mosquitto/ssl/server-cert.pem
keyfile /etc/mosquitto/ssl/server-key.pem
# TLS protocol version
tls_version tlsv1.2
# Cipher suites (OpenSSL format)
ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
# TLS 1.3 cipher suites
ciphers_tls1.3 TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
Configuration Explained
- listener 8883 -- Opens a listener on the standard MQTTS port.
- tls_version tlsv1.2 -- Sets the minimum TLS protocol version. Mosquitto 2.0 with OpenSSL 1.1.1+ supports both TLS 1.2 and TLS 1.3.
- ciphers -- OpenSSL cipher string for TLS 1.2 connections.
- ciphers_tls1.3 -- OpenSSL ciphersuites string for TLS 1.3 connections.
Client Certificate Authentication
To require clients to present a TLS certificate (mutual TLS), add these settings to the TLS listener:
require_certificate true
use_identity_as_username true
- require_certificate true -- Clients must present a valid certificate signed by the CA in
cafile. - use_identity_as_username true -- Uses the certificate's Common Name (CN) as the MQTT username, removing the need for password-based authentication.
See RFC 8446 ยง4.3.2 for the TLS Certificate Request specification, and Wikipedia: Mutual authentication for a general overview.
Multiple Listeners
You can run both a plaintext listener (for local trusted networks) and a TLS listener simultaneously:
# Plaintext listener on localhost only
listener 1883 127.0.0.1
allow_anonymous true
# TLS listener on all interfaces
listener 8883
cafile /etc/mosquitto/ssl/ca.pem
certfile /etc/mosquitto/ssl/server-cert.pem
keyfile /etc/mosquitto/ssl/server-key.pem
tls_version tlsv1.2
ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
ciphers_tls1.3 TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
WebSocket TLS
Mosquitto can serve MQTT over WebSockets with TLS for browser-based clients:
listener 8884
protocol websockets
cafile /etc/mosquitto/ssl/ca.pem
certfile /etc/mosquitto/ssl/server-cert.pem
keyfile /etc/mosquitto/ssl/server-key.pem
tls_version tlsv1.2
ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
Complete Configuration
# Per-listener settings
per_listener_settings true
# Plaintext listener on localhost only
listener 1883 127.0.0.1
allow_anonymous true
# TLS listener on port 8883
listener 8883
cafile /etc/mosquitto/ssl/ca.pem
certfile /etc/mosquitto/ssl/server-cert.pem
keyfile /etc/mosquitto/ssl/server-key.pem
tls_version tlsv1.2
ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305
ciphers_tls1.3 TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256
require_certificate false
# Password file for TLS listener
password_file /etc/mosquitto/passwd
Client Connections
mosquitto_pub / mosquitto_sub
mosquitto_pub -h mqtt.example.com -p 8883 \
--cafile /path/to/ca.pem \
-t "test/topic" -m "Hello TLS"
mosquitto_sub -h mqtt.example.com -p 8883 \
--cafile /path/to/ca.pem \
-t "test/topic"
With client certificates (mutual TLS):
mosquitto_pub -h mqtt.example.com -p 8883 \
--cafile /path/to/ca.pem \
--cert /path/to/client-cert.pem \
--key /path/to/client-key.pem \
-t "test/topic" -m "Hello mTLS"
Python (paho-mqtt)
import paho.mqtt.client as mqtt
import ssl
client = mqtt.Client()
client.tls_set(
ca_certs="/path/to/ca.pem",
tls_version=ssl.PROTOCOL_TLS_CLIENT
)
client.connect("mqtt.example.com", 8883)
Security Notes
The cipher suite and protocol configuration in this guide addresses the following known TLS vulnerabilities:
- POODLE (CVE-2014-3566, 2014): SSL 3.0 is disabled. TLS_FALLBACK_SCSV was added in OpenSSL 1.0.1j / 1.0.2 (October 2014); SSL 3.0 disabled by default in OpenSSL 1.1.0 (August 2016).
- BEAST (CVE-2011-3389, 2011): Mitigated by recommending TLS 1.2 as the minimum; AEAD-only ciphers eliminate the CBC padding oracle.
- CRIME (CVE-2012-4929, 2012): TLS compression is off by default in OpenSSL 1.1.0+; do not enable it.
- Lucky13 (2013): AEAD-only cipher list eliminates CBC padding timing side-channels entirely.
- FREAK (CVE-2015-0204, 2015): EXPORT-grade ciphers are excluded from the cipher string. Removed from OpenSSL 1.1.0 (August 2016).
- LOGJAM (CVE-2015-4000, 2015): Short-key DHE is excluded; only ECDHE key exchange is recommended.
- Sweet32 (CVE-2016-2183, 2016): 3DES is excluded from the cipher string. Disabled by default in OpenSSL 3.0 (September 2021).
- ROBOT (CVE-2017-13099, 2017): Static RSA key exchange is excluded; only ECDHE is recommended. Fixed in OpenSSL 1.0.2m / 1.0.1v (November 2017).
- Downgrade attacks: TLS_FALLBACK_SCSV prevents protocol version rollback.
The following are not addressable through TLS configuration alone:
- Heartbleed (CVE-2014-0160, 2014): A memory disclosure bug in OpenSSL 1.0.1 through 1.0.1f. Fixed in OpenSSL 1.0.1g (April 7, 2014). Addressed by patching OpenSSL, not by TLS configuration.
- BREACH (CVE-2013-3587, 2013): Not applicable. BREACH targets HTTP-level response compression; the MQTT protocol does not involve HTTP.
- DROWN (CVE-2016-0800, 2016): Requires SSLv2 to be enabled on any server sharing the same private key. Ensure SSLv2 is disabled on all services that use the same certificate and key pair.
Verification
Test the TLS connection with openssl:
openssl s_client -connect mqtt.example.com:8883
Verify the port is listening:
ss -tlnp | grep 8883
Test publish and subscribe over TLS:
mosquitto_sub -h mqtt.example.com -p 8883 --cafile /path/to/ca.pem -t "test/#" &
mosquitto_pub -h mqtt.example.com -p 8883 --cafile /path/to/ca.pem -t "test/hello" -m "works"
Check Mosquitto logs:
grep -i tls /var/log/mosquitto/mosquitto.log