0

I am trying to connect my ESP8266 board on my server in HiveMQ. Knowing that the in update would be a TLS-based connection, I had to adapt my code. However, so far I have not been able to stabilize the connection. Although I can upload the code to esp, it sends me the message:
Attempting MQTT connection...failed, rc=-2 try again in 5 seconds.

Note: The hivemq Guide is wrong, many problems) I have installed OPENssl to get the certificates, but none of the three appeared to work. I'm waiting for help, please.

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>

//---- WiFi settings
const char* ssid ="myssid";
const char* password = "mypass";
//---- MQTT Broker settings
const char* mqtt_server =  "06f141f33c074deab7c362e9cf1f3eee.s1.eu.hivemq.cloud";
// This is my broker
const char* mqtt_username = "myuser";
const char* mqtt_password = "mypass";
const int mqtt_port =8883;

WiFiClientSecure espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;

#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];

const char* sensor1_topic= "temperatura";
const char* sensor2_topic="umidade";

const char *x509CA PROGMEM = R"EOF("
-----BEGIN CERTIFICATE-----
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
nLRbwHOoq7hHwg==
-----END CERTIFICATE-----
")EOF";

void setup() {

Serial.begin(9600);
Serial.print("\nConnecting to ");
Serial.println(ssid);

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("\nWiFi connected\nIP address: ");
Serial.println(WiFi.localIP());

while (!Serial) delay(1);


espClient.setCACert((const uint8_t*)x509CA, sizeof(x509CA) - 1);
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}

void loop() {

  if (!client.connected()) reconnect();
  client.loop();

publishMessage(sensor1_topic,String("XXXX"),true);    
publishMessage(sensor2_topic,String("XXXX"),true);
}

//=======================================================================Function=================================================================================

void reconnect() {
// Loop until we’re reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection…");
String clientId = "ESP8266Client"; // Create a random client ID
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str(), mqtt_username, mqtt_password)) {
Serial.println("connected");

  client.subscribe(sensor1_topic);   // subscribe the topics here
  //client.subscribe(command2_topic);   // subscribe the topics here
} else {
  Serial.print("failed, rc=");
  Serial.print(client.state());
  Serial.println(" try again in 5 seconds");   // Wait 5 seconds before retrying
  delay(5000);
}
}
}

//=======================================
// This void is called every time we have a message from the broker

void callback(char* topic, byte* payload, unsigned int length) {
String incomingMessage = "HELLO";
for (int i = 0; i < length; i++) incomingMessage+=(char)payload[i];
Serial.println("Message arrived");
// check for other commands
/* else if( strcmp(topic,command2_topic) == 0){
if (incomingMessage.equals(“1”)) { } // do something else
}
*/
}

//======================================= publising as string
void publishMessage(const char* topic, String payload , boolean retained){
if (client.publish(topic, payload.c_str(), true))
Serial.println("Published");
}

avariant
  • 2,234
  • 5
  • 25
  • 33

2 Answers2

0

After talking with another colleague, he came to a conclusion that perhaps an ESP8266 does not support TLS connections due to its low memory capacity, and that a better resolution is to bypass an encryption by adding the following code: replace: espClient.setCACert((const uint8_t*)x509CA, sizeof(x509CA) - 1); for: espClient.setInsecure();

  • The `espClient.setInsecure()` does not disable the TLS connection. HiveMQ won't let you connect with a non-TLS connection, so the ESP8266 is doing all the key exchange and encryption necessary to create a TLS connection. All `setInsecure()` is doing is disabling the check of the server certificate against a trusted CA certificate, so you can't be sure the server you're connecting to is really the Hive MQ server. So this points to incorrectly specifying the root CA certificate. (I'm currently trying the same thing as you with similar results so if I have any success I'll post an update.) – cguk70 Aug 24 '22 at 16:26
0

I also had plans to connect an ESP8266 board to HiveMQ when I saw this question. Although the original poster has decided not to check the server certificate against a CA certificate, I did manage to get this part working so thought I would still post my answer as it may be helpful.

When using WifiClientSecure there are several options that can be used to check the remote server's identity. These options are controlled by separate method calls (see also BearSSL Wifi Classes):

  • setInsecure() - this bypasses the checking of the server certificate completely, so although the TLS connection is established we cannot guarantee that the server is actually HiveMQ.

  • setKnownKey() - we provide the complete public key we expect to receive from HiveMQ (can be found using openssl s_client). The connect will fail if HiveMQ update their certificate.

  • setFingerprint() - similar to setKnownKey() but here we just check the SHA1 fingerprint of the server's public key. Again, the connect will fail if HiveMQ update their certificate.

  • setTrustAnchors() - this will check that the server certificate has been signed by a certificate in the provided CA list and check the identity of the server. This has the advantage of working even if HiveMQ update their server certificate - as long as their CA remains the same. CA certificates typically have a longer lifespan than server certificates. However, in order to validate the server certificate, the WifiClientSecure object needs to know the current time, which we can set using the setX509Time() method. This means we need to fetch the current time from an NTP server. (Note setCACert() is deprecated in the latest code base).

The following code shows a connection to HiveMQ using setTrustAnchors() with a single CA certificate. (Again this certficate can be found using openssl s_client to connect to HiveMQ and look at which CA signed the certificate).

#include <NTPClient.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <WiFiUdp.h>

#include <PubSubClient.h>

const String MQTT_HOST("0123456789abcdef0123456789abcdef.s1.eu.hivemq.cloud");
const int    MQTT_PORT = 8883 ;
const String MQTT_CLIENT_ID("test_hive_client_1");
const String MQTT_USER("mqttuser"); 
const String MQTT_PWD("secretpassword"); 

String wifiSid = "MY_WIFI_SID";
String wifiPwd = "anothersecretpassword";

// The CA certificate used to sign the HiveMQ server certificate 
static const char caCert[] PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFFjCCAv6gAwIBAgIRAJErCErPDBinU/bWLiWnX1owDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMjAwOTA0MDAwMDAw
WhcNMjUwOTE1MTYwMDAwWjAyMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNTGV0J3Mg
RW5jcnlwdDELMAkGA1UEAxMCUjMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQC7AhUozPaglNMPEuyNVZLD+ILxmaZ6QoinXSaqtSu5xUyxr45r+XXIo9cP
R5QUVTVXjJ6oojkZ9YI8QqlObvU7wy7bjcCwXPNZOOftz2nwWgsbvsCUJCWH+jdx
sxPnHKzhm+/b5DtFUkWWqcFTzjTIUu61ru2P3mBw4qVUq7ZtDpelQDRrK9O8Zutm
NHz6a4uPVymZ+DAXXbpyb/uBxa3Shlg9F8fnCbvxK/eG3MHacV3URuPMrSXBiLxg
Z3Vms/EY96Jc5lP/Ooi2R6X/ExjqmAl3P51T+c8B5fWmcBcUr2Ok/5mzk53cU6cG
/kiFHaFpriV1uxPMUgP17VGhi9sVAgMBAAGjggEIMIIBBDAOBgNVHQ8BAf8EBAMC
AYYwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMBIGA1UdEwEB/wQIMAYB
Af8CAQAwHQYDVR0OBBYEFBQusxe3WFbLrlAJQOYfr52LFMLGMB8GA1UdIwQYMBaA
FHm0WeZ7tuXkAXOACIjIGlj26ZtuMDIGCCsGAQUFBwEBBCYwJDAiBggrBgEFBQcw
AoYWaHR0cDovL3gxLmkubGVuY3Iub3JnLzAnBgNVHR8EIDAeMBygGqAYhhZodHRw
Oi8veDEuYy5sZW5jci5vcmcvMCIGA1UdIAQbMBkwCAYGZ4EMAQIBMA0GCysGAQQB
gt8TAQEBMA0GCSqGSIb3DQEBCwUAA4ICAQCFyk5HPqP3hUSFvNVneLKYY611TR6W
PTNlclQtgaDqw+34IL9fzLdwALduO/ZelN7kIJ+m74uyA+eitRY8kc607TkC53wl
ikfmZW4/RvTZ8M6UK+5UzhK8jCdLuMGYL6KvzXGRSgi3yLgjewQtCPkIVz6D2QQz
CkcheAmCJ8MqyJu5zlzyZMjAvnnAT45tRAxekrsu94sQ4egdRCnbWSDtY7kh+BIm
lJNXoB1lBMEKIq4QDUOXoRgffuDghje1WrG9ML+Hbisq/yFOGwXD9RiX8F6sw6W4
avAuvDszue5L3sz85K+EC4Y/wFVDNvZo4TYXao6Z0f+lQKc0t8DQYzk1OXVu8rp2
yJMC6alLbBfODALZvYH7n7do1AZls4I9d1P4jnkDrQoxB3UqQ9hVl3LEKQ73xF1O
yK5GhDDX8oVfGKF5u+decIsH4YaTw7mP3GFxJSqv3+0lUFJoi5Lc5da149p90Ids
hCExroL1+7mryIkXPeFM5TgO9r0rvZaBFOvV2z0gp35Z0+L4WPlbuEjN/lxPFin+
HlUjr8gRsI3qfJOQFy/9rKIJR0Y/8Omwt/8oTWgy1mdeHmmjk7j1nYsvC9JSQ6Zv
MldlTTKB3zhThV1+XWYp6rjd5JW1zbVWEkLNxE7GJThEUG3szgBVGP7pSWTUTsqX
nLRbwHOoq7hHwg==
-----END CERTIFICATE-----
)EOF";

X509List caCertList(caCert); 

// Use secure client to handle TLS connection. 
WiFiClientSecure wifiClient ;
PubSubClient mqttClient(wifiClient) ;

// BearSSL needs current time to validate certificate. 
WiFiUDP ntpUDP; 
NTPClient timeClient(ntpUDP, "pool.ntp.org", 0); 

// Publish current time to MQTT every 5 seconds
#define MQTT_TIME_UPDATE_PERIOD 5000 
unsigned long nextTimeUpdate = 0 ;

void mqttCallback(const char* topic, byte* payload, unsigned int length)
{
  // Payload may not be null terminated. 
  char value[length+1]; 
  memcpy(value,payload, length); 
  value[length] = '\0'; 
  
  Serial.print("MQTT update: "); 
  Serial.print(topic);
  Serial.print(":");
  Serial.println(value); 
}

void connectToWifi() 
{
  WiFi.mode(WIFI_STA); 

  WiFi.disconnect(); 
  WiFi.begin(wifiSid.c_str(), wifiPwd.c_str()); 

  Serial.println("");
  Serial.print("Connecting to " + wifiSid + " - "); 

  while (WiFi.status() != WL_CONNECTED)
  {
      Serial.print("."); 
      delay(1000); 
  }
  
  Serial.println(""); 
  Serial.print("Connected, IP Address = ");
  Serial.println(WiFi.localIP()); 
}

void checkWifi()
{
  if ( WiFi.status() != WL_CONNECTED )
  {
    connectToWifi(); 
  }
}

void checkMQTT()
{
  if ( !mqttClient.connected() )
  {
    String details = MQTT_HOST + "/" ; 
    details += MQTT_PORT ;
    
    Serial.println("Connecting to MQTT server: " + details); 
     
    mqttClient.setServer(MQTT_HOST.c_str(), MQTT_PORT);   
    
    while( !mqttClient.connected() )
    {
      Serial.println(".");

      // secure client needs to know the current time. 
      timeClient.update(); 
      time_t now = (time_t) timeClient.getEpochTime();
      wifiClient.setX509Time(now); 

      int ret = mqttClient.connect(MQTT_CLIENT_ID.c_str(), MQTT_USER.c_str(), MQTT_PWD.c_str());

      Serial.print("MQTT Connect returned: ");
      Serial.println(ret);

      if ( !mqttClient.connected() )
        delay(5000); 
    }
    
    Serial.println("Connected to MQTT"); 

    mqttClient.setCallback(mqttCallback); 
    mqttClient.subscribe("test/value1"); 
  }
}

void setup() {

  Serial.begin(9600); 

  Serial.println("Starting"); 
  
  // Load certificates
  wifiClient.setTrustAnchors(&caCertList); 

  connectToWifi(); 
  checkMQTT(); 

  nextTimeUpdate = millis() + MQTT_TIME_UPDATE_PERIOD ;
}

void loop() {

  checkWifi();
  checkMQTT();
  mqttClient.loop();

  if ( millis() > nextTimeUpdate )
  {
      // publish the current time to MQTT. 
      timeClient.update(); 
      const char* payload = timeClient.getFormattedTime().c_str(); 
      mqttClient.publish("test/current-time", payload, true); 

      nextTimeUpdate = millis() + MQTT_TIME_UPDATE_PERIOD ;
  }
  
  delay(50);
}
cguk70
  • 611
  • 3
  • 7