Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET SslStream服务器是否可以尊重客户端发送的服务器名称指示器?_C#_Ssl_Https - Fatal编程技术网

C# .NET SslStream服务器是否可以尊重客户端发送的服务器名称指示器?

C# .NET SslStream服务器是否可以尊重客户端发送的服务器名称指示器?,c#,ssl,https,C#,Ssl,Https,客户:访问 1. 2. 服务器:有两个证书。 certificates1.pfx CN=host1.com和certificates2.pfx CN=host2.com 使用钢丝鲨 客户访问 1:C->S同步 2:CSACK 4:C->S客户端Hello包含服务器名称:host1.com ... 如何在C中选择证书1 5:CSSYN 2:CSACK 4:C->S客户端Hello包含服务器名称:host2.com ... 如何在C中选择证书2 5:c我不知道为什么targetHost是空白的 您

客户:访问 1. 2.

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

使用钢丝鲨 客户访问 1:C->S同步 2:CSACK 4:C->S客户端Hello包含服务器名称:host1.com ... 如何在C中选择证书1 5:CSSYN 2:CSACK 4:C->S客户端Hello包含服务器名称:host2.com ... 如何在C中选择证书2 5:c我不知道为什么targetHost是空白的

您还可以尝试检查remoteCertificate。根据服务器的标识。
ValidateServerCertificate方法应确保该方法与主机匹配。

无法使用本地CertificateSelectionCallback委托(SslStream充当服务器)选择证书。在这种情况下,您只能指定一个证书作为AuthenticateTaseServer方法的第一个参数

的文档还提到在客户端上使用LocalCertificateSelectionCallback委托:

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


最后,您可以检查这个问题,它似乎与您的问题相关

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

出现问题,因为NetworkStream不支持窥视字节。。。因此,您必须使用包装器流类。这里有一个实现:

还有一个问题——一旦得到字节,就必须找出如何处理它们。我确信这是特定于实现的,并且由几十个标准管理。。。我目前没有解析这些初始字节的实现,但当我将Win7 SSlStream客户端连接到Win8 SSlStream服务器,并捕获从客户端到服务器的第一个数据包时,我可以非常清楚地看到发送到服务器的请求服务器名(以这些字节为单位),通过上述PeekableStream可供服务器使用,在服务器上启动SslStream之前


所以这绝对是可能的。问题是在哪里可以找到可靠的实现。

我已经编辑了您的标题。请看,如果共识是否定的,他们就不应该这样做。回答得好。从技术上讲,可以通过在底层套接字对象上执行.Peek并解析SNI TLS扩展(如果存在于ClientHello中)来选择证书,然后使用该信息选择传递给服务器的证书。但是,可以肯定的是,这是非常重要的。如果您是对的,那么可以进行一些手动处理,试图从SNI TLS扩展检索客户端试图连接的服务器的主机名。但SslStream并没有提供现成的功能。除了一些自定义实现之外,另一个选择是使用另一个支持SNI的SSL库。即使在这种情况下,如果某些客户端无法使用TLS并退回到SSL2或SSL3,它也不会完全可靠。事实上:在SSL2/SSL3之外,基于Windows XP的客户端IE、Office等以及一些移动设备客户端支持TLS,但不支持SNI TLS扩展。在这些情况下,任何服务器都无法区分客户端需要的主机名,唯一的方法是在SubjectAltNames字段中返回一个包含多个主机名的证书。
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;
}