MQTTnet:无法连接 TLS:Interop+AppleCrypto+SslException:协议版本错误

MQTTnet : Unable to connect With TLS : Interop+AppleCrypto+SslException: bad protocol version

我是一名 .NET Core 新用户,正在尝试学习如何使用 MQTTnet.

在 MacOS Catalina 上使用 TLS 连接托管客户端

我正在尝试从 ASP.NET Core 3 后台服务连接到 Mosquitto 代理。使用 MqttExplorer 我能够使用用户名、密码和服务器证书 (CA) 文件通过 TLS 成功连接到服务器。所以,我知道 Mosquitto Broker 配置正确。

但是,我无法使用 MQTTnet 实现此目的。

using (var fileStream = new FileStream(_Config.Tls.CACerts, FileMode.Open))
                using (var memoryStream = new MemoryStream((int)fileStream.Length))
                {
                    fileStream.CopyTo(memoryStream);

                    _Logger.LogInformation($"Read file stream with length {memoryStream.Length} bytes, trying to connect with options:");
                    _Logger.LogInformation($"mqtt://{_Config.UserName}:{_Config.Password}/{_Config.Host}:{_Config.Port}");

                    _MqttOptions = new ManagedMqttClientOptionsBuilder()
                        .WithAutoReconnectDelay(TimeSpan.FromSeconds(5))
                        .WithClientOptions(new MqttClientOptionsBuilder()
                            .WithClientId(Guid.NewGuid().ToString())
                            .WithCredentials(_Config.UserName, _Config.Password)
                            .WithTcpServer(_Config.Host, _Config.Port)
                            .WithTls(
                                o =>
                                {
                                    o.UseTls = true;
                                    o.AllowUntrustedCertificates = true;
                                    o.SslProtocol = SslProtocols.Tls12;
#if WINDOWS_UWP
                                    o.Certificates = new List<byte[]>
                                    {
                                        new X509Certificate(memoryStream.ToArray()).Export(X509ContentType.Cert)
                                    };
#else
                                    o.Certificates = new List<X509Certificate>
                                    {
                                        new X509Certificate(memoryStream.ToArray())
                                    };
#endif

                                    o.CertificateValidationHandler = (context) =>
                                    {
                                        _Logger.LogInformation($"SSL POLICY ERRORS {context.SslPolicyErrors.ToString()}");
                                        return true;
                                    };
                                }
                            )
                            .Build())
                        .Build();
                }

我收到以下异常:

MQTTnet.Exceptions.MqttCommunicationException: Authentication failed, see inner exception.
 ---> System.Security.Authentication.AuthenticationException: Authentication failed, see inner exception.
 ---> Interop+AppleCrypto+SslException: bad protocol version
   --- End of inner exception stack trace ---
   at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)
   at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
   at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
--- End of stack trace from previous location where exception was thrown ---
   at System.Net.Security.SslStream.ThrowIfExceptional()
   at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
   at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__64_2(IAsyncResult iar)
   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
--- End of stack trace from previous location where exception was thrown ---
   at MQTTnet.Implementations.MqttTcpChannel.ConnectAsync(CancellationToken cancellationToken)
   at MQTTnet.Implementations.MqttTcpChannel.ConnectAsync(CancellationToken cancellationToken)
   at MQTTnet.Internal.MqttTaskTimeout.WaitAsync(Func`2 action, TimeSpan timeout, CancellationToken cancellationToken)
   at MQTTnet.Adapter.MqttChannelAdapter.ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at MQTTnet.Adapter.MqttChannelAdapter.WrapException(Exception exception)
   at MQTTnet.Adapter.MqttChannelAdapter.ConnectAsync(TimeSpan timeout, CancellationToken cancellationToken)
   at MQTTnet.Client.MqttClient.ConnectAsync(IMqttClientOptions options, CancellationToken cancellationToken)
>> [2020-10-02T16:07:03.9254330Z] [4] [MqttClient] [Verbose]: Disconnecting [Timeout=00:00:10]
>> [2020-10-02T16:07:03.9255750Z] [4] [MqttClient] [Verbose]: Disconnected from adapter.
>> [2020-10-02T16:07:03.9256240Z] [4] [MqttClient] [Info]: Disconnected.

此外,明确尝试将 WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V311) 添加到客户端选项构建器。

有人能帮忙吗?

There is similar very issue on github

As a workaround one user proposed following cli command:

dotnet dev-certs https
dotnet dev-certs https --trust

一些关于它们的文档。

Trust the ASP.NET Core HTTPS development certificate on Windows and macOS

Installing the .NET Core SDK installs the ASP.NET Core HTTPS development certificate to the local user certificate store. The certificate has been installed, but it's not trusted. To trust the certificate, perform the one-time step to run the dotnet dev-certs tool:

成功运行!

问题是 mosquitto 代理配置为仅使用 Tls v1.3。但是,对于 dotnet core 3.1 tls1.3 似乎不支持 macOS 环境?如果 openssl 1.1.1 可用,它可以在 Linux 环境中使用。

我已将 mosquitto 代理配置降级为使用 tls 版本 1.2,上面的代码现在可以连接了。

如果有人设法使用 tlsv1.3 获得连接到 mosquitto 代理的 dotnet core 3.1 客户端,那么任何细节都将不胜感激。

通过Google登陆这里是因为我在本地调试时出现了以下错误(Angular and .NET 6 web api)

System.IO.IOException:解密操作失败,见内部异常。 ---> Interop+AppleCrypto+SslException:杂项。错误的证书

我试过了

dotnet dev-certs https
dotnet dev-certs https --trust

但运气不好。

最终有帮助的是在浏览器中转到我本地 运行 api 的 URL,我收到了一条“警告:潜在的安全风险”消息。点击Advanced -> Accept the risk and continue后,调用成功