[英]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.