You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32通过TLS连接Mosquitto MQTT Broker证书验证失败问题

Troubleshooting ESP32 TLS Connection Failure to Mosquitto Broker (Certificate Verification Error)

Looking at your error messages—Certificate verification failed on ESP32 and sslv3 alert bad certificate in Mosquitto logs—this boils down to a mismatch or misconfiguration in how your ESP32 is handling the TLS certificate chain, or how Mosquitto is configured to present its credentials. Let’s break down the most likely fixes step by step:

1. Use the CA Certificate, Not the Broker’s Server Certificate

Your current code uses secureClient.setCACert(mosq_cert) with what looks like the Mosquitto server’s certificate. This is incorrect: the ESP32 needs the root CA certificate that signed the broker’s server certificate to validate its authenticity. If you used OpenSSL to self-sign your certificates, you should have a separate ca.crt file—use that content for mosq_cert instead.

2. Fix Certificate Formatting Issues

Manual string concatenation with "..." can introduce hidden formatting errors (like missing newlines or extra spaces) that break TLS validation. Use a raw string literal to embed your certificate cleanly:

const char* ca_cert PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFtTCCA52gAwIBAgIUK5VYs14dyCApkwl0eKBp2/Tt5dswDQYJKoZIhvcNAQEN
BQAwajEXMBUGA1UEAwwOQW4gTVFUVCBicm9rZXIxFjAUBgNVBAoMDU93blRyYWNr
... (full CA certificate content)
-----END CERTIFICATE-----
)EOF";

Remove any leading/trailing blank lines in the certificate content—WiFiClientSecure is strict about valid PEM formatting.

3. Sync ESP32 System Time

TLS certificate validation checks the certificate’s expiration date. If your ESP32 doesn’t have an accurate system time, it will reject valid certificates. Add NTP sync right after connecting to WiFi:

configTime(28800, 0, "pool.ntp.org", "time.nist.gov"); // 28800 = UTC+8 offset
time_t now = time(nullptr);
while (now < 1600000000) { // Wait until time is synced to 2020+
  delay(1000);
  now = time(nullptr);
  Serial.println("Waiting for time sync...");
}

4. Verify Mosquitto Configuration

Ensure your Mosquitto mosquitto.conf is set up correctly for TLS without requiring client certificates (since your ESP32 code doesn’t provide one):

listener 8883
cafile /path/to/your/ca.crt
certfile /path/to/your/server.crt
keyfile /path/to/your/server.key
require_certificate false  # Critical—disable if you don't use client certs

If require_certificate is set to true, Mosquitto will reject connections without a valid client certificate, triggering the "bad certificate" error.

5. Fix Hostname/IP Mismatch

Your certificate’s Common Name (CN) is "An MQTT broker"—this doesn’t match the IP or domain you’re using to connect to the broker. TLS requires the server’s hostname/IP to match the CN or Subject Alternative Name (SAN) in the certificate. To fix this:

  • Regenerate your certificate with a CN that matches your broker’s IP or domain (add a SAN field for IP if connecting via IP)
  • Or, for testing only, disable hostname validation on the ESP32 (not recommended for production):
    secureClient.setInsecure();
    

Modified Example Code

Here’s a cleaned-up version of your code incorporating the fixes above:

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

const char* ssid = "your_wifi_ssid";
const char* password = "your_wifi_password";
const char* mqtt_server = "broker_ip_or_domain";
const int mqtt_port = 8883;
const char* clientId = "esp32_client";

WiFiClientSecure secureClient;
PubSubClient client(secureClient);

// Root CA certificate (raw string literal)
const char* ca_cert PROGMEM = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFtTCCA52gAwIBAgIUK5VYs14dyCApkwl0eKBp2/Tt5dswDQYJKoZIhvcNAQEN
BQAwajEXMBUGA1UEAwwOQW4gTVFUVCBicm9rZXIxFjAUBgNVBAoMDU93blRyYWNr
cy5vcmcxFDASBgNVBAsMC2dlbmVyYXRlLUNBMSEwHwYJKoZIhvcNAQkBFhJub2Jv
ZHlAZXhhbXBsZS5uZXQwHhcNMjAxMjA5MTIzMjU3WhcNMzIxMjA2MTIzMjU3WjBq
MRcwFQYDVQQDDA5BbiBNUVRUIGJyb2tlcjEWMBQGA1UECgwNT3duVHJhY2tzLm9y
ZzEUMBIGA1UECwwLZ2VuZXJhdGUtQ0ExITAfBgkqhkiG9w0BCQEWEm5vYm9keUBl
eGFtcGxlLm5ldDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL5CDqte
kUzk75gYwgijZ1qzW962FSmtNntE1xONg2r2qsOgZoebNlTVJhy84OpiY+BV9wO9
JsJKg8xt1S5a85t2xk2reaesKr4bYz8QEzWtffKXyJ2Giv5zQF7hxsyhsamQ3IxU
y6CcILxFS2Ig5ZSAvPNX7Hz1AtUpLAewu70Wyr+nSO318UnMVwczsotV0GTqI9KZ
4qZRhhEzRkYtk1HegqJ1k4QIKCktTCre4uW9r14NwB6q+Bei8Tz19jM0ubGjZX77
OYJY5LjWABNeYPi9aNDFs7cF7LqxPNsFT2z/Vj/qSg/5ISlhPs6PqG2shmZhbl8l
nD4SfdKfJM6Zt3HpFuk1UyyXyBrscsaxKK99dbGrvul3iv+LyGBw2KQw3MsbZrqo
o4sXLvz9TReZPqUZsfHj1mwU+dl6hV3Zg8I/E/gc9dIQibjRHAXxAZl/rR/UAkw8
HqqntiX5zid8bJ1vaYvJ5WFoAZPelDWrWLKOem4gy6h7+yeqXbAbcu8W2B89vG3k
yE674ZKTsJ6vnchJqUGylrjbtieHI3hRL7vYhqKgbIuFZHZIFM1uBcOVptNL0yNp
y2wL3xEMuElO5hJtmQMoobA8x5VfO5DWvNXa6vCv0OhXmXKq1k3rNfoInwEDi6Sg
wJsyj9ig0IQTKP7kpyoO3sU5e7DXoJRf22vJAgMBAAGjUzBRMB0GA1UdDgQWBBTu
jgPMXmq0vJKREyEp7TK2d05bVjAfBgNVHSMEGDAWgBTujgPMXmq0vJKREyEp7TK2
d05bVjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBDQUAA4ICAQB+IGnyMcVA
C1P+s5KDAmKI0SLP0b2jHuoTNq4O91lUjywhjgq81fVUu7WDBZhrvah5u1DPemev
OypBYA9HIOYUuOKVXDivcKvP4C1+g9lOnrV9NMp66KHTZHCfBxgPmzxS9jGuJJgX
nrs+XiJNNRFRFX76OlgXDjP3wIBSZ/00BBNLW1tt4Ti8LokuwM/gKfrSZDjbBkNC
Jq3KZyL6pFcV7C9Xec4wl9Q9+2SE85WlZojoBCx7ElANDnt7YkRHKepb0vjsb7ZG
xfHnHCS4yQPT/TLtwkDsvJe2tm/SkxFB2MfB7+tWV+/21YuFQpNaRHZXwLa/mZNG
+qii1SGnBpBUl6YgTFA++mQqwEkxQGhrFf2FugdkzxAyQfGzvfIMcichMFS5uRgB
+Z4ShbsvIjPiQN97QOS516M6+aUywrEStdzkacwoA443pXxJxCim6lTQMe2nT01F
kOTd6yGLFkxWnOPIJCw9VsPCyRsUkJhqvAGrWsm8IT6BZcCPcvHYO8q7/u0g6if1
RHfX7LIZdB5f0NLmQedgyte70byjRGFVNfzHP65oYbuNCTFpPdJ1CMg/HXDNxYNd
v/NTKIYsanoPeHZgp/6lX44NVIaoU9uNEpr+GePgfE/+r+OoIG2nx2zgcvhJAdjF
pXVIrrNIAF3BIGK1Qop/KK+gaY/L8d+raQ==
-----END CERTIFICATE-----
)EOF";

void callback(char* topic, byte* payload, unsigned int length) {
  // Handle incoming messages here
}

void setup() {
  Serial.begin(115200);
  
  // Connect to WiFi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected to WiFi");

  // Sync system time via NTP
  configTime(28800, 0, "pool.ntp.org", "time.nist.gov");
  time_t now = time(nullptr);
  while (now < 1600000000) {
    delay(1000);
    now = time(nullptr);
    Serial.println("Waiting for time sync...");
  }
  Serial.println("Time synced successfully");

  // Configure TLS client
  secureClient.setCACert(ca_cert);
  // Uncomment below only for testing (disables hostname validation)
  // secureClient.setInsecure();

  // Configure MQTT client
  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);

  // Connect to MQTT broker
  while (!client.connect(clientId)) {
    Serial.print("Connection failed, rc=");
    Serial.print(client.state());
    Serial.println(" - retrying in 2s");
    delay(2000);
  }
  Serial.println("Connected to MQTT broker!");
}

void loop() {
  client.loop();
}

Start with the first two fixes (using the CA cert and fixing formatting)—these are the most common culprits. If that doesn’t work, move on to time sync, Mosquitto config, and hostname matching.

内容的提问来源于stack exchange,提问作者user14389193

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:05:41