ESP32使用PubSubClient v2.8通过SSL连接Mosquitto失败求助
解决ESP32通过PubSubClient v2.8连接SSL加密Mosquitto失败的问题
核心问题原因
你当前使用的WiFiClient是明文TCP客户端,不支持SSL/TLS握手,而你的Mosquitto Broker启用了SSL加密,因此连接失败(错误码-2表示TCP连接层面的握手失败)。PubSubClient本身不实现SSL逻辑,依赖底层的Client接口实现,需要改用支持SSL的WiFiClientSecure。
具体解决步骤
1. 替换客户端类型
将代码中的WiFiClient替换为WiFiClientSecure,这是ESP32 Arduino核心库中支持SSL/TLS的客户端实现。
2. 导入Let's Encrypt根证书
ESP32默认不信任Let's Encrypt的根证书,需要将ISRG Root X1根证书内容添加到代码中(Let's Encrypt颁发的证书链最终信任此根证书),PEM格式内容如下:
-----BEGIN CERTIFICATE----- MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4 WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+ 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6 UA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+s WT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qy HB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+U QwbsnnuyckKzDAGR6WUqmXesXnUVReJjwlVfBpLehjwq6hlKueZXkqArEdgDjKyJ 18RevEka7m0tmM0o4GDQ9X8CArNPSmz2pF9AzDo4sxTBvM4FyQjJS0jJS0jJL1A 9EzAqHazJnEipZ4Z39sNwVhd5jMIZbpIqV0LSKKmW0r5iXWej1pEXcLFuZS9mcw YXpIuSLaR0CqwxRj2mNy2+0lsdeCuUpVersion=1 /etc/ssl/certs/ISRG_Root_X1.pem -----END CERTIFICATE-----
3. 修改后的完整代码
#include <WiFi.h> #include <WiFiClientSecure.h> #include <PubSubClient.h> // 替换为你的WiFi信息 const char* ssid = "YOUR_WIFI_SSID"; const char* password = "YOUR_WIFI_PASSWORD"; // Let's Encrypt ISRG Root X1根证书 const char* root_ca = \ "-----BEGIN CERTIFICATE-----\n" \ "MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw\n" \ "TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh\n" \ "cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4\n" \ "WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu\n" \ "ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY\n" \ "MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc\n" \ "h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+\n" \ "0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6\n" \ "UA5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+s\n" \ "WT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qy\n" \ "HB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+U\n" \ "QwbsnnuyckKzDAGR6WUqmXesXnUVReJjwlVfBpLehjwq6hlKueZXkqArEdgDjKyJ\n" \ "18RevEka7m0tmM0o4GDQ9X8CArNPSmz2pF9AzDo4sxTBvM4FyQjJS0jJS0jJL1A\n" \ "9EzAqHazJnEipZ4Z39sNwVhd5jMIZbpIqV0LSKKmW0r5iXWej1pEXcLFuZS9mcw\n" \ "YXpIuSLaR0CqwxRj2mNy2+0lsdeCuUpVersion=1 /etc/ssl/certs/ISRG_Root_X1.pem\n" \ "-----END CERTIFICATE-----\n"; WiFiClientSecure espClient; PubSubClient client(espClient); String listening_topic; void mqtt_configure(const char* mqtt_server, int mqtt_port) { client.setServer(mqtt_server, mqtt_port); // 配置SSL根证书 espClient.setCACert(root_ca); } void mqtt_connect(const char* mqtt_topic, const char* mqtt_user, const char* mqtt_pass) { listening_topic = String(mqtt_topic); while (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect("ESP32Client", mqtt_user, mqtt_pass)) { Serial.println("connected, subscribing to"); Serial.println(mqtt_topic); client.subscribe(mqtt_topic); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } void setup() { Serial.begin(115200); // 连接WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("WiFi connected"); mqtt_configure("my.server.com", 7383); mqtt_connect("esp32/output", "myuser", "mypass"); } void loop() { if (!client.connected()) { mqtt_connect("esp32/output", "myuser", "mypass"); } client.loop(); }
4. 额外说明
- 你的Mosquitto配置中使用了
fullchain.pem,其中包含了服务器证书和中间证书,客户端只需信任根证书即可完成证书链验证,无需额外配置中间证书。 - 如果仍然连接失败,可以尝试关闭证书验证(仅用于调试,不推荐生产环境):
espClient.setInsecure();,但这会降低安全性。
内容的提问来源于stack exchange,提问作者learningtech
相关产品推荐
相关产品推荐

