Go Down

Topic: MQTT über TLS funktioniert nicht - Wemos D1 mini (ESP8266) (Read 146 times) previous topic - next topic

Tobi90as

Ich möchte mich mit meinem MQTT-Broker über TLS verbinden. Leider schaffe ich es nicht mit meinem Wemos D1 mini.
Warum ich mir sehr sicher bin, dass es an der TLS-Verbindung des ESP8266 liegt:
  • ohne TLS funktioniert alles, auch mit User und Passwort
  • auf einem ESP32 funktioniert auch die TLS verbindung anstandslos (natürlich mit entsprechenden Codeanpassungen), der Broker scheint also auch korrekt konfiguriert worden zu sein

Unten habe ich meinen auf das Wesentliche gekürzten Code angehängt. An zwei Stellen habe ich Anpassungen unternommen. Diese sind markiert mit

///////// Änderungszeile /////////

Mit dem dort auskommentierten Teil funktioniert es noch. Mit dem gegenwärtigen Code bekomme ich aber als Fehler-Code "-2" beim Verbindungsversuch mit dem MQTT-Broker.


Was gilt es noch zu beachten beim ESP8266 um eine TLS-Verbindung aufbauen zu können?

Übrigens: Ich weiß, dass ich aktuell keinen Fingerprint überprüfe und es deshalb noch nicht wirklich sicher ist, aber eines nach dem anderen. Das müsste ja auch schon so gehen, zumindest klappt das auf dem ESP32 auch so...


Code: [Select]

#include <ESP8266WiFi.h>


#include <WiFiClientSecure.h> //#include <WiFiClient.h>  ///////// Änderungszeile /////////



#include <PubSubClient.h>


char* ssid = "WLAN-*****";
char* password =  "********";

char* mqttServer = "192.168.178.35";
int mqttPort = 8883;
const char* mqttUser = "esp8266";
const char* mqttPassword = "*****";

WiFiClientSecure espClient; //WiFiClient espClient;  ///////// Änderungszeile /////////



PubSubClient client(espClient);


// SETUP ///////////////////////////////////////////////////////////////////
void setup() {
 
Serial.begin(9600);

ConnectWLAN();
ConnectMQTT();

}
// ENDE SETUP /////////////////////////////////////////////////////////////

void loop(){
  client.loop();  //allow the client to process incoming messages and maintain its connection to the server
 
   
}


void ConnectWLAN() {
 
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
      Serial.print("WiFi.status: ");
      Serial.println(WiFi.status());
      if (WiFi.status()==4) {
        Serial.println("Disconnecting...");
        //ESP.restart();
            WiFi.disconnect();
            WiFi.begin(ssid, password);
            delay(1000);
      }
    // wait 1 second for re-trying
      delay(1000);
      Serial.println("Connecting to WiFi..");
    }
    Serial.print("Connected to the WiFi network after: ");
    Serial.print(millis());
    Serial.println(" ms");
  }
}

void ConnectMQTT() {
  if (!client.connected()) { 
    client.setServer(mqttServer, mqttPort);
    client.setCallback(callback);
   
    while (!client.connected()) {
      Serial.print("Connecting to MQTT (");
      Serial.print(mqttServer);
      Serial.println(") ...");
   
      if (client.connect("Wemos_1",mqttUser,mqttPassword)) {
        Serial.println("connected to MQTT"); 
      } else {
        Serial.print("failed with state ");
        Serial.println(client.state());
        delay(3000);
      }
    }
    String text="Hello (" + String(random(1000)) + ")";
   
    client.subscribe("control/Wemos_1/RGB_LED");
    client.publish("debug",text.c_str());
  }
}

void callback(char* topic, byte* payload, unsigned int length) {
  // Parameter verarbeiten
    String Top=String((char*)topic);
    byte msgByte[length+1];    //Temporäres Byte-Array um Null-Byte anhängen zu können
    for (int i = 0; i < length; i++) {
        msgByte[i] = payload[i];
    }
    msgByte[length] = '\0';
    String msg=String((char*)msgByte); //Mit (char*) wird ein Typecast vom Byte-Pointer msgByte zu einem char-Pointer durchgeführt. Dieser kann von der Stringfunktion in einen String umgewandelt werden.
    Serial.print("Received message [");
    Serial.print(Top);
    Serial.print("]: ");
    Serial.println(msg);
  }


Danke schon mal für den ein oder anderen Tipp... Bin ziemlich ratlos...
Gruß Tobi

Tommy56

Ist der Port der Richtige für HTTPS?
Welchen HTTPS-Client benutzt Du?

Ich sehe nirgendwo, dass Du den SHA256-Code des Servers (setFingerprint) setzt.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Tobi90as

Der Port sollte stimmen. Zumindest ist das der Standardport für SSL/TLS bei MQTT.
Ich nutze (eigentlich?) keinen HTTPS-Client. Ich kommuniziere nur mit dem MQTT-Broker. Das ist bei mir mosquitto auf einem raspberry pi... Lässt sich bei MQTT überhaupt von HTTPS sprechen?

Zum Fingerprint: Wie ich oben schon geschrieben habe, ist der Umstand des fehlenden Fingerprints vielleicht ein Sicherheitsproblem, aber doch kein Grund keine Verbindung aufbauen zu können oder? Zumindest konnte ich auf einem ESP32 eine Verbindung ebenfalls ohne Fingerprint aufbauen...

Ich möchte erst die Verbindung so hinbekommen, dann kann ich mich daran machen, die Sache mit dem Fingerprint hinzuzufügen dachte ich mir. So weiß ich zumindest schon, dass nicht meine Fingerprint-Implementierung Schuld sein kann? Oder ist das hier etwa zwingend erforderlich für einen erfolgreichen Verbindungsaufbau?

Gruß Tobi

Tommy56

Bei BearSSL ist es Pflicht oder Du musst setInsecure benutzen.
Der normale Client kann keine verschlüsselte Verbindung handeln, wird also da auch keine eröffnen.

ESP32 != ESP8266

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Tobi90as

hm... ich dachte das ist optional den Fingerprint zu prüfen oder nicht...

Aber ich hab dennoch Probleme, das umzusetzen. Ich glaub ich verwende gar kein BearSSL oder woran erkenne ich das denn überhaupt in meinem Code oben? Sry, bin da leider nicht so sehr in der Materie...

Ich verwende ja WiFiClientSecure und nicht BearSSL, verstehe ich da grad was total falsch?

Wie/Wo in meinem oberen Code muss ich denn setInsecure() implementieren?

Aus Mangel an besseren Ideen habe ich jetzt auch noch meinen Code wie folgt angepasst (praktisch mich an mqtt-mosquitto-esp8266-tls gehalten:
Code: [Select]
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>

#include <PubSubClient.h>


char* ssid = "WLAN-XYZ";
char* password =  "73366094292006561972";

char* mqttServer = "192.168.178.35";
int mqttPort = 8883;


const char* mqttUser = "esp32";
const char* mqttPassword = "K489CQpy9";

const char* mqtt_fprint ="01:CF:4E:E8:29:E0:EC:1A:A0:63:98:CC:52:2A:A4:81:DD:C0:BB:5E";

WiFiClientSecure espClient;

PubSubClient client(espClient);

void setup() {
  Serial.begin(9600);
  ConnectWLAN();
  ConnectMQTT();

}

void loop(){
  client.loop();  //allow the client to process incoming messages and maintain its connection to the server
}


void ConnectWLAN() {
  if (WiFi.status() != WL_CONNECTED) {
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
      Serial.print("WiFi.status: ");
      Serial.println(WiFi.status());
      if (WiFi.status()==4) {
        Serial.println("Disconnecting...");
        //ESP.restart();
            WiFi.disconnect();
            WiFi.begin(ssid, password);
            delay(1000);
      }
    // wait 1 second for re-trying
      delay(1000);
      Serial.println("Connecting to WiFi..");
    }
    Serial.print("Connected to the WiFi network after: ");
    Serial.print(millis());
    Serial.println(" ms");
  }
}

void ConnectMQTT() {
  if (!client.connected()) { 
    client.setServer(mqttServer, mqttPort);
    client.setCallback(callback);
   
    while (!client.connected()) {
      //verifyFingerprint();
      Serial.print("Connecting to MQTT (");
      Serial.print(mqttServer);
      Serial.println(") ...");
   
      if (client.connect("Wemos_1",mqttUser,mqttPassword)) {
        Serial.println("connected to MQTT"); 
      } else {
        Serial.print("failed with state ");
        Serial.println(client.state());
        delay(3000);
      }
    }
    String text="Hello (" + String(random(1000)) + ")";
   
    client.subscribe("control/Wemos_1/RGB_LED");
    client.publish("debug",text.c_str());
  }
}

void verifyFingerprint() {
  if(client.connected() || espClient.connected()) return; //Already connected
 
  Serial.print("Checking TLS @ ");
  Serial.print(mqttServer);
  Serial.print("...");
 
  if (!espClient.connect(mqttServer, mqttPort)) {
    Serial.println("Connection failed. Rebooting.");
    Serial.flush();
    delay(15000);
    ESP.restart();
  }
  if (espClient.verify(mqtt_fprint, mqttServer)) {
    Serial.print("Connection secure -> .");
  } else {
    Serial.println("Connection insecure! Rebooting.");
    Serial.flush();
    delay(15000);
    ESP.restart();
  }
 
  espClient.stop();
 
  delay(100);
}

void callback(char* topic, byte* payload, unsigned int length) {
  // Parameter verarbeiten
    String Top=String((char*)topic);
    byte msgByte[length+1];    //Temporäres Byte-Array um Null-Byte anhängen zu können
    for (int i = 0; i < length; i++) {
        msgByte[i] = payload[i];
    }
    msgByte[length] = '\0';
    String msg=String((char*)msgByte); //Mit (char*) wird ein Typecast vom Byte-Pointer msgByte zu einem char-Pointer durchgeführt. Dieser kann von der Stringfunktion in einen String umgewandelt werden.
    Serial.print("Received message [");
    Serial.print(Top);
    Serial.print("]: ");
    Serial.println(msg);
}


Bleibt leider beim gleichen Fehler...

Viele Grüße
Tobi

Tommy56

Dann schau mal in die WiFiClientSecure.h, die in Deiner IDE liegt. Da siehst Du, welche Implementierung angezogen wird.

Gruß Tommy
"Wer den schnellen Erfolg sucht, sollte nicht programmieren, sondern Holz hacken." (Quelle unbekannt)

Go Up