Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Connect async via TLS is different on Windows and Linux. #2019

Open
Basko-Dev opened this issue Jun 11, 2024 · 3 comments
Open

Connect async via TLS is different on Windows and Linux. #2019

Basko-Dev opened this issue Jun 11, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@Basko-Dev
Copy link

Basko-Dev commented Jun 11, 2024

Describe the bug

Connect async via TLS is different on Windows and Linux.

Which component is your bug related to?

  • Client

To Reproduce

Steps to reproduce the behavior:

  1. Use MQTTnet v4.3.6.1152.
  2. Build the client code below.
  3. Run the code on Windows and Linux. Do not provide any certificates. The code does not use any certificates by design.
  4. See error on Windows and Linux.

Actual behavior

Windows:

  • ConnectAsync method throws an exception ("Authentication failed because the remote party sent a TLS alert: 'HandshakeFailure'.").
  • CertificateValidationHandler event is not raised.
  • RemoteCertificateValidationCallback method is not called.

Linux (Yocto v3.4):

  • ConnectAsync method throws an exception ("The remote certificate was rejected by the provided RemoteCertificateValidationCallback").
  • CertificateValidationHandler event is raised.
  • RemoteCertificateValidationCallback method is called.

Expected behavior

Flow and errors should be the same on Windows and Linux.

Code example

public async void Connect()
{
    try
    {
        var factory = new MqttFactory();
        var client = factory.CreateMqttClient();
        var options = new MqttClientTlsOptions();
        options.UseTls = true;
        options.CertificateValidationHandler = RemoteCertificateValidationCallback;
        
        var optionsBuilder = new MqttClientOptionsBuilder()
                        .WithTcpServer("<your_broker>", 8883)
                        .WithTlsOptions(options);

        MqttClientConnectResult result = await client.ConnectAsync(optionsBuilder.Build()).ConfigureAwait(false);
         
        Log.Info($"Connected with result code: {result.ResultCode}. Reason: {result.ReasonString}).");
    }
    catch (Exception ex)
    {
        Log.Error($"Connection failed. {ex.Message}");
    }
}

private bool RemoteCertificateValidationCallback(MqttClientCertificateValidationEventArgs arg)
{
    // do nothing
    return false;
} 
@Basko-Dev Basko-Dev added the bug Something isn't working label Jun 11, 2024
@rido-min
Copy link
Member

Hi @Basko-Dev

Thanks for describing your issue.

To help with this we need to understand how the endpoint is configured:

  1. Does the endpoint use a trusted CA certificate? (this might be a different by OS, since Linux and Windows have different trust stores)
  2. Which version of .NET are you using?
  3. Can you run openssl s_client -connect 10.76.75.106:8883 and paste the results here? If you are using a custom CA, run the command with the parameter --CAfile

Flow and errors should be the same on Windows and Linux.

I understand the expectation, but MQTTnet is not implementing the TLS stack, it's based on .NET having different implementations per platform, and each platform might handle CA certificates differently.

I guess the callback is not triggered in Windows because the TLS stack fails before starting the certificate validation.

@Basko-Dev
Copy link
Author

Basko-Dev commented Jun 13, 2024

Hi @rido-min,

ad1. my MQTT broker uses self-signed CA certificate.
ad2. .NETCore 6.0.27
ad3. See the attached logs:
openssl s_client -connect broker_ip:8883 --CAfile cacert-v3.crt: s_client_with_cafile.txt
openssl s_client -connect broker_ip:8883: s_client_without_cafile.txt

@rido-min
Copy link
Member

.NET 7 introduced a new API to validate the chain with a CAfile, since you are in .NET6 you might need to implement the validation by yourself. Here is an example (note it's not in main, and I'm pointing to a specific commit)

https://github.com/Azure-Samples/MqttApplicationSamples/blob/4e785ae65e331d95cefd38a7b8d4f944a83fe209/mqttclients/dotnet/MQTTnet.Client.Extensions/WithTlsSettings.cs#L18

https://github.com/Azure-Samples/MqttApplicationSamples/blob/4e785ae65e331d95cefd38a7b8d4f944a83fe209/mqttclients/dotnet/MQTTnet.Client.Extensions/X509ChainValidator.cs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants