You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

.NET 9升级后WebSocket Secure(WSS)连接失败排查求助

.NET 9升级后WSS服务器无法建立安全连接问题

近期将项目从.NET 8升级至.NET 9后,WebSocket Secure(WSS)服务器停止工作,相同代码在.NET 8中可正常运行,升级后无法建立安全连接。

相关代码如下:

public WebSocketServer wssv = new WebSocketServer("wss://127.0.0.1:5963");

X509Certificate2 certificate = new X509Certificate2("path_to_cer");
using (X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser))
{
    store.Open(OpenFlags.ReadWrite);

    if (!store.Certificates.Contains(certificate))
        store.Add(certificate);
}

X509Certificate2 cert = new X509Certificate2("path_to_pfx", "1", X509KeyStorageFlags.MachineKeySet);

wssv.SslConfiguration.ServerCertificate = new X509Certificate2(cert);
wssv.SslConfiguration.CheckCertificateRevocation = false;
wssv.SslConfiguration.ClientCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
wssv.SslConfiguration.EnabledSslProtocols |= SslProtocols.Tls12 | SslProtocols.Tls13;
wssv.AddWebSocketService<WebSocketService>("/");
wssv.KeepClean = false;
wssv.Start();

问题描述

  • .NET 8中,代码可成功启动WSS服务器并允许安全WebSocket连接
  • 升级至.NET 9后,服务器无法建立安全连接,客户端连接时出现SSL/TLS握手失败相关错误
  • 已验证:
    • path_to_pfx对应的证书有效且未过期
    • 私钥可访问,证书已正确添加至CurrentUser\Root存储
    • 端口5963已开放,未被防火墙拦截

疑问

  1. .NET 9中是否存在与SSL/TLS或WebSocket安全连接相关的破坏性变更?
  2. 问题是否与.NET 9的证书处理方式有关?若有关,代码需做哪些修改?
  3. 有无更详细的调试方法来定位SSL/TLS握手失败的根本原因?

补充说明

  • 使用的WebSocket库为WebSocketSharp
  • 操作系统为Windows 11
  • 证书为自签名证书,仅用于本地开发

解答

1. .NET 9的破坏性变更说明

.NET 9确实对SSL/TLS相关逻辑有调整:

  • 默认禁用了TLS 1.0/1.1,但你的代码已指定TLS 1.2和1.3,这部分影响不大
  • 核心变更:.NET 9强化了证书链验证逻辑,即使设置CheckCertificateRevocation = false,对自签名证书的信任处理也更严格;另外,X509Certificate2的加载逻辑有调整,私钥访问权限的校验更严格

2. 证书处理相关的代码修改方案

针对你的场景,建议做以下调整:

(1)优化证书加载方式

避免重复创建X509Certificate2实例,同时调整密钥存储标志以适配.NET 9的权限校验:

// 加载PFX时,组合密钥存储标志,提升兼容性
X509Certificate2 cert = new X509Certificate2(
    "path_to_pfx", 
    "1", 
    X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable
);
// 直接赋值,无需重新包装证书对象
wssv.SslConfiguration.ServerCertificate = cert;

(2)补充证书链信任处理

由于.NET 9对自签名证书的信任校验更严格,可针对性调整验证回调:

wssv.SslConfiguration.ServerCertificateValidationCallback += (sender, cert, chain, errors) =>
{
    // 本地开发场景下,信任指定的自签名证书
    if (errors == SslPolicyErrors.None || errors == SslPolicyErrors.RemoteCertificateChainErrors)
    {
        // 替换为你的证书主题,确保只信任自己的自签名证书
        if (cert.SubjectName.Name == "CN=你的证书主题")
        {
            return true;
        }
    }
    return false;
};

(3)适配WebSocketSharp兼容性

WebSocketSharp是较老的库,可能未适配.NET 9的SSL/TLS变更,可尝试:

  • 更新WebSocketSharp到最新版本
  • 若无法更新,在项目文件中添加兼容性配置,强制使用旧版SSL/TLS逻辑:
<PropertyGroup>
  <RuntimeHostConfigurationOption Include="System.Net.Security.UseSchSendAuxRecord" Value="false" />
</PropertyGroup>

3. 调试SSL/TLS握手失败的方法

(1)启用.NET的SSL/TLS日志

在项目文件中添加以下配置,生成详细的握手日志:

<PropertyGroup>
  <DebugType>full</DebugType>
</PropertyGroup>
<ItemGroup>
  <RuntimeHostConfigurationOption Include="System.Net.Security.SslStreamLogging" Value="true" />
</ItemGroup>

日志会输出到控制台或调试窗口,可查看握手过程中具体的错误环节(如证书链验证失败、协议不匹配等)

(2)使用工具抓包分析

  • 使用Wireshark抓包,过滤ssl协议,查看握手过程中的告警信息
  • 使用openssl s_client命令测试连接,输出会返回具体错误原因:
openssl s_client -connect 127.0.0.1:5963 -tls1_2
openssl s_client -connect 127.0.0.1:5963 -tls1_3

(3)调试证书加载过程

在代码中添加日志,确认证书状态:

Console.WriteLine($"证书主题: {cert.Subject}");
Console.WriteLine($"证书有效期: {cert.NotBefore} 至 {cert.NotAfter}");
Console.WriteLine($"是否加载私钥: {cert.HasPrivateKey}");

内容的提问来源于stack exchange,提问作者Abbosbek Niyozqulov

火山引擎 最新活动