Lab: securing MQTT with passwords and TLS
In short: An open MQTT broker lets anyone read or inject messages. In this lab you add TLS encryption with your own lab certificate authority, require a password for each client and use an access control list so each device can only touch its own topics.
Aim and what you need
The aim is to turn the open broker from the Mosquitto lab into one that protects confidentiality (TLS, Transport Layer Security), authentication (passwords) and authorisation (topic ACLs, access control lists). These are the main fixes for weak MQTT setups found in real IoT reviews.
- The Mosquitto broker from the previous lab on a Pi at 192.168.10.5, with a DNS or hosts-file name such as
broker.lab.example. - OpenSSL (installed on most Linux systems).
- Your own isolated network and devices.
Steps
- Create a small certificate authority (CA) for the lab, then a server key and certificate signed by it. The subject alternative name (SAN) must match the name or IP clients use.
- Copy the files to
/etc/mosquitto/certsand make the key readable only by the mosquitto user. - Create a password file with one user per device or app.
- Write an ACL file so each user can only use its own topics.
- Replace the temporary
lab.confwith a TLS listener, then restart and open port 8883 to the LAN only.
openssl req -x509 -new -nodes -newkey rsa:3072 -keyout ca.key -out ca.crt -days 365 -subj "/CN=Lab MQTT CA"
openssl req -new -nodes -newkey rsa:3072 -keyout server.key -out server.csr -subj "/CN=broker.lab.example"
printf "subjectAltName=DNS:broker.lab.example,IP:192.168.10.5" > san.ext
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365 -extfile san.ext
sudo mkdir -p /etc/mosquitto/certs
sudo cp ca.crt server.crt server.key /etc/mosquitto/certs/
sudo chown mosquitto: /etc/mosquitto/certs/server.key
sudo chmod 600 /etc/mosquitto/certs/server.key
sudo mosquitto_passwd -c /etc/mosquitto/passwd sensor1
sudo mosquitto_passwd /etc/mosquitto/passwd dashboard
# /etc/mosquitto/acl
user sensor1
topic write lab/sensor1/#
user dashboard
topic read lab/#
# /etc/mosquitto/conf.d/lab.conf
listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
allow_anonymous false
password_file /etc/mosquitto/passwd
acl_file /etc/mosquitto/acl
sudo chown root:mosquitto /etc/mosquitto/passwd /etc/mosquitto/acl
sudo chmod 640 /etc/mosquitto/passwd /etc/mosquitto/acl
sudo systemctl restart mosquitto
sudo ufw delete allow from 192.168.10.0/24 to any port 1883 proto tcp
sudo ufw allow from 192.168.10.0/24 to any port 8883 proto tcp
mosquitto_sub -h broker.lab.example -p 8883 --cafile ca.crt -u dashboard -P '<dashboard-password>' -t 'lab/#' -v
mosquitto_pub -h broker.lab.example -p 8883 --cafile ca.crt -u sensor1 -P '<sensor1-password>' -t lab/sensor1/temp -m 21.7
Keep ca.key off the broker and offline: anyone holding it can issue certificates your clients will trust.
How to verify and troubleshoot
The dashboard subscriber should receive the sensor's message. Then test the negatives, which matter as much: a client without --cafile should fail the certificate check; a wrong password should be refused; sensor1 publishing to lab/sensor2/temp should be silently dropped; and a plain connection to port 1883 should fail. If you capture traffic in Wireshark (see capturing IoT traffic) you should see only TLS records, not readable topics.
- Certificate verify failed: the name you connect to is not in the SAN, or the client is using a different CA file.
- Broker fails to start: usually key permissions or a typo in a path; check
journalctl -u mosquitto. - Messages disappear: ACL rules are strict; a missing rule means no access, without an error to the client.
- ESP32 cannot connect: give it the CA certificate and enough memory; TLS on small boards is slower, so test with a longer timeout.
Clean-up and next steps
Passing -P on the command line leaves passwords in shell history, so clear test lines with history -d or use a client config file. Note the certificate expiry date in your documentation and set a reminder to renew it. For larger setups consider client certificates instead of passwords. When the lab ends, remove test users with mosquitto_passwd -D, and delete or securely store the CA key.
Practice
Why must the broker certificate include a subject alternative name?
A device can connect but its messages never arrive. Passwords are correct. What should you check?
Why keep the CA private key off the broker?
Key takeaways
- Use TLS on port 8883 and close plain 1883.
- Give each device its own username and password.
- ACLs limit each client to its own topics.
- Test the failures, not just the success.
- Protect the CA key and track certificate expiry.
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.