I want to setup an MQTT client on my esp. I was able to do it without SSL, and it is working fine with cloud mqtt providers if it is not secure. I used it with https://www.emqx.com/en/cloud and it was good. Now i want to implement secure connection feature.
For this, i pick https://www.hivemq.com because it is free and allows secure connections. I got a CA from the server with openssl on windows with the following command:
Code: Select all
openssl s_client -connect <IDHERE>accountID</IDHERE>.s2.eu.hivemq.cloud:8883
Code: Select all
keytool -exportcert -keystore hivemq.jks -alias hivemq -keypass <PWHERE> -storepass <PWHERE>-rfc -file hivemq-server-cert.pem
The CA looks fine for me. ( I also tried with other CAs like one of my own CA from https://zerossl.com but it obviously did not work since the dns does not match )
I got the following error on the ESP32 side on the Serial.
Code: Select all
E (25952) esp-tls: mbedtls_ssl_handshake returned -0x2700
E (25956) esp-tls: Failed to open new connection
E (25956) TRANS_SSL: Failed to open a new connection
E (25957) MQTT_CLIENT: Error transport connect
Here is my sketch:
Code: Select all
const char* mqttServer = "mqtts://<IDHERE>accountID</IDHERE>.s1.eu.hivemq.cloud";
const char* mqtt_user = "test";
const char* mqtt_pwd = "test1234567";
esp_mqtt_client_config_t mqtt_cfg;
esp_mqtt_client_handle_t mqtt_client;
const char* pemFile = R"literal(
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----)literal";
inline esp_err_t mqttEvent(esp_mqtt_event_handle_t event) {
esp_mqtt_client_handle_t mqttclient = event->client;
switch (event->event_id) {
case MQTT_EVENT_CONNECTED:
onMqttConnect(mqttclient);
break;
case MQTT_EVENT_DISCONNECTED:
mqttConnected = false;
break;
case MQTT_EVENT_DATA:
onMqttData(event);
break;
default:
break;
}
return ESP_OK;
}
const size_t mqttJsonSize = 15000;
String mqttBuffer;
static const inline void setupMQTT(){
mqttBuffer.reserve(mqttJsonSize);
Serial.print("mqtt_setup: "); Serial.println(mqttServer);
mqtt_cfg.event_handle = mqttEvent;
mqtt_cfg.uri = mqttServer;
//mqtt_cfg.port = 15902; // this port is working fine with non ssl connection
mqtt_cfg.port = 8883; // current mqtts port.
//mqtt_cfg.task_stack = 10048; // it was just a test
mqtt_cfg.username=(const char *)mqtt_user;
mqtt_cfg.password=(const char *)mqtt_pwd;
//mqtt_cfg.use_secure_element = true; // not supported error?
mqtt_cfg.cert_pem = (const char *)pemFile;
//mqtt_cfg.client_key_pem = (const char *)keyPemFile; // it was a test. i did not get a key with the openssl command.
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
if( esp_mqtt_client_start(mqtt_client) == ESP_OK){
Serial.println("MQTT init success."); // this line prints with or without TLS
}else{
Serial.println("Problem on mqtt INIT");
}
}
void onMqttConnect(esp_mqtt_client_handle_t client) {
mqttConnected = true;
esp_mqtt_client_subscribe(client, receiveTopic, 0);
Serial.print("subscribed to: "); Serial.println(receiveTopic);
}
void onMqttData(esp_mqtt_event_handle_t event) {
// working with non SSL
boolean packageOk = false;
mqttBuffer += String(event->data).substring(0, event->data_len);
if(mqttBuffer.length() >= event->total_data_len){packageOk = true;}
if(packageOk){
// packet is ok to process.
}
}
Code: Select all
CONNECTED(000001A4)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = *.s2.eu.hivemq.cloud
verify return:1
---
Certificate chain
0 s:CN = *.s2.eu.hivemq.cloud
i:C = US, O = Let's Encrypt, CN = R3
1 s:C = US, O = Let's Encrypt, CN = R3
i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
i:O = Digital Signature Trust Co., CN = DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
<HERE IS THE CA></HERE IS THE CA>
-----END CERTIFICATE-----
subject=CN = *.s2.eu.hivemq.cloud
issuer=C = US, O = Let's Encrypt, CN = R3
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 4520 bytes and written 446 bytes
Verification error: unable to get local issuer certificate
---
New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES128-GCM-SHA256
Session-ID: <sessionid>
Session-ID-ctx:
Master-Key: <masterkey>
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1633589568
Timeout : 7200 (sec)
Verify return code: 20 (unable to get local issuer certificate)
Extended master secret: yes
---
closed
- TOTAL_SKETCH 3.13 MB
USED_SKETCH 1.47 MB
TOTAL_HEAP 303.21 KB
FREE_HEAP 104.5 KB
TOTAL_PSRAM 4 MB
FREE_PSRAM 3.89 MB
USED_PSRAM 109.47 KB
TOTAL_FS 9.69 MB
USED_FS 780 KB
FREE_FS 8.93 MB
Also i'm not using WiFi, instead of a LAN8720 Ethernet Chip with the built in ETH library.
( every http or https request is working fine to my server with the zerossl CA and it is also running an Async webserver which is working fine too )
Thank you for your help.