Security is a very important aspect for MQTT brokers. In a previous article you’ve already learned how to implement authentication and authorization. The weakness in that configuration was that credentials were transmitted in cleartext; it was therefore possible, for an attacker who can sniff the network traffic, to read and use them to impersonate a legitimate client.
Today I’ll show you how to encrypt the communication channel between client and broker using SSL certificates. I’ll also explain how to write a program for the esp32 chip to send data to the broker using the secure channel…
SSL certificate
To be able to encrypt the communication, mosquitto requires a server certificate.
First generate the private key (RSA with a length at least 2048 bits):
openssl genrsa -out mosquitto.key 2048 |
Then create the CSR file:
openssl req -new -out mosquitto.csr -key mosquitto.key |
type the required information; the most important of which is the common name that will identify the server:
Now sign the CSR file with your Certificate Authority (or send it to a public / corporate CA) to generate the certificate:
openssl ca -config openssl.cnf -extensions server_cert -notext -in mosquitto.csr -out mosquitto.cer |
Create the ssl subfolder in the folder where you installed mosquitto and copy into that folder the certificate, its private key and the certificate of the CA:
Configuration
Open the mosquitto.conf file and add the following lines:
The first line changes the TCP port mosquitto is normally listening to (1883) to the default port for SSL connection, 8883.
The following 3 lines set the path for server and CA certificates and for the private key that corresponds to the server certificate. The last one, which is not compulsory, forces the use of the TLS v1.2 protocol, the most secure one at the moment of writing.
Once the server has been configured, you can start it (-v is to enable the verbose output):
mosquitto.exe -c mosquitto.conf -v |
To be able to use the mosquitto_pub and mosquitto_sub tools, you now have to add new parameters:
mosquitto_sub.exe -p 8883 -t test --cafile .\ssl\ca.cer --insecure mosquitto_pub.exe -p 8883 -m 20 -t test --cafile .\ssl\ca.cer --insecure |
With -p you specify the TCP port of the server, with –cafile the path of the CA certificate which signed the server certificate mosquitto uses and finally with –insecure you configure the two clients not to verify that the certificate’s common name (in my example mymosquitto.local) corresponds to the server name.
esp32
Tuan PM developed a library (espmqtt) for the esp-idf framework that implements a complete MQTT client. Moreover, the library does support secure connections, you can therefore use it to connect to an MQTT broker with TLS enabled.
Copy the content of the Github repository in the components folder of your project and include the library’s header file in your source code:
#include "mqtt.h" |
The MQTT client is configured using the mqtt_settings struct:
The most important parameters are:
- the server (host) that runs the MQTT broker (you can use the IP address or the DNS name)
- the TCP port (port) the server is listening to (default is 1883 or 8883 if SSL is enabled)
- username and password if the server requires authentication
- one or more callback functions the espmqtt library will call when the corresponding event occurs
Your program can interact with the MQTT client implementing its callback functions.
For example the connection or disconnection from the MQTT server occurs as follows:
The connect_cb and disconnect_cb functions perform the “real” connection and disconnection, while connected_cb and disconnected_cb functions are executed after the corresponding activity is completed (= the client successfully connected to the server). Your program usually doesn’t need to re-implement the main functions, but will implement the ones related to events, to execute actions (for example subscribe a topic) when a specific event occurs.
After having configured the client, you can run it with:
mqtt_start(&settings); |
Once connected to the server (connected_cb callback function) you can subscribe or unsubscribe a topic with:
void mqtt_subscribe(mqtt_client *client, const char *topic, uint8_t qos); void mqtt_unsubscribe(mqtt_client *client, const char *topic); |
and publish data to a topic with:
void mqtt_publish(mqtt_client* client, const char *topic, const char *data, int len, int qos, int retain); |
Demo
I prepared an example to show my esp32 devboard sending data to a mosquitto server, with SSL enabled.
I connected to the devboard an HTU21D sensor as explained in a previous article and my program reads, every 5 seconds, the temperature and humidity values and sends them to the broker. I used a very handy opensource program, HelloIoT, to create a dashboard and display the received data.
The source code of the program and the configuration of the HelloIoT dashboard are available in my Github repository; here’s a short video of the demo:
Want to use ESP32 Thing with Environmental Combo Breakou sensor 14348 and lipo(lithium battery) as air quality portable modules in an area. How to set id for ESP 32 Thing. How to send sensor data to a server for further processing. Please Help urgently
Hi, sorry but I don’t offer professional support.
Articoli sempre molto utili e ben scritti, grazie tante!
ps. niente in arrivo riguardo al Bluetooth LE?
grazie Vincenzo! Si, sto lavorando a una serie di tutorial su BLE visto che l’argomento è abbastanza complesso…
Ciao e complimenti per questo sito! Pensi che sia possibile configurare connessioni sicure con l’ESP8266, seguendo questo tutorial?
PS. Non riesco a commentare attraverso la versione mobile del sito, non compare la domanda di sicurezza 🙂
Ciao Jacopo. No, per esp8266 devi usare un diverso framework e diverse librerie… ad esempio questa dello stesso autore di quella utilizzata da me per esp32.
Very good article.
How is the key file used by the ESP32? I didn’t see in the source files where the key file was being included or read.
Thanks,
Robert
Hi Robert, you don’t need the private key in the client: mosquitto uses it to enable the TLS protocol.
Ciao e ancora complimenti per gli ottimi articoli che scrivi.
Sto cercando di aggiungere al tuo esempio una callback che gestisca la ricezione di messaggi.
Purtroppo non riesco a venirne a capo, anche perchè non riesco a trovare documentazione sulla libreria espmqtt.
Comunque, per gestire i messaggi in arrivo ho aggiunto alla struct mqtt_settings la voce .read_cb = mqtt_rx_callback
Ho poi creato la callback:
int mqtt_rx_callback(mqtt_client *client, void *buffer, int len, int timeout_ms)
{
// mqtt_subscribe(mqtt_client *client, const “/ubi”, 0);
// char buf[512];
while(1)
{
if(!len) return(0);
// strncpy(buf, (char *)buffer, len);
printf(“ricevuto %s\n”, (char *)buffer);
vTaskDelay(1000 / portTICK_RATE_MS);
}
return(0);
}
Se decommento le righe char buf… e strncpy… l’esp si riavvia in continuazione.
Ma quello che mi preoccupa di più è che se decommento la riga mqtt_subscribe…
ricevo degli errori in compilazione:
$21_mqtt/main/./main.c:80:20: error: expected expression before ‘mqtt_client’
mqtt_subscribe(mqtt_client *client, const “/ubi”, 0);
^
$21_mqtt/main/./main.c:80:5: error:too few arguments to function ‘mqtt_subscribe’
mqtt_subscribe(mqtt_client *client, const “/ubi”, 0);
^
In file included from $21_mqtt/main/./main.c:12:0:
/esp32-tutorial-master/21_mqtt/components/espmqtt/include/mqtt.h:117:6: note: declared here
void mqtt_subscribe(mqtt_client *client, const char *topic, uint8_t qos);
Eppure il prototipo nel file header prevede quegli argomenti.
Riesci a darmi un aiuto veloce senza perdere troppo tempo?
Grazie.
Stefano
Ciao Luca,
innanzitutto complimenti per il tuo lavoro, rendi semplici i concetti più difficili.
Una cosa non mi è chiara del TLS con Mosquitto: perché non ho bisogno della CA del mio broker locale per accedere al TLS?
Grazie,
Mattia
ciao Mattia… una volta che hai il certificato client (generato dalla CA) e che tale certificato è accettato da mosquitto è sufficiente. La CA ti serve solo in fase di generazione dei certificati, non per utilizzarli.
Ciao Luca,
Come tuo solito ottimo lavoro. Davvero complimenti.
Volevo chiederti se nel tuo repository github l’esempio relativo a questo articolo è il https://github.com/lucadentella/esp32-tutorial/tree/master/21_mqtt.
Non riesco a capire come sia possibile che l’ESP non abbia bisogno del certificato client per essere autorizzato ad accedere al mosquito server con TLS attivo.
Puoi aiutarmi? Grazie.
Inoltre volevo segnalarti che nel main.c dell’esempio ci sono delle credenziali in chiaro per accedere al wi-fi.
Grazie mille
Ciao Luca,
forse ho capito: la libreria usa il certificato inviato dal broker per ottenere la chiave pubblica con cui criptare i messaggi. Non è richiesta la mutua autenticazione.
Grazie
Claudio
Hello Luca,
Would you be able to assist me? I cannot find the ca.cer file that I should copy into my mosquitto/ssl file or is this the ca.cert.pem?
Many thanks
Hi Fred! ca.cer is the certificate of your certification authority, the one used to sign the SSL certificate used by Mosquitto server.
In my blog post you can find a link to setup a CA using OpenSSL, but it is not mandatory: you may use a public CA or an existing one. What is important is that you pass the certificate of this CA to the client so that it trusts the certificate exposed by Mosquitto.