Free tech learning for everyone, from basics to pro

IoT SecurityIoT SecurityIntermediate

Securing MQTT and IoT messaging: TLS, authentication and topic access control

In short: MQTT has no security by default, so a broker on port 1883 with anonymous access lets anyone read and write every topic. Secure it with TLS on port 8883, authenticate every client, restrict each one to its own topics with access control lists, and keep the broker off the public internet where possible.

Why MQTT needs extra care

MQTT (Message Queuing Telemetry Transport) is a lightweight publish-subscribe protocol used by a huge number of IoT systems. Its simplicity is its strength, but the protocol leaves security to the transport and the broker. Internet scans regularly find brokers that accept anonymous connections, where anyone can subscribe to # (every topic) and read sensor data, or publish fake commands to actuators.

Layers of MQTT securityNetworkfirewall, private networkTransportTLS 1.2 or 1.3, port 8883Authenticationclient cert or passwordAuthorisationtopic ACLs per clientPayloadvalidation, optional signing
Figure 1. MQTT security builds up in layers, from who can reach the broker to what each client may publish.

Encrypt with TLS

Run MQTT over TLS on port 8883 and close plain port 1883, or bind it to localhost for local tools. Use TLS 1.2 or 1.3, a certificate from your own CA or a public CA, and make clients verify the broker's certificate and hostname. A client that skips verification can be fooled by any attacker in the middle.

Authenticate every client

Two common methods:

  • Client certificates (mutual TLS): strongest, because each device has its own key pair, ideally in secure hardware. The broker can use the certificate's common name as the username.
  • Username and password: simpler, but use a unique password per device, store only hashes on the broker, and always run it inside TLS.

MQTT 5 also supports enhanced authentication, allowing challenge-response or token-based methods where both sides support them.

Authorise topics with ACLs

A secure MQTT connectionTCP to 8883only allowedhostsTLS handshakebroker certcheckedClient certor usernameCONNECTclient IDmatchedACL checkper topic
Figure 2. What happens before a device may publish: every step can reject the client.

Authentication says who the client is; an ACL (access control list) says what it may do. A good topic design makes ACLs easy: put the device ID in the topic, such as site1/sensors/<device-id>/temp. Each sensor can then write only to its own branch, and only the dashboard can read everything. Here is a Mosquitto example:

# /etc/mosquitto/conf.d/secure.conf
per_listener_settings false
allow_anonymous false

listener 8883
cafile   /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/broker.crt
keyfile  /etc/mosquitto/certs/broker.key
tls_version tlsv1.2
require_certificate true
use_identity_as_username true

acl_file /etc/mosquitto/acl

# /etc/mosquitto/acl
# each device writes only to its own branch (%u = username from the certificate)
pattern write site1/sensors/%u/#
pattern read  site1/commands/%u/#

user dashboard
topic read site1/sensors/#

On the client side, a Python program using the paho-mqtt library (version 2) verifies the broker and presents its own certificate:

import paho.mqtt.client as mqtt

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="sensor-0042")
client.tls_set(ca_certs="ca.crt", certfile="sensor-0042.crt", keyfile="sensor-0042.key")
client.connect("broker.example.com", 8883)
client.publish("site1/sensors/sensor-0042/temp", "21.4", qos=1)
client.disconnect()

Hardening the broker

  1. Keep the broker on a private network or behind a firewall; expose it to the internet only if you must, and then only on 8883.
  2. Deny wildcard subscriptions such as # for device accounts.
  3. Set limits on message size, connections and queued messages to resist floods.
  4. Log connections, failed logins and ACL denials, and send logs to your SIEM.
  5. Validate payloads in the application: never trust a number just because it arrived on the right topic.
  6. Patch the broker and libraries, and review retained messages that might hold stale or sensitive data.

Tip: test your ACLs. Connect as one device and try to publish to another device's topic; the broker should refuse it and log the attempt.

Practice

Why is subscribing to # dangerous on an open broker?
The multi-level wildcard matches every topic, so one subscriber can read all data passing through the broker.
What does use_identity_as_username do in Mosquitto?
It takes the client certificate's common name as the username, so ACL rules can be written per device without separate passwords.
A client connects to 8883 but disables certificate verification. What risk remains?
An attacker in the middle can present a fake broker certificate, read the traffic and steal credentials.

Key takeaways

  • MQTT has no built-in security; the broker and transport must provide it.
  • Use TLS on 8883 and make clients verify the broker certificate.
  • Authenticate each client, ideally with its own certificate.
  • Design topics around device IDs so ACLs can restrict each client.
  • Keep brokers private, limit wildcards, log denials and patch.
Tracks your learning on this device only. See your progress on the learning paths.

About the author

Mohamed Fayas

Founder of FM TecHub. CCNA certified, with a BTEC HND in Network Engineering, and BEng (Hons) in Computer Networking and Cloud Security. He writes practical, plain-English guides on networking, security and cloud.

More about the author

Original content written by Mohamed Fayas for FM TecHub. © 2026 FM TecHub. You're welcome to share a link to this page; please don't copy the text elsewhere without permission.

Stay up to date by email

New notes, tools and security news from FM TecHub, explained simply. Free.

We only use your email to send these updates. See our privacy policy.