1

In my MQTT broker when active TLS 1.2 client cant connect to broker and get this exception

The remote certificate was rejected by the provided RemoteCertificateValidationCallback

Note: I use self-signed certificate generated by openssl.

Broker code

using MQTTnet.Server;
using System;
using MQTTnet;
using System.Text;
using static System.Console;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using SharedItems;

var wait = new ManualResetEvent(false);

var option = new MqttServerOptionsBuilder()
    .WithEncryptedEndpoint()
    .WithEncryptedEndpointPort(8200)
    .WithEncryptionCertificate(ConfigCertificate.GetCertificate().Export(X509ContentType.Pfx))
    .WithEncryptionSslProtocol(System.Security.Authentication.SslProtocols.Tls12)
    .WithConnectionValidator(OnNewConnection)
    .WithApplicationMessageInterceptor(OnNewMessage);
var mqttServer = new MqttFactory().CreateMqttServer();
await mqttServer.StartAsync(option.Build());
wait.WaitOne();

static void OnNewConnection(MqttConnectionValidatorContext context)
{
    WriteLine(
            "New connection: ClientId = {0}, Endpoint = {1}",
            context.ClientId,
            context.Endpoint);
}

static void OnNewMessage(MqttApplicationMessageInterceptorContext context)
{
    var payload = context.ApplicationMessage?.Payload == null ? null : Encoding.UTF8.GetString(context.ApplicationMessage?.Payload);
    WriteLine(
        " TimeStamp: {0} -- Message: ClientId = {1}, Topic = {2}, Payload = {3}, QoS = {4}, Retain-Flag = {5}",

        DateTime.Now,
        context.ClientId,
        context.ApplicationMessage?.Topic,
        payload,
        context.ApplicationMessage?.QualityOfServiceLevel,
        context.ApplicationMessage?.Retain);
}

ConfigCertificate.GetCertificate method code (it's okay and return certificate)

public static X509Certificate2 GetCertificate()
{
    var currectPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var certificationPath = Path.Combine(currectPath, "Assets/key/mycert.pfx");
    return  new X509Certificate2(certificationPath, "password", X509KeyStorageFlags.Exportable);
}

mqtt client code

using System;
using MQTTnet;
using System.Text;
using static System.Console;
using MQTTnet.Client.Options;
using MQTTnet.Client.Connecting;
using MQTTnet.Client.Disconnecting;
using MQTTnet.Extensions.ManagedClient;
using System.Text.Json;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using SharedItems;

WriteLine("Start App");
var _url = "localhost";
var _topic = "dev.to/topic/json";
var builder = new MqttClientOptionsBuilder()
    .WithClientId(Guid.NewGuid().ToString())
    .WithTls(new MqttClientOptionsBuilderTlsParameters
    {
        UseTls=true,
        Certificates=certs,
        SslProtocol=System.Security.Authentication.SslProtocols.Tls12
    })
    .WithTcpServer(_url, port);

var option = new ManagedMqttClientOptionsBuilder().WithAutoReconnectDelay(TimeSpan.FromSeconds(50)).WithClientOptions(builder.Build()).Build();

var client = new MqttFactory().CreateManagedMqttClient();
client.ConnectedHandler = new MqttClientConnectedHandlerDelegate(OnConnected);
client.ConnectingFailedHandler = new ConnectingFailedHandlerDelegate(OnConnectingFailed);
client.DisconnectedHandler = new MqttClientDisconnectedHandlerDelegate(OnDisconnected);
client.StartAsync(option).GetAwaiter().GetResult();
client.UseApplicationMessageReceivedHandler(context =>
{
    var payload = context.ApplicationMessage?.Payload == null ? null : Encoding.UTF8.GetString(context.ApplicationMessage?.Payload);

    WriteLine(
        " TimeStamp: {0} -- Message: ClientId = {1}, Topic = {2}, Payload = {3}, QoS = {4}, Retain-Flag = {5}",

        DateTime.Now,
        context.ClientId,
        context.ApplicationMessage?.Topic,
        payload,
        context.ApplicationMessage?.QualityOfServiceLevel,
        context.ApplicationMessage?.Retain);
});

while (true)
{
    if (!client.IsConnected)
        continue;
    string json = JsonSerializer.Serialize(new {id=Guid.NewGuid(), message = "Heyo :)", sent = DateTimeOffset.UtcNow });
    await client.PublishAsync(_topic, json);
    WriteLine("Send Data");
    await Task.Delay(1000);
}

static void OnConnected(MqttClientConnectedEventArgs obj)
{
    WriteLine("Successfully connected.");
}

static void OnConnectingFailed(ManagedProcessFailedEventArgs obj)
{
    WriteLine("Couldn't connect to broker."+obj.Exception.Message);
}

static void OnDisconnected(MqttClientDisconnectedEventArgs obj)
{
    WriteLine("Successfully disconnected. "+ obj.Exception.Message);
}

ConfigCertificate.GetCrtCertificate (it's okay and returns certificate):

public static X509Certificate GetCrtCertificate()
{
    var currectPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var certificationPath = Path.Combine(currectPath, "Assets/key/client.crt");
    return X509Certificate.CreateFromCertFile(certificationPath);
}

Why client get this error? How can fix and client connect to broker?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
behroozbc
  • 1,992
  • 2
  • 12
  • 25
  • For some reason the remote certificate is not accepted, it could be a good reason or not, but if you could hook into the certificate validation callback, you should be able to either fix the problem or ignore the error and accept the remote certificate regardless of its errors. This is a [similar question with SSlStream that uses RemoteCertificateValidationCallback](https://stackoverflow.com/a/69069790/2265446), I would suggest you try a similar approach with MQ. – Cleptus Oct 19 '21 at 19:26
  • I can't see where you have passed a copy of the broker cert to the MQTT client so it can verify the broker. – hardillb Oct 20 '21 at 20:53

0 Answers0