Requirements

Recently we’re doing an IoT project and decided to use MQTT for messaging. As we had strict security requirements we use TLS for communication with the MQTT broker. We used the popular Mosquitto MQTT broker and Vault from Hashigroup as our PKI. I found some basic information about securing a MQTT broker with TLS but still had some issues that costs me several hours to solve so I wrote down my findings in this blog post to hope it will save someone else a valuable part of his lifetime.

Setup your PKI with Vault

There are already very good resources on the net how to setup Vault see [1] and [2] and of course the official documentation. So I don’t explain how to setup Vault in this post.

In production you will typically use a certificate chain to issue your server or client certificates.

certificate.chain

The root CA is in a save spot and you use the intermediate CA for daily business. For simplicity we we create the root CA and the intermediate CA in vault in the following example. *Don’t do this in production*!

Create Root CA

We’re going to use two PKI mount points in vault. One for the Root CA and the second for the Intermediate CA.

First mount the Root CA, we will use the path „myorg_ca“.

With

you can check if you can see the newly mounted PKI is correctly mounted.

Create the CA certificate and key.

You can get the certificate in PEM format easily with curl

You can safe the certificate in the file ca.crt as we need it later for the Mosquitto configuration.

Last but not least set the issuing_certificates url with

That completes our CA for this example. Again – don’t do this in production. Separate Root CA from intermediate CA as written in Vault’s documentaiton.

Create the Intermediate CA

Now we will create an intermediate CA. Again we mount a PKI backend in Vault.

We need to save the output of the certificate signing request so lets save the output in a file myorg.csr and use it for signing the signing request with our root CA.

This gives us our intermediate certificate which we save in the file myorg.crt to import with

The last thing to do is to set the urls

Setup Mosquitto

Setting up Mosquitto is quite simple. Use the package management for your distribution/OS to install it or use Docker for using the current image. Then edit the config file mosquitto.conf. I’m using Docker so the path looks like in the following file.

Here we use the ca.crt file but we still need the server certificate and the key file. We use our intermediate CA in Vault to generate them. Therefore we will create a role for our MQTT server.

And create the certificate

Now comes the tricky part. Save the private key in the file mqtt.key and combine the certificate with the intermediate CA. First copy the certificate and then the intermediate CA to the file mqtt.crt. So you have the certificate chain that is needed for TLS to verify the certificate. It is important to set the ip_sans to the used IP address. Alternatively you can use the alt_names to set all the ip addresses or host names that are used in your environment. If you don’t set these settings correctly you end up with strange and not easy to analyze error messages. Some messages I’ve encountered (while I used wrong settings).

All you get from the client is

On the server side you see something like

All my fails were caused by wrong IP settings and certificate chains. If you have everything setup correctly you can use

Add client certification support

To enforce client side TLS certificates all we have to do is to add the option require_certificate and set the value to true.

To create the client certificates we use vault again.

And create the certificate

As with the server certificate combine the newly generated certificate with the intermediate certificate. Save the files in mqtt-client.crt and mqtt-client.key.

Finally we can test the configuration with

which should work without any error messages. Congratulations you have a working MQTT broker with client and server side TLS certificates.

References

* http://cuddletech.com/?p=959
* https://blog.kintoandar.com/2015/11/vault-PKI-made-easy.html
* http://rockingdlabs.dunmire.org/exercises-experiments/ssl-client-certs-to-secure-mqtt
* https://www.digicert.com/ssl-support/pem-ssl-creation.htm – how to correctly create a certificate chain in PEM format.

Disclaimer

You have to find your own settings for certificate management. You have to carefully design your system to make it secure. This tutorial is a working example but is not meant as a best practice in securing distributed systems or PKI’s. It should serve you as a starting point in designing such a system.