Mongoose-OS has a built-in MQTT client supporting TLS. This allows us to authenticate the server, but also the server infrastructure is able to authenticate the identity of incoming connections, that is, to validate that they belong to authorized users.
For further information on the MQTT client and using it without TLS, read this article. For more information on TLS, read this one.
Configuration
We’ll configure the ESP32 running Mongoose-OS to use the MQTT client and connect to a WiFi network. Since we are going to connect to a server (the MQTT broker), this is perhaps the simplest and fastest way to run our tests. This action can be done manually using RPCs (Remote Procedural Calls), writing a JSON config file, or it can be defined in the YAML file that describes how the project will be built. We’ve chosen this last option for our tests.
libs: - origin: https://github.com/mongoose-os-libs/mqtt # Include the MQTT client config_schema: - ["mqtt.enable", true] # Enable the MQTT client - ["mqtt.server", "address:port"] # Broker IP address (and port) - ["mqtt.ssl_ca_cert", "ca.crt"] # Broker certificate, required - ["mqtt.ssl_cert", "sandboxclient.crt"] # our certificate, for mutual authentication - ["mqtt.ssl_key", "sandboxclient.key"] # our key, for mutual authentication
The most common port for MQTT over TLS is 8883. The broker can also ask us to send a username and password, full configuration details are available at the corresponding Mongoose-OS doc page. Finally, it is the broker who decides which type of authentication to use (one- or two-way), though we must provide our certificate when the broker asks for it.
Operation
Before we build our project and execute our code, it is perhaps convenient to have an MQTT client connected to the broker, so we can see the message the device will send at connect time. We’ve used a broker we installed in a server in our lab and connected to it with no authentication, so all we’ve shown in the MQTT article is valid here too.
After the code is compiled and linked (mos build) and the microcontroller’s flash is programmed (mos flash) using mos tool, we’ll watch the log and check if everything is going on as it should, or catch any possible errors. Remember we need to configure the proper access credentials to connect to our WiFi network of choice (SSID and password), and the address and port for the MQTT broker we are going to use. At the end of this note we show how to configure a Mosquitto broker.
One-way authentication
This way we can authenticate the server, that is, we can trust it is the one to whom we want to connect, but the server has no idea who can we be.
This is the simplest configuration and we only have to provide the CA certificate filename in the parameter ssl_ca_cert, the certificate has to be stored in the fs directory. This indicates the broker has to be validated.
[Mar 31 17:21:18.360] mgos_mqtt_conn.c:435 MQTT0 connecting to 192.168.5.3:8883 [Mar 31 17:21:18.585] mongoose.c:4906 0x3ffca41c ciphersuite: TLS-ECDHE-RSA-WITH-AES-128-GCM-SHA256 [Mar 31 17:21:20.404] mgos_mqtt_conn.c:188 MQTT0 TCP connect ok (0) [Mar 31 17:21:20.414] mgos_mqtt_conn.c:235 MQTT0 CONNACK 0 [Mar 31 17:21:20.423] init.js:34 MQTT connected [Mar 31 17:21:20.437] init.js:26 Published:OK topic:/this/test/esp32_807A98 msg:CONNECTED!
Two-way (mutual) authentication
This way we can authenticate the server and the client, that is, now the server knows we should be the one who our certificate says we are. This dual process requires lots of processing and we’ll notice that connection establishment takes longer. In this configuration we must provide our certificate and key in the fs directory, and configure parameters ssl_cert and ssl_key appropriately; otherwise the broker might give us a clue in its log, as Mosquitto does:
Mar 31 17:30:52 Server mosquitto[2694]: OpenSSL Error: error:140890C7:SSL routines:ssl3_get_client_certificate:peer did not return a certificate
Brokers: Mosquitto
These are minimal configurations for Mosquitto, take them as a quick help and not as a reference. Paths are in GNU/Linux form and we should put our certificates there.
One-way authentication (broker authentication)
listener 8883 192.168.5.1 log_dest syslog cafile /etc/mosquitto/certs/ca.crt certfile /etc/mosquitto/certs/server.crt keyfile /etc/mosquitto/certs/server.key
Mutual (two-way) authentication
listener 8883 192.168.5.1 log_dest syslog cafile /etc/mosquitto/certs/ca.crt certfile /etc/mosquitto/certs/server.crt keyfile /etc/mosquitto/certs/server.key require_certificate true
Example
Companion example code available in Github, here and here. We’ll also need server credentials, I left a set here so we can do this easily.