MQTTnet icon indicating copy to clipboard operation
MQTTnet copied to clipboard

SSL/TLS Handshake Fails when Connecting with MQTTnet

Open radutomy opened this issue 1 year ago • 3 comments

Describe your question

The following command works perfectly well when sending a message to my EMQX server:

mosquitto_pub -h "dummyserver.com" -p 8883 -t "peaches" -m "Hello World" -u "dummyuser" -P 'dummypassword' --cafile ca.pem --cert client.pem --key client.key

I'm trying to replicate the above in a C# function:

const string serverIp = "dummyserver.com";
const int port = 8883;
const string topic = "peaches";
const string message = "Hello World";
const string username = "dummyuser";
const string password = "dummypassword";
// eg: /home/user/src/pem
string sslFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "src", "pem");

string capem = Path.Combine(sslFolderPath, "ca.pem");
string clientpem = Path.Combine(sslFolderPath, "client.pem");
string clientkey = Path.Combine(sslFolderPath, "client.key");

// Validate inputs
if (string.IsNullOrEmpty(topic) || string.IsNullOrEmpty(message))
{
	throw new ArgumentException("Topic and message cannot be null or empty.");
}

if (!string.IsNullOrEmpty(sslFolderPath) && (!File.Exists(capem) || !File.Exists(clientpem) || !File.Exists(clientkey)))
{
	throw new ArgumentException("SSL files are missing in the provided folder path.");
}

var logger = new MqttNetEventLogger("");
logger.LogMessagePublished += (s, e) =>
{
        // put breakpoints here to debug
	Console.WriteLine(e.LogMessage);
	Console.WriteLine(Environment.NewLine);
	Console.WriteLine(Environment.NewLine);
};

var mqttFactory = new MqttFactory();
using IMqttClient mqttClient = mqttFactory.CreateMqttClient(logger);

try
{
	MqttClientOptions mqttClientOptions = new MqttClientOptionsBuilder()
		.WithTcpServer(serverIp, port)
		.WithProtocolVersion(MqttProtocolVersion.V311)
		.WithCredentials(username, password)
		.WithTlsOptions(o =>
		{
			o.UseTls(true);
			o.WithAllowUntrustedCertificates(false);
			o.WithClientCertificates(new[]
			{
				new X509Certificate2(capem),
				new X509Certificate2(clientpem, clientkey)
			});
			o.WithSslProtocols(SslProtocols.None);
			o.WithCertificateValidationHandler(args =>
			{
				// Console.WriteLine(args);
				return true;
			});
		})
		.Build();

	MqttClientConnectResult res = await mqttClient.ConnectAsync(mqttClientOptions, CancellationToken.None);
	Console.WriteLine(res.ResultCode);
}
catch (Exception e)
{
	Console.WriteLine(e);
	throw;
}

MqttApplicationMessage applicationMessage = new MqttApplicationMessageBuilder()
	.WithTopic(topic)
	.WithPayload(message)
	.Build();

await mqttClient.PublishAsync(applicationMessage, CancellationToken.None);
await mqttClient.DisconnectAsync();

Does anyone know what I'm doing wrong or missing? When executing the code above I'm getting the following logs from MqttNetEventLogger:

[2023-09-05T23:16:58.7647014Z] [] [6] [MqttClient] [Error]: Error while connecting with server
MQTTnet.Adapter.MqttConnectingFailedException: Error while authenticating. One or more errors occurred. (One or more errors occurred. (The decryption operation failed, see inner exception.))
 ---> System.AggregateException: One or more errors occurred. (One or more errors occurred. (The decryption operation failed, see inner exception.))
 ---> MQTTnet.Exceptions.MqttCommunicationException: One or more errors occurred. (The decryption operation failed, see inner exception.)
 ---> System.AggregateException: One or more errors occurred. (The decryption operation failed, see inner exception.)
 ---> System.IO.IOException: The decryption operation failed, see inner exception.
 ---> Interop+OpenSsl+SslException: Decrypt failed with OpenSSL error - SSL_ERROR_SSL.
 ---> Interop+Crypto+OpenSslCryptographicException: error:0A00045C:SSL routines::tlsv13 alert certificate required
   --- End of inner exception stack trace ---
   at Interop.OpenSsl.Decrypt(SafeSslHandle context, Span`1 buffer, SslErrorCode& errorCode)
   at System.Net.Security.SslStreamPal.DecryptMessage(SafeDeleteSslContext securityContext, Span`1 buffer, Int32& offset, Int32& count)
   --- End of inner exception stack trace ---
   at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
   at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
   at MQTTnet.Implementations.MqttTcpChannel.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
   at MQTTnet.Adapter.MqttChannelAdapter.ReadFixedHeaderAsync(CancellationToken cancellationToken)
   at MQTTnet.Adapter.MqttChannelAdapter.ReceiveAsync(CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at System.Threading.Tasks.Task`1.get_Result()
   at MQTTnet.Adapter.MqttChannelAdapter.ReceivePacketAsync(CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at MQTTnet.Adapter.MqttChannelAdapter.WrapAndThrowException(Exception exception)
   at MQTTnet.Adapter.MqttChannelAdapter.ReceivePacketAsync(CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
   at MQTTnet.Client.MqttClient.Receive(CancellationToken cancellationToken)
   at MQTTnet.Client.MqttClient.Authenticate(IMqttChannelAdapter channelAdapter, MqttClientOptions options, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at MQTTnet.Client.MqttClient.Authenticate(IMqttChannelAdapter channelAdapter, MqttClientOptions options, CancellationToken cancellationToken)
   at MQTTnet.Client.MqttClient.ConnectInternal(IMqttChannelAdapter channelAdapter, CancellationToken cancellationToken)
   at MQTTnet.Client.MqttClient.ConnectAsync(MqttClientOptions options, CancellationToken cancellationToken)
4

MQTTnet.Diagnostics.MqttNetEventLogger
[2023-09-05T23:16:58.7801885Z] [] [6] [MqttClient] [Verbose]: Disconnecting [Timeout=00:01:40]
4

MQTTnet.Diagnostics.MqttNetEventLogger
[2023-09-05T23:16:58.7831013Z] [] [6] [MqttClient] [Verbose]: Disconnected from adapter.
4

MQTTnet.Diagnostics.MqttNetEventLogger
[2023-09-05T23:16:58.7843253Z] [] [6] [MqttClient] [Info]: Disconnected.

radutomy avatar Sep 05 '23 23:09 radutomy

Are you using the latest nuget version 4.3.0.858. I am having issue with TLS where my MqttNet for Aspnet is version 4.2.1.781 and my managed client is 4.3.0.858, without TLS it connects.

The error I get is "Error while authenticating" from the client side but no messages or connection attempt on the Server Side.

alberk8 avatar Sep 06 '23 02:09 alberk8

Yes, using the latest nuget packages

radutomy avatar Sep 06 '23 06:09 radutomy

@alberk8 A fix for the TLS issue in the client will be released soon. Here it says "certificate required" so I assume that the root cause is something different.

chkr1011 avatar Sep 06 '23 17:09 chkr1011