ruuvi / ruuvi.gateway_esp.c

Ruuvi Gateway ESP32 code
BSD 3-Clause "New" or "Revised" License
24 stars 15 forks source link

Gateway erroneously forced to use TLS v1.3, preventing it from establishing a connection using TLS v1.2, resulting in SSL_HANDSHAKE_FAILED when connecting to Azure IoT Hub #1025

Closed jheba closed 1 month ago

jheba commented 2 months ago

Does anyone else experience ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED when connecting to Azure IoT Hub? This does not happen on v1.14.3

ojousima commented 2 months ago

We updated TLS version from v1.2 to v1.3 in 14.X -> 15.X firmware, this might be related. Does the Azure IoT Hub support TLS v1.3 and SSL session tickets? The goal of this change is to reduce data usage on metered connections, SSL overhead is the largest data bandwidth consumer in Gateway.

@TheSomeMan will take a closer look if needed.

TheSomeMan commented 2 months ago

We updated TLS version from v1.2 to v1.3 in 14.X -> 15.X firmware, this might be related. Does the Azure IoT Hub support TLS v1.3 and SSL session tickets? The goal of this change is to reduce data usage on metered connections, SSL overhead is the largest data bandwidth consumer in Gateway.

@TheSomeMan will take a closer look if needed.

I'll check it on this week.

jheba commented 2 months ago

We updated TLS version from v1.2 to v1.3 in 14.X -> 15.X firmware, this might be related. Does the Azure IoT Hub support TLS v1.3 and SSL session tickets? The goal of this change is to reduce data usage on metered connections, SSL overhead is the largest data bandwidth consumer in Gateway.

@TheSomeMan will take a closer look if needed.

Nope, ref. https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-tls-support

IoT Hub uses Transport Layer Security (TLS) to secure connections from IoT devices and services. Three versions of the TLS protocol are currently supported, namely versions 1.0, 1.1, and 1.2.

When creating new instance only 1.0 and 1.2 can be chosen: image

jheba commented 2 months ago

after RFC8446

A TLS 1.3 client who wishes to negotiate with servers that do not support TLS 1.3 will send a normal TLS 1.3 ClientHello containing 0x0303 (TLS 1.2) in ClientHello.legacy_version but with the correct version(s) in the "supported_versions" extension. If the server does not support TLS 1.3, it will respond with a ServerHello containing an older version number. If the client agrees to use this version, the negotiation will proceed as appropriate for the negotiated protocol.

ojousima commented 2 months ago

In this case it might be best to use FW 1.14.3 on Gateway until Azure supports TLS1.3. What language you're using on Azure? There are quite a lot of parsing libraries for Ruuvi available, so you might not have to write the library on your own.

jheba commented 2 months ago

The problem with FW v1.14.3 is that there is no way to limit how often it sends messages (am I wrong?).

From what I could observe, it sends ca. 1 message per second per sensor. For 5 sensors it gives quite a number of messages per day and since it is constant traffic of 5 requests per second, it looks suspicious for ISP.

ojousima commented 2 months ago

The problem with FW v1.14.3 is that there is no way to limit how often it sends messages (am I wrong?).

MQTT sends every message as they are received, and it is a lot of traffic. The original intention was that the user will throttle data on their backend as needed, if messages are processed at 1 Hz that does get expensive for sure.

MQTT traffic is within one continuous connection, it should not be any different from e.g. video streaming or gaming as far as your ISP is concerned, but data rate to backend can become a concern.

HTTP traffic is within discrete packets, the packet rate can be controlled by the backend by returning appropriate header. In Ruuvi's case the default is "send every 10 seconds" and Ruuvi Cloud then requests Gateway to drop the data rate to once per minute.

I cannot make any promises on supporting TLS 1.2 through legacy support on Gateway, but we will look into it to understand what it would mean from firmware point of view. Supporting AWS / Azure / Google IoT platforms is a high priority for us, but the process to add support to our Gateway might take longer than it takes for Microsoft to add support on their end. I see that they have had it on their roadmap for a while: https://learn.microsoft.com/en-us/answers/questions/1166506/azure-iot-hub-tls-1-3-support

In meanwhile, you could use one of these approaches:

The best approach depends on your schedule and Azure's schedule as well. I think I'd go with the third option just to transparently downgrade the TLS from 1.3 to 1.2 and take the bridge server out of the way once Azure has TLS 1.3 support on their end.

TheSomeMan commented 2 months ago

We updated TLS version from v1.2 to v1.3 in 14.X -> 15.X firmware, this might be related. Does the Azure IoT Hub support TLS v1.3 and SSL session tickets? The goal of this change is to reduce data usage on metered connections, SSL overhead is the largest data bandwidth consumer in Gateway. @TheSomeMan will take a closer look if needed.

Nope, ref. https://learn.microsoft.com/en-us/azure/iot-hub/iot-hub-tls-support

IoT Hub uses Transport Layer Security (TLS) to secure connections from IoT devices and services. Three versions of the TLS protocol are currently supported, namely versions 1.0, 1.1, and 1.2.

When creating new instance only 1.0 and 1.2 can be chosen: image

Ruuvi Gateway continues to support TLS v1.2. If a server supports TLS v1.3, the Gateway will use the newer version; otherwise, it will use TLS v1.2.

I tested the Gateway firmware v1.15.0 to use MQTT with Azure IoT Hub and found no issues. I configured the Client on the server side to use self-signed certificate by enabling “Thumbprint Match” Validation scheme: image

And here is the gateway configuration: image

ojousima commented 2 months ago

@jheba can you recheck this?

jheba commented 1 month ago

Hi, thanks for response.

Are you sure you tested it with IoT Hub? I don't recognize the authentication settings UI you present on your first screenshot neither the server URL on your second screenshot. Your URL ends with .eventgrid.azure.net while mine with .azure-devices.net which is common for IoT hub service. Could you please point out a documentation you have used for your CBA setup?

I tried to use certificate based authentication and I experience the same problem: Failed to connect (Error 32794 (ESP_ERR_MBEDTLS_SSL_HANDSHAKE_FAILED)).

Could you please test if you can connect to IoT Hub using SAS token >> ref. https://learn.microsoft.com/en-us/azure/iot/iot-mqtt-connect-to-iot-hub#using-the-mqtt-protocol-directly-as-a-device ? This is way simpler scenario than CBA and should not take you much time to test.

ojousima commented 1 month ago

@jheba can you test this out now? You can update the Gateway firmware to the latest through WebUI updater, URL https://jenkins.ruuvi.com/job/ruuvi_gateway_esp-PR/lastSuccessfulBuild/artifact/build/

jheba commented 1 month ago

Works with v1.15.0-16-gb14828a !