I'm working with an ESP32 and an MQTT Server to create a meteo station. I managed to connect the esp32 to the server without any problem, even outside the local network, and I could post and received messages. So I decide to add some security with SSL and it's certificate, and suddenly, nothing work anymore.
After searching for a bit, I narrowed the problem down : if my esp32 is in the local network, SSL and it's certificate work like a charm. So that obviously means that my certificates are ok, and that my server configuration is probably ok too. But when I try from outside the network, it's the certificates that raises the error. More specifically, it raises :
sslv3 alert bad certificate mqtt
Which at least mean that I can reach my server, I just can't connect to it. To add even more puzzling element to the problem, I try to connect to the server with a computer outside of the network using MQTT explorer, with SSL and the exact same certificates, and it work without a itch.
I'm using mosquitto for the server. My configuration file give :
listener 8883
require_certificate true
allow_anonymous true ## this one is here for debug purpose. Taking it out doesn't change anything.
certfile C:\Users\username\Documents\Arduino\MQTT\MQTT SSL\broker\broker.crt
keyfile C:\Users\username\Documents\Arduino\MQTT\MQTT SSL\broker\broker.key
cafile C:\Users\username\Documents\Arduino\MQTT\MQTT SSL\ca\ca.crt
And for my ESP32, I can reproduce my problem with this simplified code. It come in part from the code given in that link : https://iotdesignpro.com/projects/how-to-connect-esp32-mqtt-broker .
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
const char* ssid = "mySsid";
const char* password = "myPassword";
const char* mqtt_server = "publicIp";
#define mqtt_port 8883
// I don t really need those two next lines for now, but I intend to use them later
#define MQTT_USER "eapcfltj"
#define MQTT_PASSWORD "3EjMIy89qzVn"
#define MQTT_SERIAL_PUBLISH_CH "/icircuit/ESP32/serialdata/tx"
#define MQTT_SERIAL_RECEIVER_CH "/icircuit/ESP32/serialdata/rx"
const char AWS_PUBLIC_CERT[] = ("-----BEGIN CERTIFICATE-----\n\
...
-----END CERTIFICATE-----\n");
//client.crt
const char AWS_DEVICE_CERT[] = ("-----BEGIN CERTIFICATE-----\n\
...
-----END CERTIFICATE-----\n");
//client.key
const char AWS_PRIVATE_KEY[] = ("-----BEGIN RSA PRIVATE KEY-----\n\
...
-----END RSA PRIVATE KEY-----\n");
WiFiClientSecure wifiClient;
PubSubClient client(wifiClient);
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte *payload, unsigned int length) {
Serial.println("-------new message from broker-----");
Serial.print("channel:");
Serial.println(topic);
Serial.print("data:");
Serial.write(payload, length);
Serial.println();
}
void reconnect() {
// Loop until we're reconnected
wifiClient.setCACert(AWS_PUBLIC_CERT);
wifiClient.setCertificate(AWS_DEVICE_CERT);
wifiClient.setPrivateKey(AWS_PRIVATE_KEY);
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (client.connect(clientId.c_str(),MQTT_USER,MQTT_PASSWORD)) {
Serial.println("connected");
client.subscribe(MQTT_SERIAL_RECEIVER_CH);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
Serial.setTimeout(500);// Set time out for
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
reconnect();
}
void loop() {
client.loop();
if (Serial.available() > 0) {
char mun[501];
memset(mun,0, 501);
Serial.readBytesUntil( '\n',mun,500);
if (!client.connected()) {
reconnect();
}
client.publish(MQTT_SERIAL_PUBLISH_CH, mun);
}
}
So. Since to reach my server from outside the local network I needed to add some port forwarding on my box, said box is my main suspect. I don't exactly know what happen, but I suspect either a loss of data, or something that come from the fact that the certificates are hardcoded. Like, maybe the "\n" are badly interpreted by my Internet box or by another element ? I don't know. I couldn't found anything to help me more, so really I could use any help on that problem. How could I manage to connect my esp32 to my server ?
Apologies for any bad english, and thank you in advance for your help !
DNS:hostname.lan, IP Address:192.168.0.2. Pay attention to that when creating the cert. Anyway, glad to hear you've made progress.