12

我目前有这段代码可以与服务器建立 SSL 连接:

using (client = new TcpClient())
{

    client.Connect(Hostname, Port);
    var callback = new RemoteCertificateValidationCallback(ValidateServerCertificate);


    using (stream = new SslStream(client.GetStream(), false, callback))
    {
        stream.AuthenticateAsClient(Hostname);
    }
}

但是,我认为它不支持 SNI,因为从 SNI 配置的服务器返回了错误的证书。反正有没有使用 SNI 建立 SSL 连接?

我正在使用 .NET 2(如有必要愿意升级)。我使用的是 Windows 7,但如果可能的话,我希望该软件可以在其他平台上运行,例如 Windows 2008。

4

4 回答 4

2

因此,总而言之,答案似乎是:不,您无法使 TLS 连接使用 SNI :-(

我找不到任何与 SNI 建立 TLS 连接的 C# 示例代码。但理论上,应该可以手动创建,即按照如何实现服务器名称指示 (SNI)

但是,这里的尝试失败了:TLS SNI with C#

于 2013-04-20T00:38:03.197 回答
0

我们在尝试使用双向 SSL 连接到业务 API 时遇到了类似的问题。标准 .NET 库不起作用。您可以使用第三方库http://curl.haxx.se/libcurl/作为可能的解决方案之一。

libcurl 是一个免费且易于使用的客户端 URL 传输库,支持 DICT、FILE、FTP、FTPS、Gopher、HTTP、HTTPS、IMAP、IMAPS、LDAP、LDAPS、POP3、POP3S、RTMP、RTSP、SCP、 SFTP、SMTP、SMTPS、Telnet 和 TFTP。libcurl 支持 SSL 证书、HTTP POST、HTTP PUT、FTP 上传、基于 HTTP 表单的上传、代理、cookie、用户+密码身份验证(Basic、Digest、NTLM、Negotiate、Kerberos)、文件传输恢复、http 代理隧道等。

.NET 库可以从http://sourceforge.net/projects/libcurl-net/上传

当您上传它时,将 libcurl.dll 更改为您可以找到的最新版本(它应该是 7.18.1 或更高版本)。在当前的 libcurl-nel 包中,它比需要的要旧。

 public string HTTPGet(string URL, string Proxy, string certName = null, string certPassword = null)
 {
    Easy easy = new Easy();
    SockBuff = "";
    try
    {
        Easy.WriteFunction wf = new Easy.WriteFunction(OnWriteData);
        easy.SetOpt(CURLoption.CURLOPT_URL, URL);
        easy.SetOpt(CURLoption.CURLOPT_TIMEOUT, "60");
        easy.SetOpt(CURLoption.CURLOPT_WRITEFUNCTION, wf);
        easy.SetOpt(CURLoption.CURLOPT_USERAGENT, UserAgent);
        easy.SetOpt(CURLoption.CURLOPT_COOKIEFILE, CookieFile);
        easy.SetOpt(CURLoption.CURLOPT_COOKIEJAR, CookieFile);
        easy.SetOpt(CURLoption.CURLOPT_FOLLOWLOCATION, true);

        if (!string.IsNullOrEmpty(certName))
        {
            easy.SetOpt(CURLoption.CURLOPT_SSLCERT, certName);
            if (!string.IsNullOrEmpty(certPassword))
            {
                easy.SetOpt(CURLoption.CURLOPT_SSLCERTPASSWD, certPassword);
            }
        }

        if (URL.Contains("https"))
        {
            easy.SetOpt(CURLoption.CURLOPT_SSL_VERIFYHOST, 1);
            easy.SetOpt(CURLoption.CURLOPT_SSL_VERIFYPEER, 0);
        }

        if (!string.IsNullOrEmpty(Proxy))
        {
            easy.SetOpt(CURLoption.CURLOPT_PROXY, Proxy);
            easy.SetOpt(CURLoption.CURLOPT_PROXYTYPE, CURLproxyType.CURLPROXY_HTTP);
        }

        var code = easy.Perform();
        easy.Cleanup();
        Console.WriteLine(code);
    }
    catch
    {
        Console.WriteLine("Get Request Error");
    }

    return SockBuff;
}

public static Int32 OnWriteData(Byte[] buf, Int32 size, Int32 nmemb, Object extraData)
{
    // Console.Write(System.Text.Encoding.UTF8.GetString(buf));
    SockBuff = SockBuff + System.Text.Encoding.UTF8.GetString(buf);

    return size * nmemb;
}
于 2014-07-02T22:51:56.293 回答
0

答案似乎是“是”,因为有一个支持 SNI 的 C# 实现。 这个错误报告提到了支持带有 SNI 的 HTTPS 请求的 mono 版本。

于 2013-05-18T00:42:13.033 回答
-2

我知道这是一篇较旧的帖子,但我最近需要同样的东西。我有一个 C# 应用程序,用于在 C# 中动态创建网站。我需要站点的绑定在创建时设置“服务器名称指示”标志,因为我们试图在同一个 IP 地址上使用多个 SSL 站点。

事实证明,您现在可以在 C# 中执行此操作。您可以传递一个标志选项,该选项将打开 SNI 选项。我希望这可以帮助任何有这个问题的人。这是一个例子:

// Create site using server manager
ServerManager sm = new ServerManager();
Site mySite =  sm.Sites.Add("example.com", "C:\Test Website\", 443);

// Creating binding object to store SSL cert
var ibind = mySite.Bindings.CreateElement();
ibind.Protocol = "https";
ibind.BindingInformation = "*:443:" + domain;
ibind.CertificateHash = certificate.GetCertHash();

// This option will turn on SNI (server name indication)
ibind.SetAttributeValue("sslFlags", 1);

// Add the binding to the site
mySite.Bindings.Add(ibind);

于 2015-03-21T07:08:50.093 回答