You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C# SSL客户端/服务端应用连接异常修复与调试(无需Wireshark)

修复C# SSL客户端/服务端握手问题(自签名证书)

核心问题根源

你遇到的SocketException(远程主机强制关闭连接)本质是SSL握手失败——.NET默认严格验证证书信任链,未安装到系统的自签名证书会被判定为不可信,导致任意一方主动终止连接。Java可通过自定义信任管理器跳过验证,但C#需显式配置信任策略。

服务端代码修复

服务端需正确加载带私钥的自签名证书(PFX格式),并配置SSL认证参数:

using System;
using System.Net;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;

class SslServer
{
    static void Main()
    {
        // 加载自签名PFX证书(替换为你的证书路径和密码)
        var cert = new X509Certificate2("server-cert.pfx", "your-cert-password");
        
        var listener = new TcpListener(IPAddress.Any, 4433);
        listener.Start();
        Console.WriteLine("SSL服务端已启动,等待连接...");

        while (true)
        {
            using var client = listener.AcceptTcpClient();
            using var sslStream = new SslStream(client.GetStream(), false);
            
            try
            {
                // 服务端认证:绑定证书,关闭吊销检查(自签名证书无吊销列表)
                sslStream.AuthenticateAsServer(
                    cert, 
                    clientCertificateRequired: false, 
                    checkCertificateRevocation: false
                );
                
                // 读取客户端发送的两个数字(逗号分隔)
                byte[] buffer = new byte[1024];
                int bytesRead = sslStream.Read(buffer, 0, buffer.Length);
                string input = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                string[] numbers = input.Split(',');
                int sum = int.Parse(numbers[0]) + int.Parse(numbers[1]);
                
                // 返回求和结果
                byte[] response = Encoding.UTF8.GetBytes(sum.ToString());
                sslStream.Write(response);
                Console.WriteLine($"已处理请求:{numbers[0]} + {numbers[1]} = {sum}");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"服务端错误:{ex.Message}");
            }
        }
    }
}

服务端关键注意点

  • 必须使用PFX格式证书(包含私钥),CER格式仅含公钥无法完成服务端认证;
  • checkCertificateRevocation设为false,自签名证书无合法吊销列表,开启会导致验证失败。

客户端代码修复

客户端需自定义证书验证回调,跳过系统信任链检查(仅用于测试,生产环境需替换为指纹验证):

using System;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;

class SslClient
{
    static void Main()
    {
        using var client = new TcpClient("localhost", 4433);
        using var sslStream = new SslStream(client.GetStream(), false, ValidateServerCertificate);
        
        try
        {
            // 客户端认证:指定目标主机名(必须与证书CN完全一致)
            sslStream.AuthenticateAsClient("localhost");
            
            // 发送两个数字(逗号分隔)
            string input = "123,456";
            byte[] buffer = Encoding.UTF8.GetBytes(input);
            sslStream.Write(buffer);
            
            // 读取服务端返回结果
            buffer = new byte[1024];
            int bytesRead = sslStream.Read(buffer, 0, buffer.Length);
            string result = Encoding.UTF8.GetString(buffer, 0, bytesRead);
            Console.WriteLine($"服务端返回结果:{result}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"客户端错误:{ex.Message}");
        }
    }

    // 自定义证书验证回调:信任所有证书(测试用,生产环境需验证证书指纹)
    private static bool ValidateServerCertificate(
        object sender, 
        X509Certificate certificate, 
        X509Chain chain, 
        SslPolicyErrors sslPolicyErrors
    )
    {
        // 生产环境示例:验证证书指纹
        // return certificate.Thumbprint.Equals("你的证书指纹(大写无空格)");
        return true;
    }
}

客户端关键注意点

  • AuthenticateAsClient的主机名必须与证书的**CN(通用名称)**完全匹配,否则会触发主机名不匹配错误;
  • 生产环境不要直接返回true,改为验证证书的指纹(硬编码可信指纹),避免中间人攻击风险。

调试握手问题(无需Wireshark)

  1. 启用.NET SSL日志:在应用配置文件(App.config)中添加以下配置,运行后查看ssl-log.txt获取握手细节:
    <configuration>
        <system.diagnostics>
            <sources>
                <source name="System.Net" tracemode="includehex" maxdatasize="1024">
                    <listeners><add name="System.Net"/></listeners>
                </source>
                <source name="System.Net.Security">
                    <listeners><add name="System.Net"/></listeners>
                </source>
            </sources>
            <sharedListeners>
                <add name="System.Net" type="System.Diagnostics.TextWriterTraceListener" initializeData="ssl-log.txt"/>
            </sharedListeners>
            <switches>
                <add name="System.Net" value="Verbose"/>
                <add name="System.Net.Security" value="Verbose"/>
            </switches>
        </system.diagnostics>
    </configuration>
    
  2. 捕获详细认证异常:单独捕获AuthenticationException,它会包含握手失败的具体原因(如证书不信任、主机名不匹配):
    catch (AuthenticationException authEx)
    {
        Console.WriteLine($"SSL握手失败:{authEx.Message}");
        Console.WriteLine($"内部原因:{authEx.InnerException?.Message}");
    }
    
  3. 验证证书加载正确性:在服务端输出证书信息,确认加载的是目标自签名证书:
    Console.WriteLine($"证书CN:{cert.Subject}");
    Console.WriteLine($"证书指纹:{cert.Thumbprint}");
    

常见坑点

  • 端口权限:使用443等知名端口时,需以管理员权限运行应用;
  • 证书权限:PFX证书需授予当前用户读取私钥的权限,否则服务端无法加载;
  • 防火墙设置:确保服务端端口未被防火墙拦截。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 12:21:00