Table of Contents
< All Topics
Print

MQTT over TLS Walkthrough

Introduction

Info Box

Created with AI assistance and validated by a Human

MQTT over TLS, or MQTTS, secures communication between MQTT clients and brokers by using the Transport Layer Security (TLS) protocol, encrypting the data transmitted over the network. This ensures that sensitive information, like credentials and messages, is protected from eavesdropping and tampering. 

Prerequisites

MQTT Broker: You need an MQTT broker that supports TLS. Popular choices include Mosquitto,EMQX, and HiveMQ. 

TLS Certificates: You will need TLS certificates for both the broker and the clients. These can be self-signed certificates or certificates signed by a Certificate Authority (CA). 

MQTT Clients: You will need MQTT clients (e.g., Mosquitto’s mosquitto_pub and mosquitto_sub, or clients written in languages like Python or Java) that support TLS connections. 

Generating Certificates

The steps to create the MQTT certificates is split in 3 parts:

  1. Create a Root CA
  2. Create the Server Certificate
  3. Create the Client Certificate

MQTT Broker Certificates

Create a directory for certificates (optional)
Generate a Certificate Authority (CA) key
Generate a CA certificate
Generate a server key
Generate a server certificate signing request (CSR)
Sign the server certificate with the CA

Execution under a Linux Box using openssl

These chapter explains the working in commands to setup a TLS MQTT client-server communication.

Create a Certificate Authority, this will the base to create all certificates:

iot-demo@ubuntu:~/sandbox$ openssl genrsa -out ksoft_ca.key 2048
 
iot-demo@ubuntu:~/sandbox$  openssl req -new -x509 -days 365 -key ksoft_ca.key -out ksoft_ca.crt

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CH
State or Province Name (full name) [Some-State]:zurich
Locality Name (eg, city) []:zurich
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Ksoft
Organizational Unit Name (eg, section) []:ksoft-iot
Common Name (e.g. server FQDN or YOUR name) []:luism.co
Email Address []:luis.coelho.720813@gmail.com
 

 
 

After the CA, we create the certificates to be used by the MQTT Server

iot-demo@ubuntu:~/sandbox$ openssl genrsa -out ksoft-iot-server.key 2048

iot-demo@ubuntu:~/sandbox$ openssl req -new -key ksoft-iot-server.key -out ksoft-iot-server.csr

You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CH
State or Province Name (full name) [Some-State]:zurich
Locality Name (eg, city) []:zurich
Organization Name (eg, company) [Internet Widgits Pty Ltd]:ksoft-iot
Organizational Unit Name (eg, section) []:ksoft-iot-server
Common Name (e.g. server FQDN or YOUR name) []:iot.luism.co
Email Address []:info@luism.co

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:iot-pass
An optional company name []:ksoft
 
iot-demo@ubuntu:~/sandbox$ openssl x509 -req -in ksoft-iot-server.csr -CA ksoft_ca.crt -CAkey ksoft_ca.key -CAcreateserial -out ksoft-iot-server.crt -days 365

Certificate request self-signature ok
subject=C = CH, ST = zurich, L = zurich, O = ksoft-iot, OU = ksoft-iot-server, CN = iot.luism.co, emailAddress = info@luism.co

Configure the MQTT Broker

The following step is to configure the MQTT Broker, in this case the server connection for that open the Mosquitto configuration file /etc/mosquitto/mosquitto.conf Add the following lines, replacing paths with your actual certificate paths: 

iot-demo@ubuntu:~$ 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 /run/mosquitto/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

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

include_dir /etc/mosquitto/conf.d

 

The require_certificate parameter offers two authentication modes: if false, only the server is authenticated; if true, both the client and server must authenticate each other using mTLS, meaning mutual TLS, according to SecureW2. In essence, a false setting means a one-way authentication (server to client), while a true setting means a two-way authentication (both server and client). 

root@ubuntu:/home/iot-demo# cat /etc/mosquitto/conf.d/tls.conf
listener 8883 0.0.0.0
    protocol mqtt
    cafile /etc/mosquitto/ca_certificates/ca.crt
    certfile /etc/mosquitto/certs/server.crt
    keyfile /etc/mosquitto/certs/server.key
    allow_anonymous true
    require_certificate false 

Restart Mosquitto: sudo systemctl restart mosquitto. 

Test client

With this setup no further client certificate is required and the connection can be tested with mosquitto_pub

iot-demo@ubuntu:~$ mosquitto_sub -h iot.luism.co -p 8883 --cafile /home/iot-demo/workspace/helper-scripts/ca.crt  -t "#" --debug
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending SUBSCRIBE (Mid: 1, Topic: #, QoS: 0, Options: 0x00)
Client (null) received SUBACK
Subscribed (mid: 1): 0
^CClient (null) sending DISCONNECT

Important Remarks

Sometimes is difficult to debug the TLS handshake, so here are a couple of tips to make it work.

  • Mosquitto Debug
    • Log to systemd-journald by adding the following lines to mosquitto.conf
      • log_dest syslog
      • log_facility local5
  • For testing the clients without credentials the server must have the parameter (otherwise on top of TLS a credentials setup is required)
    • allow_anonymous true
  • For testing proposes if using a localhost communication:
    • The server CN, the common name parameter added on the CSR can be a dummy FQDN, like in the example iot.luism.co
    • In order to work as localhost the /etc/hosts needs to be updated with the following line
      • 127.0.0.1 iot.luism.co

MQTT Client Certificate setup

Generate a client CSR
Sign the client certificate CSR
iot-demo@ubuntu:~/sandbox/client_certs$ openssl genrsa -out mqtt_client.key 2048
 
 
iot-demo@ubuntu:~/sandbox/client_certs$ openssl req -new -key mqtt_client.key -out mqtt_client.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CH
State or Province Name (full name) [Some-State]:Luzern
Locality Name (eg, city) []:Luzern
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Ksoft-iot
Organizational Unit Name (eg, section) []:high-speed-gateway
Common Name (e.g. server FQDN or YOUR name) []:edge.iot-luism.co
Email Address []:edge@luism.co

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:edge-iot
An optional company name []:edge-iot
 
iot-demo@ubuntu:~/sandbox/client_certs$  openssl x509 -req -in mqtt_client.csr -CA ../ca/ksoft_ca.crt -CAkey ../ca/ksoft_ca.key -CAcreateserial -out mqtt_client.crt -days 365
Certificate request self-signature ok
subject=C = CH, ST = luzern, L = luzern, O = Ksoft-iot, OU = hight-speed-gateway, CN = edge.iot-luism.co, emailAddress = edge@luism.co
 


Using MQTT Clients

Notice

This section was not yet human validated

When publishing or subscribing, use the –cafile, –cert, and –key options to specify the CA certificate, client certificate, and client key, respectively. For example: mosquitto_pub -h localhost -p 8883 –cafile ~/certs/ca.crt –cert ~/certs/client.crt –key ~/certs/client.key -t test/topic -m “hello”. 

Using other MQTT clients: Refer to your client’s documentation for how to enable TLS and provide the necessary certificate and key information. 

Two-Way Authentication

Two-way authentication, also known as mutual TLS, requires both the client and server to authenticate each other using certificates.

To enable two-way authentication, you’ll need to configure your broker to require client certificates and provide the client with its certificate and key. 

Scroll to Top