MQTTnet
MQTTnet copied to clipboard
Can't connect to broker using CA Cert ClientCert and Key
I try to connect to my MQTT broker with TLS. I have these 3 certificates as follows -CA Cert (CRT) -Client Cert (PEM) -Client Key (PEM)
These certificates are valid and work if I use them with a software like MQTTX.
Now I am trying to use MqttNet (3.1.2) to connect to broker. I have read the documentation and accordingly tried by converting clientCert and Key to pfx file using following command.
openssl pkcs12 -export -out certificate.pfx -inkey clientkey.pem -in clientCert.crt
My MQTTnet code : `// Creates a new client MqttClientOptionsBuilder builder = new MqttClientOptionsBuilder() .WithClientId("Test") .WithTcpServer("mqtt.cmec.iotexpress.io", 8889);
var clientCert_mos = new X509Certificate2(@"C:\Temp\certificate.pfx");
var caCrt_mos = new X509Certificate2(@"C:\Temp\ca-chain2.pem");
builder
.WithCredentials("User", "Password")
.WithTls(
new MqttClientOptionsBuilderTlsParameters()
{
UseTls = true,
SslProtocol = System.Security.Authentication.SslProtocols.Tls12,
AllowUntrustedCertificates = true,
CertificateValidationHandler = (certContext) => {
X509Chain chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck;
//chain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
//chain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
//chain.ChainPolicy.VerificationTime = DateTime.Now;
//chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0);
chain.ChainPolicy.CustomTrustStore.Add(caCrt_mos);
chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust;
// convert provided X509Certificate to X509Certificate2
var x5092 = new X509Certificate2(certContext.Certificate);
return chain.Build(x5092);
},
Certificates = new List<X509Certificate>()
{
caCrt_mos ,
}
})
.Build(); `
I can't connect.
I did try to connet to Test.mosquitto.org on port 8884 (Encrypted and client certificate required (Ca, Cert, Key), same as mine) and I can establish the connection...
Any idea what I'm doing wrong?
Thanks,
Hi!
There might be several issues, but I can try suggesting some stuff.
public bool ValidateCertificates(MqttClientCertificateValidationEventArgs args)
{
var chain = new X509Chain();
chain.ChainPolicy = new X509ChainPolicy
{
DisableCertificateDownloads = true,
RevocationFlag = X509RevocationFlag.EndCertificateOnly,
RevocationMode = X509RevocationMode.NoCheck,
TrustMode = X509ChainTrustMode.CustomRootTrust,
UrlRetrievalTimeout = new TimeSpan(0, 0, 0),
VerificationFlags = X509VerificationFlags.NoFlag,
VerificationTime = DateTime.Now,
VerificationTimeIgnored = false,
CustomTrustStore = { _signingCertificates.ToList()[0] }
};
chain.ChainPolicy.ExtraStore.AddRange(_signingCertificates);
return chain.Build(new X509Certificate2(_clientCertificate));
}
This is a custom callback that validates my tls1.3 certs, the custom trust store has the ca_cert as an X509Xertificate2 and the client certificate is the .pfx generated.
This could in turn be used with the MqttClientOptionsBuilder
.WithTlsOptions(opts =>
{
opts.WithClientCertificates(_provider.GetCertificates());
opts.WithSslProtocols(SslProtocols.Tls13);
opts.UseTls();
opts.WithCertificateValidationHandler(_provider.ValidateCertificates);
opts.Build();
})
The GetCertificates is pretty much
return new[] { _clientCertificate };
Which is the .pfx file.
Another thing that might of interest to check out is the way your operating system handles certificates, I use linux and I pretty much deploy the ca_cert to the certificate store
sudo update-ca-certificates --fresh
sudo cp ca/certificate.crt /usr/local/share/ca-certificates/
sudo update-ca-certificates
I assume that you are using windows so I am not familiar with how windows handles that so you might have to dig a little bit.
Hi @glwalsh
Can you provide the error messages?
I'd suggest the next steps:
1. Validate server TLS certificate
you only need to load the CAfile and use tlsOptions.WithTrustChain()
, note that if your CA does not provide revocation endpoints, you might also need to use tlsOptions.WithRevocationMode(X509RevocationMode.NoCheck)
2. Configure the client certificate for authentication
first, you dont need to convert your pem/key files to pfx, as you can load the cert with X509Certificate2.CreateFromPemFile(certFile, keyFile)
, however there is this issue in .NET that requires to export/import the cert before using with new X509Certificate2(cert.Export(X509ContentType.Pkcs12)
second, you can load the client certificates in tlsOptions with
List<X509Certificate2> certs = new();
var cert = X509Certificate2.CreateFromPemFile(certFile, keyFile);
certs.Add(new X509Certificate2(cert.Export(X509ContentType.Pkcs12));
tlsOptions.WithClientCertificates(certs)
There is sample targeting mosquitto in https://github.com/Azure-Samples/MqttApplicationSamples/tree/main/scenarios/getting_started