.NET SslStream AuthenticateAsServer可以尊重客户端发送的服务器名称指示器吗?

时间:2013-09-12 02:16:00

标签: c# ssl https

客户:访问
    1. https://host1.com/
    2. https://host2.com/

服务器:有两个证书。
  certificates1.pfx CN = host1.com和certificates2.pfx CN = host2.com

使用wireshark
客户访问https://host1.com/
1:C - > S SYN
2:C< -S SYN,ACK
3:C - > S ACK
4:C - > S客户端Hello(包含服务器名称:host1.com)
...如何在C#中选择certificate1 5:C< -S服务器Hello,证书,服务器Hello完成

客户访问https://host2.com/
1:C - > S SYN
2:C< -S SYN,ACK
3:C - > S ACK
4:C - > S客户端Hello(包含服务器名称:host2.com)
...如何在C#中选择certificate2 5:c< - S服务器Hello,证书,服务器Hello Hello完成

SslStream sslStream = new SslStream(
  clientStream,
  false,
  new RemoteCertificateValidationCallback(ValidateServerCertificate),
  new LocalCertificateSelectionCallback(SelectLocalCertificate)
);

X509Certificate2 certificate = new X509Certificate2("certificates1.pfx");

sslStream.AuthenticateAsServer(certificate , false, SslProtocols.Tls | SslProtocols.Ssl3 | SslProtocols.Ssl2, true);

private X509Certificate SelectLocalCertificate(object sender, string targetHost, X509CertificateCollection localCertificates, X509Certificate remoteCertificate, string[] acceptableIssuers)
{
  //In Debug, targetHost is empty string and remoteCertificate=null
  //I can't return right Certificates
  return null;
}
private bool ValidateServerCertificate( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    return true;
}

3 个答案:

答案 0 :(得分:2)

虽然SslStream本身不支持SNI,但我已经确认可以解决这个问题。在服务器上,如果在启动SslStream之前从NetworkStream中读取了一些字节,则可以看到从客户端发送到服务器的初始数据包实际上是客户端hello,其中包括请求的服务器名称。

有一个问题,因为NetworkStream不支持偷看字节......所以你必须使用包装器流类。 (这里有一个实现:https://stackoverflow.com/a/7281113/1726692)。

还有另一个问题 - 一旦获得字节,就必须弄清楚如何处理它们。我确定这是特定于实现的,并且由许多标准管理...我目前没有解析这些初始字节的实现,但是当我将Win7 SSlStream客户端连接到Win8 SslStream服务器时,我捕获从客户端到服务器的第一个数据包,我可以非常清楚地看到在服务器上启动SslStream之前,服务器可以通过上面的PeekableStream查找发送到服务器的请求服务器名称。

所以这绝对有可能。问题是在哪里找到可靠的实施方案。

答案 1 :(得分:1)

使用SslStream充当服务器的LocalCertificateSelectionCallback委托不能选择证书。在这种情况下,您只能指定一个证书,作为AuthenticateAsServer方法的第一个参数。

SslStream Class on MSDN的文档还提到了客户端上LocalCertificateSelectionCallback委托的用法:

  

如果服务器需要客户端身份验证,则客户端必须指定   一个或多个用于身份验证的证书如果客户有更多   一个证书,客户端可以提供一个   LocalCertificateSelectionCallback委托选择正确的   服务器证书。

最后,您可以查看与您的问题Does SslStream use LocalCertificateSelectionCallback when acting as a server?

相关的问题

答案 2 :(得分:0)

我不确定为什么targetHost是空白的。

您还可以尝试检查remoteCertificate.Subject以识别服务器。 您的ValidateServerCertificate方法应确保这与主机匹配。