Demo 30: How to use Arduino ESP32 MQTTS with MQTTS Mosquitto broker (TLS/SSL)

1. Introduction
Arduino-ESP32 SDK has been updated and new WiFiClientSecure library not working any more. In order to fix it, please using the old github commit or download the zip file here.
After downloading the old commit; extract it; go to the libraries folder; copy the
WiFiClientSecure folder; replace the current WiFiClientSecure folder (in Arduino/hardware/espressif/esp32/libraries or refer here) by the copied WiFiClientSecure folder.
- In this tutorial, I will show you how to use ESP32 MQTTS with MQTTS Mosquitto broker (TLS/SSL).
- In order to make this tutorial, please refer topics:
How to set up secure transportation for MQTT Mosquitto broker with SSL/TLS
Demo 29: How to use HTTPS in Arduino ESP32
Demo 14: How to use MQTT and Arduino ESP32 to build a simple Smart home system
- The requirement for this demo: ESP32 with a LED on it will turn On/Off when subscribing a topic "smarthome/room1/led" with values (0: off, 1: on).
2. Steps
- After doing the steps in this demo How to set up secure transportation for MQTT Mosquitto broker with SSL/TLS, you have to extract the content of ca.crt for SSL/TLS handshake phase by running the command:  
cat /etc/mosquitto/certs/ca.crt
 Figure: Extract content of ca.crt
- Get the IP address of machine that run MQTT mosquitto by running command: ifconfig or if you use MDNS for that machine you can follow this tutorial to get the IP directly from ESP32: How to get the IP address of a node by its mdns host name in Arduino ESP32.
- We will use WiFiClientSecure class for SSL/TLS handshake phase and PubSubClient library for ESP32 MQTT communication. Please see the topics that I mentioned above.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#include <ESPmDNS.h>

/* change it with your ssid-password */
const char* ssid = "dd-wrt";
const char* password = "0000000000";
/* this is the MDNS name of PC where you installed MQTT Server */
const char* serverHostname = "iotsharing";

const char* ca_cert = \ 
"-----BEGIN CERTIFICATE-----\n" \
"MIIDpzCCAo+gAwIBAgIJAOHc50EeJ6aeMA0GCSqGSIb3DQEBDQUAMGoxFzAVBgNV\n" \
"BAMMDkFuIE1RVFQgYnJva2VyMRYwFAYDVQQKDA1Pd25UcmFja3Mub3JnMRQwEgYD\n" \
"VQQLDAtnZW5lcmF0ZS1DQTEhMB8GCSqGSIb3DQEJARYSbm9ib2R5QGV4YW1wbGUu\n" \
"bmV0MB4XDTE3MDgyNzAyMDQwNFoXDTMyMDgyMzAyMDQwNFowajEXMBUGA1UEAwwO\n" \
"QW4gTVFUVCBicm9rZXIxFjAUBgNVBAoMDU93blRyYWNrcy5vcmcxFDASBgNVBAsM\n" \
"C2dlbmVyYXRlLUNBMSEwHwYJKoZIhvcNAQkBFhJub2JvZHlAZXhhbXBsZS5uZXQw\n" \
"ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC8mQfR058k7LBV7Xt6RiZL\n" \
"BIpC5ewSweAnsaS6Ue+jx6uruJsccnIJbiHJVjOcSYV3JLMt3un7d0JTottW6Zx/\n" \
"VleYC4CUzf3bcHLe7Qhl0veP9QAdZceblMCbEqAM9227EaXKQVzAYGwRnuxvfJM7\n" \
"P84iu2J/zB4o+AEWUJDIW38SO4b+0i1FYHmKKxEx7dztDyCJvTsn35wX3oKlJ5e+\n" \
"na/6csD+Ngh9QQ+wDd02TBqXKB7UXyRT5ECesu19U6CTE7Wr9xECbDO262aD6GtC\n" \
"HpeSAWqa6HKbKjZ20pL5V5ceS85TdWbvPdVrFUDWMIhK9dNuwhIK0s6VyRcJkbe5\n" \
"AgMBAAGjUDBOMB0GA1UdDgQWBBQPZ0u1jIg65jT3Th42VGMnya6VDDAfBgNVHSME\n" \
"GDAWgBQPZ0u1jIg65jT3Th42VGMnya6VDDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3\n" \
"DQEBDQUAA4IBAQB8JrNsV32aXBOLSX8WqoHuU2NOJH+1fTdGDLYLEAPe/x3YxkNC\n" \
"MJDx8TGLSQsz4L0kCsLEQ/qsnkuPJUt3x7eNIMOrvS+zDv9wXqnGwMgeAOtEkG5n\n" \
"NbPezM50ovgZAuEZMphp2s/Zl0EROydnqpkweWa5bxYRkiQBlp0nUkCtec3PZ6iO\n" \
"QVPj/bHHi4T3jkbL0+oLNShv9Zw9hr6BkKCVqeHe9prlOMVuEJOVrEKzkhhAY90p\n" \
"Wwrj+OQYCLllJVD9VQhLVOXLg1bSuqkld3PCQBFNvrvk4Up61wuu/Oj5c5g8vwYd\n" \
"0ul29sU3heTw4ZXifpbMXRM36LFNH5uLrSba\n" \
"-----END CERTIFICATE-----\n";

/* create an instance of WiFiClientSecure */
WiFiClientSecure espClient;
PubSubClient client(espClient);

/*LED GPIO pin*/
const char led = 4;

/* topics */
#define COUNTER_TOPIC    "smarthome/room1/counter"
#define LED_TOPIC     "smarthome/room1/led" /* 1=on, 0=off */

long lastMsg = 0;
char msg[20];
int counter = 0;

void receivedCallback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message received: ");
  Serial.println(topic);

  Serial.print("payload: ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();
  /* we got '1' -> on */
  if ((char)payload[0] == '1') {
    digitalWrite(led, HIGH); 
  } else {
    /* we got '0' -> on */
    digitalWrite(led, LOW);
  }

}

void mqttconnect() {
  /* Loop until reconnected */
  while (!client.connected()) {
    Serial.print("MQTT connecting ...");
    /* client ID */
    String clientId = "ESP32Client";
    /* connect now */
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");
      /* subscribe topic */
      client.subscribe(LED_TOPIC);
    } else {
      Serial.print("failed, status code =");
      Serial.print(client.state());
      Serial.println("try again in 5 seconds");
      /* Wait 5 seconds before retrying */
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  // We start by connecting to a WiFi network
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  /* set led as output to control led on-off */
  pinMode(led, OUTPUT);

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  /*setup MDNS for ESP32 */
  if (!MDNS.begin("esp32")) {
      Serial.println("Error setting up MDNS responder!");
      while(1) {
          delay(1000);
      }
  }
  /* get the IP address of server by MDNS name */
  Serial.println("mDNS responder started");
  IPAddress serverIp = MDNS.queryHost(serverHostname);
  Serial.print("IP address of server: ");
  Serial.println(serverIp.toString());
  /* set SSL/TLS certificate */
  espClient.setCACert(ca_cert);
  /* configure the MQTT server with IPaddress and port */
  client.setServer(serverIp, 8883);
  /* this receivedCallback function will be invoked 
  when client received subscribed topic */
  client.setCallback(receivedCallback);
  
}
void loop() {
  /* if client was disconnected then try to reconnect again */
  if (!client.connected()) {
    mqttconnect();
  }
  /* this function will listen for incomming 
  subscribed topic-process-invoke receivedCallback */
  client.loop();
  /* we increase counter every 3 secs
  we count until 3 secs reached to avoid blocking program if using delay()*/
  long now = millis();
  if (now - lastMsg > 3000) {
    lastMsg = now;
    if (counter < 100) {
      counter++;
      snprintf (msg, 20, "%d", counter);
      /* publish the message */
      client.publish(COUNTER_TOPIC, msg);
    }else {
      counter = 0;  
    }
  }
}
3. Result

Post a Comment

20 Comments

Anonymous said…
I keep getting the following error in my broker's logs:

New connection from xxx.yyy.zzz.ddd on port 8883.
1513416718: OpenSSL Error: error:14094412:SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate
1513416718: OpenSSL Error: error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure
1513416718: Socket error on client , disconnecting.

I followed the procedure exactly as stated. The only real difference is that my device connects from an external location to my home MQTT broker (I opened port 8883 and forwarded it to the broker). I can see the connection attempts, but the SSL handshake fails every time... is there a known solution for that?
1. are you able to connect it from local?
2. If yes, Are you able to ping it from external?
I'm also having problems connecting to my Mosquito server.
My broker's log gets
1513549085: New connection from 46.189.241.12 on port 8883.
1513549085: OpenSSL Error: error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure
1513549085: Socket error on client (null), disconnecting.

I also tried the test.mosquitto.org broker with their own certificate test.mosquitto.org/ssl/mosquitto.org.crt but always get
the same message on the Serial console:

Attempting MQTT connection...failed, rc=-2 try again in 5 seconds
Hi all,

Arduino-ESP32 SDK has been updated and new WiFiClientSecure library not working any more. In order to fix it, please using the old github commit or download the zip file here.

After downloading the old commit; extract it; go to the libraries folder; copy the
WiFiClientSecure folder; replace the current WiFiClientSecure folder (in Arduino/hardware/espressif/esp32/libraries or refer here) by the copied WiFiClientSecure folder.
Constan said…
Excelent article.

Im trying connect to Sap Leonardo (mqtt-tls) , it requiere 3 certs (root ca, cert, key). The problem is: connect, publish but "not publish" in sap leonardo cockpit dashboard ... in Python paho use similar code and work fine. Mqtt for arduino esp32 have some debug or message code error or logging for diagnostic some error and outcomming message?

(in arduino esp32 work with 3 certs and 2 too, maybe I must test with idf-c++ )
Vinicius said…
Thank you so much!
I was looking for resolving a name with the ESP32 to conecta to my mosquitto server.
Unknown said…
I tried using the above code with the necessary steps and tried connecting to "test.mosquitto.org" my esp32 is constantly rebooting while trying to connect to mqtt server i am sharing the serial prints below :

---------------------Serial monitor-------------------------------------------------

Connecting to Hocket
..
WiFi connected
IP address:
192.168.0.105
mDNS responder started
IP address of server: 0.0.0.0
MQTT connecting ...Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400f4744 PS : 0x00060030 A0 : 0x800feca5 A1 : 0x3ffb1e20
A2 : 0x3ffbaa70 A3 : 0x00000190 A4 : 0x8008e98c A5 : 0x3ffb1af0
A6 : 0x00000000 A7 : 0x3ffb0060 A8 : 0xfefefefe A9 : 0x3ffb1e10
A10 : 0x3ffba820 A11 : 0x00000000 A12 : 0x00000190 A13 : 0x3ffba9b0
A14 : 0x00000020 A15 : 0x00000019 SAR : 0x00000018 EXCCAUSE: 0x0000001c
EXCVADDR: 0xfefeff26 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000

Backtrace: 0x400f4744:0x3ffb1e20 0x400feca2:0x3ffb1e40 0x400d2ba2:0x3ffb1e60 0x400d297d:0x3ffb1e80 0x400d2a7f:0x3ffb1ea0 0x400d2aa9:0x3ffb1ec0 0x400d31aa:0x3ffb1ef0 0x400d3382:0x3ffb1f30 0x400d1b49:0x3ffb1f60 0x400d1d9b:0x3ffb1f90 0x400d3e0d:0x3ffb1fb0 0x4008e779:0x3ffb1fd0

Rebooting...
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1100
load:0x40078000,len:10088
load:0x40080400,len:6380
entry 0x400806a4
ishan said…
I'm also trying to use the above code with the necessary steps and tried connecting to "test.mosquitto.org" my ESP32 is constantly rebooting while trying to connect to MQTT server

-------Serial output ---------

MQTT connecting ...Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x400f4b44 PS : 0x00060230 A0 : 0x800ff0a5 A1 : 0x3ffb1e00
A2 : 0x3ffbaa70 A3 : 0x00000190 A4 : 0x8008f13c A5 : 0x3ffb1ad0
A6 : 0x00000000 A7 : 0x3ffb0060 A8 : 0xfefefefe A9 : 0x3ffb1df0
A10 : 0x3ffba820 A11 : 0x00000000 A12 : 0x00000190 A13 : 0x3ffba9b0
A14 : 0x00000020 A15 : 0x00000019 SAR : 0x00000018 EXCCAUSE: 0x0000001c
EXCVADDR: 0xfefeff26 LBEG : 0x4000c46c LEND : 0x4000c477 LCOUNT : 0x00000000

Any help would be highly appreciated.

ccmcwolf said…
Link for MQTT Library you use?
ishan said…
Hi,
Thanks for the attention. Please find below the link for MQTT library,

http://downloads.arduino.cc/libraries/github.com/knolleary/PubSubClient-2.4.0.zip

Arduino IDE 1.8.3
MarcPous said…
After 10 hour of work, with problem:
1584535555: OpenSSL Error[0]: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate

Is solved after downgrade to PubSubClient-2.4.0

Downgrade WifiClientSecure don't work, i think only exist V1

Thanks to everyone
MarcPous said…
Sorry, last message is incorrect.

Need restart arduino ide after Downgrade WifiClientSecure to work

PubSubClient work fine with all versions (Tested PubSubClient con versión 2.7)

Thanks
Vasko said…
@MarcPous can you share the zip with us please?
jorgegene said…
@Vasko Did you get the zip? I'm on the same spot, impossible to make it work getting rc=-2.
If you have any advice or there is something I can help just mail me.

Thanks for the help.
Selvamani1991 said…
Hi,

ESP32-Mqtt was not connected using Azure SSL Certificate

I am using the below code for connecting with ssl certificate was not working.

#include
const char* ssid = "xxx"; // your network SSID (name of wifi network)
const char* password = "xxx"; // your network password
const char* server = "xxx.azure-devices.net"; // Server URL
const char* test_root_ca=
"-----BEGIN CERTIFICATE-----\n"

"-----END CERTIFICATE-----\n";

// You can use x.509 client certificates if you want
const char* test_client_key =
"-----BEGIN RSA PRIVATE KEY-----\n"

"-----END RSA PRIVATE KEY-----\n"; //to verify the client

const char* test_client_cert =
"-----BEGIN CERTIFICATE-----\n"

"-----END CERTIFICATE-----\n"; //to verify the client
WiFiClientSecure client;
void setup() {
//Initialize serial and wait for port to open:
Serial.begin(115200);
delay(100);
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// attempt to connect to Wifi network:
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
// wait 1 second for re-trying
delay(1000);
}
Serial.print("Connected to ");
Serial.println(ssid);
client.setCACert(test_root_ca);
client.setCertificate(test_client_cert); // for client verification
client.setPrivateKey(test_client_key); // for client verification
Serial.println("\nStarting connection to server...");
if (!client.connect(server, 8883)){
Serial.println("Connection failed!");
}
else {
Serial.println("Connected to server!");
}
}
void loop() {
// do nothing
}
Anonymous said…
Excellent article!

The example worked with old "WiFiClientSecure" library but failed with the latest.

After activating the verbose logging I've got the following error: "(-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" (see article: https://github.com/espressif/arduino-esp32/issues/1015).

One way to solve it is the set the CN (Common Name) field of the CA certificate to the IP of the server where MQTT server is running.
Following the guide: http://www.steves-internet-guide.com/mosquitto-tls/ I managed to get a set of certificates that work with the latest libraries (Arduino ESP32 1.0.5 and PubSubClient 2.8).

"generate-CA.sh" script needs a little update!
Unknown said…
I'm getting this log from serial monitor,

13:37:59.530 -> MQTT connecting ...failed, status code =-2try again in 5 seconds

What means "status code=-2"?
Unknown said…
@Tech It Yourself, Can you share the link for old github code for wificlientsecure
Unknown said…
@Selvamani1991 Did you find the issue. I'm also trying to connect to secured MQTT.
Guy Turcotte said…
Hello, I was able to use the current WiFiClientSecure library with the code.

One aspect that is important: the Common Name used in the certificate must be the same as the first parameter used for the client.setServer() call.

- If you have used the server IP address for the Common Name field, you must use the IP address in the client.setServer() call.

- If you have used the server DNS name for the Common Name, then use it also for the client.setServer() call.