MQTT brokers are surprisingly vulnerable to unauthorized access and data breaches if not properly secured.
Let’s see what a typical, insecure MQTT setup looks like, and then how we can lock it down. Imagine a simple scenario: a few sensors publishing temperature data to a central broker, and a dashboard subscribing to that data.
# mosquitto.conf (insecure example)
listener 1883
allow_anonymous true
With allow_anonymous true, anyone on the network can connect to your broker on port 1883 and either publish messages to any topic or subscribe to any topic. This is like leaving your front door wide open. A malicious actor could flood your topics with garbage data, overload your broker, or even intercept sensitive information if your "sensors" are publishing anything more than just temperature.
To harden this, we need to implement authentication and authorization.
1. Disallow Anonymous Access
The first step is to prevent unauthenticated clients from connecting.
- Diagnosis: If you can connect to your broker using
mosquitto_sub -h <broker_ip> -t "some/topic"without any username or password, it’s anonymously accessible. - Fix: In your
mosquitto.conffile, setallow_anonymous false. - Why it works: This forces every client to provide credentials before the broker even considers their connection request.
# mosquitto.conf (after disallowing anonymous)
listener 1883
allow_anonymous false
2. Implement Username/Password Authentication
Now that anonymous access is off, clients must authenticate.
- Diagnosis: Attempting to connect with
mosquitto_pub -h <broker_ip> -t "some/topic" -m "hello"will now fail with a "not authorized" or similar error if no credentials are provided. - Fix: Create a password file (e.g.,
pwfile.txt) and point your broker to it. Usemosquitto_passwdto add users. For example, to add a userdevice1with a passwordsupersecretpassword:
Then, inmosquitto_passwd -c pwfile.txt device1 # Enter password when prompted, then again to confirm.mosquitto.conf:
Clients will now connect like this:password_file /etc/mosquitto/pwfile.txtmosquitto_pub -h <broker_ip> -t "some/topic" -m "hello" -u "device1" -P "supersecretpassword" - Why it works: The broker reads the
password_file, hashes the provided password, and compares it to the stored hash. A match grants access.
3. Enforce Access Control Lists (ACLs)
Just because a client can authenticate doesn’t mean they should have free rein. ACLs define what topics a user can publish to or subscribe from.
- Diagnosis: A user authenticated with correct credentials can still publish to or subscribe from any topic if no ACLs are defined.
- Fix: Create an ACL file (e.g.,
aclfile.txt) and configure the broker to use it.
In# aclfile.txt example # User device1 can publish to sensors/temperature/livingroom # and subscribe to sensors/temperature/# user device1 topic write sensors/temperature/livingroom topic read sensors/temperature/# # User dashboard can only subscribe to all sensor data user dashboard topic read sensors/#mosquitto.conf:acl_file /etc/mosquitto/aclfile.txt - Why it works: The broker checks the
acl_filefor rules matching the authenticated user and the requested topic/action (read/write) before allowing the operation.
4. Use TLS/SSL for Encrypted Communication
Password-based authentication is only as secure as the network it traverses. An attacker on the same network could sniff credentials without TLS.
- Diagnosis: Network traffic to and from the broker can be inspected with tools like Wireshark, revealing plaintext credentials and message payloads.
- Fix: Enable TLS on your broker. This involves generating or obtaining SSL certificates and configuring Mosquitto to use them.
- Generate self-signed certificates (for testing/internal use):
You’ll need to create certificates for the broker and potentially for clients. For simplicity, let’s assume you have# Generate a private key openssl genrsa -out ca.key 2048 # Generate a Certificate Signing Request (CSR) openssl req -new -key ca.key -out ca.csr # Generate a self-signed certificate openssl x509 -req -days 365 -in ca.csr -signkey ca.key -out ca.crtserver.crtandserver.keyfor the broker. - Configure
mosquitto.conf:# TLS settings listener 8883 protocol mqtt tls_version tlsv1.2 certfile /etc/mosquitto/certs/server.crt keyfile /etc/mosquitto/certs/server.key # Optional: If using client certificates for mutual TLS # cafile /etc/mosquitto/certs/ca.crt # certfile /etc/mosquitto/certs/client.crt # keyfile /etc/mosquitto/certs/client.key - Clients connect using
mosquitto_pub -h <broker_ip> --cafile /path/to/ca.crt -t "test" -m "hello"(or specifying client certs/keys if mutual TLS is used).
- Generate self-signed certificates (for testing/internal use):
- Why it works: TLS encrypts the entire communication channel between client and broker, making credentials and message payloads unreadable to eavesdroppers.
5. Restrict Client IDs
Each MQTT client has a unique Client ID. Allowing clients to choose arbitrary IDs can lead to spoofing or denial-of-service attacks where a malicious client impersonates a legitimate one, potentially disrupting message delivery or causing confusion.
- Diagnosis: Clients can connect with any Client ID, even those reserved for system use or identical to other clients’ IDs (though MQTT spec handles duplicate IDs by disconnecting one).
- Fix: Use the
clientid_prefixoption inmosquitto.confto enforce a naming convention for client IDs.
Now, any client attempting to connect with a Client ID that doesn’t start with# mosquitto.conf # ... other settings ... clientid_prefix sensor_sensor_will be rejected. - Why it works: This acts as a simple form of client identity validation, ensuring that only clients adhering to the expected naming scheme can connect.
6. Limit Connection Rates and Payload Sizes
A denial-of-service attack can involve a single client bombarding the broker with a high volume of connections, subscriptions, or very large messages.
- Diagnosis: A single IP address or client can overwhelm the broker by opening many connections or sending excessively large messages.
- Fix: Configure rate limiting and maximum payload size.
# mosquitto.conf # Limit to 100 connections per IP address per minute max_connections_per_IP 100 # Limit message payload to 256KB max_payload_size 262144 - Why it works: These limits prevent a single, misbehaving client from consuming excessive resources and impacting the availability of the broker for legitimate clients.
After implementing these measures, attempting to connect anonymously or with incorrect credentials will result in connection refused or authentication failure errors. A legitimate, configured client will be able to connect, authenticate, and publish/subscribe according to its ACLs over a secure TLS channel.
The next common issue you’ll likely encounter is managing certificate revocation if a client’s key is compromised.