MQTT is a popular lightweight protocol for use in home automation. If features a central broker where each of the clients can communicate with in a pub / sub fashion.

Since I’ve been toying around with some home automation setups, I was curious how to secure it with TLS.

Mosquitto

The most commonly used broker implementation I have come across is mosquitto and is quite straightforward to setup on most *nix flavors. In my setup, I wanted to run it on Raspberry Pi, which I could leave running at my local home network. Since it runs raspbian, installing it was as simple as:

~ sudo apt-get install mosquitto

TLS setup: keys and certificates

Doing the TLS setup requires a number of key and certificate files. The official mosquitto-tls man page fortunately lists all of them and how to generate them.

Note that for the final setup, not all of these files are required; these are the files we do need:

  1. ca.crt: Certificate Authority certificate: the “central” authority certifying ownership of the public key
  2. server.key: server private key, linked to the certificate.
  3. server.crt: certificate from the server (MQTT broker), signing the server key pair, by the CA.

File layout on the broker

On my setup, most of these folders were already available after install, so I figured to actually use them.

~ tree /etc/mosquitto
/etc/mosquitto
├── ca_certificates
│   ├── ca.crt
│   └── README
├── certs
│   ├── README
│   ├── server.crt
│   └── server.key
├── conf.d
│   ├── README
│   └── tls.conf
└── mosquitto.conf

mosquitto.conf

This is pretty the same config that was also provided by the built-in; just to show:

~ cat /etc/mosquitto/mosquitto.conf
# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example

pid_file /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

# This include assures that our own custom config gets loaded
include_dir /etc/mosquitto/conf.d

tls.conf

Actual TLS specific config, pointing to all the files that were added.

~ cat /etc/mosquitto/conf.d/tls.conf
port 8883
cafile /etc/mosquitto/ca_certificates/ca.crt
keyfile /etc/mosquitto/certs/server.key
certfile /etc/mosquitto/certs/server.crt
tls_version tlsv1

Reload the setup

The package installer also conveniently creates the required (systemd) service for us. Simply restart the service now:

sudo systemctl restart mosquitto.service

Client subscribe

With the broker running the new config, testing can easily be done with the mosquitto built-in mosquitto_pub / mosquitto_sub commands. Obviously, all clients that want to use this config now need the CA file.

On a client: subscribe:

~ mosquitto_sub --cafile ca.crt -h raspberrypi.lan -t test

Note: the host name should correspond to the host name in the certificate.

Client publish

On a client: publish

~ mosquitto_pub --cafile ca.crt -h raspberrypi.lan -t test -m "hi there"

In the window running the subscribe, the message should now appear.

Here, the clients do not verify themselves though, they just use the certificate to encrypt traffic over TLS.