客户:访问
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;
}
答案 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
方法应确保这与主机匹配。