Skip to content

fix(mqtt): use TLS on any port when TLS is enabled - #3302

Open
csutcliff wants to merge 1 commit into
emsesp:devfrom
csutcliff:pr/mqtt-tls-any-port
Open

csutcliff wants to merge 1 commit into
emsesp:devfrom
csutcliff:pr/mqtt-tls-any-port

Conversation

@csutcliff

@csutcliff csutcliff commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Problem

ESP_SSLClient::connect() only starts TLS when the port is on its built-in list of well-known secure ports (_secure_ports in ESP_SSLClient.h: 443, 8883 and 24 others). On any other port it quietly connects with plain TCP. With "Enable TLS" ticked and a broker on, say, 8884 or 18883, EMS-ESP therefore sends the MQTT CONNECT, including the username and password, in clear text, and the broker rejects it (mosquitto logs wrong version number).

Captured on the wire, with port 18883 and TLS enabled, the first bytes from EMS-ESP were 10 56 00 04 4d 51 54 54 ...: a plaintext MQTT CONNECT.

Fix

ClientSecureSync::connect() checks isSecure() after connect(). If the library left the connection in plain TCP, it upgrades it with connectSSL(), which runs the handshake on the open socket. On the listed ports nothing changes.

The IP-address overload takes the same route. connectSSL() then checks the certificate against the host name of the last by-name connect, or none if there wasn't one. EMS-ESP always connects by host name, so this only matters if setServer() is ever switched from a host name to an IP; a comment says so.

Testing

  • Port 18883, TLS enabled, P-521 CA: before, plaintext CONNECT and wrong version number on the broker. After, TLSv1.2 ECDHE-ECDSA-AES256-GCM-SHA384, certificate verified, connected.
  • Port 8883 with Let's Encrypt X2: unchanged.
  • Builds for s_16M_P, clang-format clean.

Related MQTT TLS fixes, independent of each other: #3300, #3301, #3303.

Checklist

  • Against the dev branch
  • Formatted per .clang-format
  • New logic is commented
  • One fix only, only relevant files touched
  • CHANGELOG_LATEST.md updated
  • I accept the CLA in CONTRIBUTING.md

@proddy

proddy commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

this looks like a valid fix, but should be fixed upstream in the owner's project at https://github.com/bertmelis/espMqttClient . Please do a PR there.

@proddy proddy closed this Oct 19, 2026
@csutcliff

Copy link
Copy Markdown
Contributor Author

Same situation as #3300: this code is in EMS-ESP's own ClientSecureSync. Upstream espMqttClient uses WiFiClientSecure, which does TLS on any port. ESP_SSLClient only starts TLS by itself on its list of well-known ports (mIsSecurePort()) and leaves other ports as plain TCP so the caller can upgrade with connectSSL(), which looks deliberate. So the fix belongs in the caller, which here is EMS-ESP. Without it, "Enable TLS" on a port such as 8884 sends the MQTT username and password in clear text.

@proddy proddy reopened this Oct 19, 2026
ESP_SSLClient::connect() only starts a TLS session when the port is on
its built-in list of well-known secure ports (8883 is, 8884 or 18883 are
not). On any other port the connection silently stays plain TCP, so with
"Enable TLS" ticked the MQTT CONNECT, including the username and
password, went out in clear text and the broker rejected the handshake.

Upgrade the connection with connectSSL() whenever connect() returns
without a secure session.
@csutcliff
csutcliff force-pushed the pr/mqtt-tls-any-port branch from 4d1e5b7 to 9651c04 Compare October 20, 2026 11:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants