繁体   English   中英

ESP32 MQTT TLS 错误(自签名证书)

[英]ESP32 MQTT TLS errors (self signed cert)

我似乎无法让 MQTT+TLS+自签名证书在我的 ESP32 上工作。

我在我的家庭网络中使用这个“设置”,没有对 paho-python 和 mosquitto_pub/sub 造成重大影响。 后者适用于以下 bash 命令(注意那里的不安全):

mosquitto_pub -h 192.168.1.X -p 8883 --cafile /etc/mosquitto/ca_certificates/mosq_ca.crt --cert /etc/mosquitto/certs/mosq_client.crt --key /etc/mosquitto/certs/mosq_client.key --debug --insecure --topic "test/message" -m "off"

除了证书路径和常规设置之外,我的代理的 mosquitto 配置文件还包含以下几行:

tls_version tlsv1.3
require_certificate true

当我将草图发送到我的 ESP32 时,结果是它卡在了reconnect()循环中(见下面的草图)。

当我没有指定客户端证书和密钥( // for client verification行在setup()中注释)时,我收到以下错误(我猜这是由于需要证书的配置):

1594936874: New connection from 192.168.1.162 on port 8883.
1594936874: OpenSSL Error: error:14094412:SSL routines:ssl3_read_bytes:sslv3 alert bad certificate
1594936874: Socket error on client <unknown>, disconnecting.

当我指定客户端证书时,我得到了这个:

1594936887: New connection from 192.168.1.162 on port 8883.
1594936888: Socket error on client <unknown>, disconnecting.

不确定是证书上的主机名不匹配还是什么。 这将是我的主要提示,但我不确定。 我也不知道是否可以为 WiFiClientSecure class 指定与--insecure类似的选项,到目前为止我还没有找到类似的选项。 但我也是初学者。

我的草图如果还很粗糙,但它应该仍然可读:

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



const char* ssid = "mySSID";
const char* password = "myPasswd";

const char*  server = "192.168.1.X";  // Server URL
const char* MQTT_subscribe_topic = "test/esp32";

int timediff_hr = 2;

const char* root_ca = \ 
"-----BEGIN CERTIFICATE-----\n" \ 
"pem format broken into lines\n" \
"pem format broken into lines\n" \
"pem format broken into lines\n" \
"-----END CERTIFICATE-----\n" ;


// You can use x.509 client certificates if you want
const char* test_client_key = \
"-----BEGIN CERTIFICATE-----\n" \ 
"pem format broken into lines\n" \
"pem format broken into lines\n" \
"pem format broken into lines\n" \
"-----END CERTIFICATE-----\n" ;

const char* test_client_cert =  \
"-----BEGIN CERTIFICATE-----\n" \ 
"pem format broken into lines\n" \
"pem format broken into lines\n" \
"pem format broken into lines\n" \
"-----END CERTIFICATE-----\n" ;

WiFiClientSecure wifiClient;
time_t now;

void msgReceived(char* topic, byte* payload, unsigned int len);
PubSubClient pubSubClient(server, 8883, msgReceived, wifiClient); 


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);

  getTime();

  wifiClient.setCACert(root_ca);
  wifiClient.setCertificate(test_client_key); // for client verification
  wifiClient.setPrivateKey(test_client_cert);  // for client verification

  
}


unsigned long lastPublish;
int msgCount;

void loop() {
  
  if (!pubSubClient.connected()) {
    reconnect();
  }
  
  pubSubClient.loop();
  
  if (millis() - lastPublish > 10000) {
    String msg = String("Hello from ESP32: ") + ++msgCount;
    boolean rc = pubSubClient.publish("outTopic", msg.c_str());
    Serial.print("Published, rc="); Serial.print( (rc ? "OK: " : "FAILED: ") );
    Serial.println(msg);
    lastPublish = millis();
  }
}

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

void reconnect() {

  Serial.print(F("PubSubClient attempting connection to: ")); Serial.println(server);

    uint8_t i = 0;
    while ( ! pubSubClient.connected()) {

    // Attempt to connect
    if (pubSubClient.connect("ESP32Client")) { //or "ESP8266Client"
      Serial.println("connected");
      // Subscribe
      pubSubClient.subscribe(MQTT_subscribe_topic);
      
    } else { //unsuccessful connect
      Serial.print("failed, rc=");
      Serial.print(pubSubClient.state());
      Serial.print("\nNext try in 5 seconds: connection to "); Serial.println(server);
      
      // Wait 5 seconds before retrying
      delay(5000);
    }
    }
}


void getTime(){
    // Synchronize time useing SNTP. This is necessary to verify that
  // the TLS certificates offered by the server are currently valid.
  Serial.print("Setting time using SNTP");
  configTime(timediff_hr * 3600, 0, "de.pool.ntp.org");
  time_t now = time(nullptr);
  while (now < 1000) {
    delay(500);
    Serial.print(".");
    now = time(nullptr);
  }
  Serial.println("");
  struct tm timeinfo;
  gmtime_r(&now, &timeinfo);
  Serial.print("Current time: ");
  Serial.print(asctime(&timeinfo));
  
}

PS:这个草图的基础是我的 MQTT:1883 unsecured 的测试草图,它也可以正常工作。 所以问题肯定出在 TLS 部分。

您的test_client_key包含一个证书。

如果您发布带有密钥和证书的示例代码,将会很有帮助。 显然不是您稍后将使用的那些,但由于您是自签名的,因此生成一些您可以在此处发布的测试密钥材料。

您的代理的配置也将很有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM