4

I have ESP8266 which is connecting to MQTT broker and it is working ok using user+pass with following code:

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

const char* ssid = "WIFINAME";
const char* password = "WIFI_PASS";

const char* mqtt_server = "SERVER_IP";
const char* mqttUser = "user";
const char* mqttPassword = "pass";

WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
int value = 0;

void setup_wifi() {

  delay(10);
  // 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(".");
  }

  randomSeed(micros());

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++) {
    Serial.print((char)payload[i]);
  }
  Serial.println();

  // Switch on the LED if an 1 was received as first character
  if ((char)payload[0] == '1') {
    digitalWrite(BUILTIN_LED, LOW);   // Turn the LED on (Note that LOW is the voltage level
    // but actually the LED is on; this is because
    // it is active low on the ESP-01)
  } else {
    digitalWrite(BUILTIN_LED, HIGH);  // Turn the LED off by making the voltage HIGH
  }
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    if (client.connect(clientId.c_str(), mqttUser, mqttPassword)) {
      Serial.println("connected");
      client.subscribe("CoreElectronics/test");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  pinMode(BUILTIN_LED, OUTPUT);
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
}

void loop() {

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

As this is insecure usage I have setup TLS on MQTT broker and I can connect over command line:

mosquitto_sub --cafile ca.crt -h server_ip  -t "#" -p 8883 -d --cert client.crt --key client.key

Problem is that I cannot find any working (for me) sample with using TLS connection on ESP8266 client.

I have tried generating self-signed certs by manually script and over LetsEncrypt.

Thank you

1
  • 1
    If PSK is acceptable, there are probably some tutorials over at adafruit.com or discussions in their forum.
    – st2000
    Feb 21, 2020 at 12:58

2 Answers 2

7

You could make the following changes to your code by making use of WifiClientSecure (which is already part of the ESP8266 Wifi library).

The tricky part is finding out the SHA1 fingerprint for your own MQTT server and hard coding it into the *fingerprint PROGMEM = "..." part (for example by examining the certificate via a PC browser and copying the SHA1 fingerprint).

Alternatively, you could set the connection to setInsecure. This means that the connection will be encrypted but it will accept any server certificate without checking.

...
const char* mqttPassword = "pass";

WiFiClientSecure espClient;     // <-- Change #1: Secure connection to MQTT Server 
PubSubClient client(espClient);

// Change #2: Set the SHA1 fingerprint for the connection -->
static const char *fingerprint PROGMEM = "44 14 9A 3F C3 E9 F1 F3 84 1A B4 9F B6 4D 19 8A B2 92 31 D6";
...
...
void setup() {
    ...
    setup_wifi();

    espClient.setFingerprint(fingerprint);   // <-- Change #3: Set the SHA1 fingerprint
    // Alternative: espClient.setInsecure;

    client.setServer(mqtt_server, 8883);  // <-- Change #4: Set the port number to 8883
    client.setCallback(callback);
 ...

Good luck!

7
  • where I need to put ca.crt, client.crt and client.key?
    – iWizard
    Feb 21, 2020 at 17:15
  • You won't need them if you use the setFingerprint method. You only need the fingerprint.
    – StarCat
    Feb 21, 2020 at 17:25
  • I get error 'class PubSubClient' has no member named 'setFingerprint' and also for setInsecure. Which PubSubClient is latest and best for use?
    – iWizard
    Feb 21, 2020 at 20:43
  • solved. changed client.setFingerprint(fingerprint); -> espClient.setFingerprint(fingerprint);
    – iWizard
    Feb 21, 2020 at 21:18
  • My bad, I will fix it in the answer.
    – StarCat
    Feb 21, 2020 at 21:21
2

There is an example of client certificates here.

https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFiClientSecure/examples/WiFiClientSecure/WiFiClientSecure.ino

I believe the answer by @StarCat should be expanded to use the ca cert and client certs. With MQTT, we don't want clients being faked either.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.