Platformio on esp32 to do mqtt on ssl via Wi-Fi

New to esp32 and platformio. I can connect to Wi-Fi fine but can’t subscribe to our mqtt topic which is on ssl - port 8883. Anyone have an example of how to do this? Also concerned if the cert gets updated on the server do we have to go to each esp32 and update it?

See example & example

Cert checks against root, not sub or server cert. Pinning root CA cert (as the ^ examples do) means that as long as only the server cert (most common case) or sub CA cert (not so common case) are exchanged in the chain (but are still signed from the same root CA), the cert verify still works since only the saved root CA is your trust anchor (TA). Of course you could also build in some secure OTA capability to update certs at will.

This looks like just about it! I believe the example at arduino-mqtt/ESP32DevelopmentBoardSecure.ino at master · 256dpi/arduino-mqtt · GitHub is the way we want to go but one question. For the mqtt connection we have a specific topic we want to connect to and it has a username and password. For the client.begin command or previous to this is there a way to set a specific topic and include the username and password?

Well except for that “secure” TLS connection there.

Without entering a CA cert there as your root-of-trust (/trust anchor), security is pretty much dead, hence the link to the second example where that is done.

I apologize, very new to ESP32 programming. For the example at arduino-mqtt/ESP32DevelopmentBoardSecure.ino at master · 256dpi/arduino-mqtt · GitHub, at the top it has #include <MQTT.h>. I understand that that is including a library somewhere called MQTT.h and you can add this either by going to your platform.ini file and having lib_deps = and having a link to the library there or if you search on platformIO and go to the installation tab it has the command you can paste into the terminal to manually install it - however, how do I know which MQTT.h library this is pointing to - or in other words which one I need to reference or install?

The https://github.com/256dpi/arduino-mqtt already has the library code (MQTT.h and friends) and the examples in one. This is also the most common – a library with its examples in one repo. So when the examples #include <MQTT.h>, they mean the MQTT.h in that very same repo.

Technically, when you are looking at https://github.com/256dpi/arduino-mqtt/blob/master/examples/ESP32DevelopmentBoardSecure/ESP32DevelopmentBoardSecure.ino, this is on the master (git) branch of this repo, and logically when you use this code, it needs the master version of the library repo itself too, so e.g., lib_deps = https://github.com/256dpi/arduino-mqtt.git. (Pointing to the .git link downloads the default branch (=master) of this repo).

You can also look at other branches and tags (tags are frozen commit states) in Github by clicking on the <branch symbol< <branch name> icon.

grafik

The tagged versions are then the ones selectible via the PlatformIO registry, see e.g. here.

However, usually good libraries are API stable, so using the example code from the master branch of their repo together with the last published (tagged) version like 2.5.0 works fine. If you want to be very pedantic, then you would look at the example in the e.g. 2.5.0 version (by looking at https://github.com/256dpi/arduino-mqtt/tree/v2.5.0, aka, select the right tag from the menu) and use that with the exact same library version, aka lib_deps = 256dpi/MQTT@2.5.0.

Thank you for the clarifications! So I get to the point where I have my certificate - I am connecting to the server on port 8883, but then when I try the connect(“RandomName”,“UserName”,“Password”) it returns:

So not sure if there is something I have to do to start the ssl client or what.

Easy test: install OpenSSL on your machine (e.g. for Windows or sudo apt install openssl) and use OpenSSL’s s_client feature to connect to SSL/TLS secured MQTT server port (8883).

E.g., I can test that general SSL/TLS connections against google.com port 443 (where HTTPS is spoken) and the TLS 1.2 protocol (not the new TLS 1.3 which is probably not yet supported in the ESP32 libraries) works with

$ openssl s_client -port 443 -host google.com -msg -showcerts -tls1_2
CONNECTED(00000003)
>>> ??? [length 0005]
    16 03 01 00 ca
>>> TLS 1.2, Handshake [length 00ca], ClientHello
    01 00 00 c6 03 03 03 f7 d2 cb 68 70 a0 15 38 bb
 [..]
    03 01 03 02 04 02 05 02 06 02
<<< ??? [length 0005]
    16 03 03 00 3f
<<< TLS 1.2, Handshake [length 003f], ServerHello

The “Server Hello” response is good. Then the program finishes with…

---
SSL handshake has read 6864 bytes and written 292 bytes
Verification: OK
---
New, TLSv1.2, Cipher is ECDHE-ECDSA-CHACHA20-POLY1305
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-ECDSA-CHACHA20-POLY1305
    Session-ID: 20E01FBC69930D78EB308700F34461C1636C4843A647D3A854D503C0537AC987
    Session-ID-ctx: 
[...]

So the TLS connection works fine with the TLS 1.2 standard and the ECDHE-ECDSA-CHACHA20-POLY1305 ciphersuite (aka, ephemereal elliptic curve diffie hellman for key exchange, elliiptic curve signatures, ChaCha20-Poly1305 for the symmetric cipher).

The output, thanks to -showcerts, also shows the used certificate chain, so you can double check whether you have gotten the correct certificates in your firmware.

If the TLS tunnel establishment works with OpenSSL on TLS 1.2 and the returned root certificate is equal to what you have in your firmware (latter is not needed if you’re using .setInsecure() for now), then the problem is likely on the ESP32 side. You can enable more verbose debug information as per documentation in the platformio.ini.

build_flags = -DCORE_DEBUG_LEVEL=5

with that, the Arduino core or library might tell you more about what specifically fails. “-1” might just be a general “there was an error code” or already a specific one like, “TCP connection to host and port could not be established” – you can look that up in the library code. (Ctrl+Click on any function in VSCode to get into its implementation).

Will try this now - also found out that port 8883 on our server is mqtt over websockets. So not sure how that will effect the way the code needs to be done.

It seems like we are chasing our tails here - would you be willing do to contract work (there is some paperwork to fill out so we can pay you) to help get this resolved?

This is hugely important – MQTT is spoken in 4 main flavors per ESP-MQTT - ESP32 - — ESP-IDF Programming Guide latest documentation. The sketch we’ve been talking about all the time does MQTT over SSL (standard port 8883).

MQTT over websockets (which is also differnt from MQTT over websockets with SSL, aka “Websockets Secure”) is not handled by the 256dpi/MQTT library, see mqtt over websockets? · Issue #134 · 256dpi/arduino-mqtt · GitHub.

Thankfully, it looks like a different MQTT library supports this protocol flavor just fine: MQTTPubSubClient/examples/WiFiMQTToverWebSocketSecure at main · hideakitai/MQTTPubSubClient · GitHub.

You should have absolute certainty on what protocol your MQTT server is speaking. Servers like Mosquito can also open multiple ports, e.g. for MQTT over SSL (default :8883) and MQTT over Websockets with SSL (default :443).

I think setup up a basic example / tutorial with a MQTT server and a corresponding ESP32 client sketch is really simple, that doesn’t need payment. You just have to tell me what exact requirements there are in terms of used MQTT protocol (MQTT over SSL, MQTT over WebSockets Secure, …?) and MQTT client authentication (none, password-based, TLS certificate based?).

I just messaged you with the server info. Thank you!