Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.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

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# 在验证服务器之前读取ClientHello_C#_Ssl_Sni - Fatal编程技术网

C# 在验证服务器之前读取ClientHello

C# 在验证服务器之前读取ClientHello,c#,ssl,sni,C#,Ssl,Sni,我正在开发一个需要管理不同SSL服务的服务器应用程序。 每项服务都有自己的证书(当然,有不同的CN)。 我想使用提供正确的证书,但在验证流之前,我很难阅读ClientHello(SNI扩展所在的位置) 这就是代码: byte[] ClientHello = new byte[3000]; Stream TargetStream = TargetTcpClient.GetStream(); //Whatever I write here let me be unable to successfu

我正在开发一个需要管理不同SSL服务的服务器应用程序。 每项服务都有自己的证书(当然,有不同的CN)。 我想使用提供正确的证书,但在验证流之前,我很难阅读ClientHello(SNI扩展所在的位置)

这就是代码:

byte[] ClientHello = new byte[3000];
Stream TargetStream = TargetTcpClient.GetStream();

//Whatever I write here let me be unable to successfully authenticate 
//If I don't read anything (like in this way), it works perfectly  
int ClientHelloN = 0; //TargetStream.ReadByte();// TargetStream.Read(ClientHello, 0, 3000);

/*SNI Logic to extract Server-name*/
Certificate = new X509Certificate2(/*PATH TO CORRECT CERTIFICATE*/);

SslStream SSLStream = new SslStream(TargetStream);
SSLStream.AuthenticateAsServer(Certificate);

如果我直接使用带前缀的证书进行身份验证,没有问题,但是当我尝试在进行身份验证之前从流读取一个字节时,它在AuthenticateAsServer方法中永远循环。

一旦您从
TargetStream
读取数据,它就消失了,您的
SslStream
将丢失握手的开始


我相信您需要做的是将从
TargetTcpClient.GetStream()
获得的
包装为您自己的
子类。在您的子类中,您可以从流中读取字节来解析客户机Hello,但是您应该将所有这些字节保存在缓冲区中。您的子类应该重写-当调用重写时,如果缓冲区中有任何内容,则返回该内容,否则将调用转发到包装流。这种方法与类似,只是子类
StreamReader
只缓冲一个字符。

我知道我参加聚会有点晚了,但为什么不看看TcpClient的底层套接字呢

byte[] peekBuffer = new byte[16];
Socket socket = targetTcpClient.Client;
int bytesAvailable = socket.Receive(peekBuffer, SocketFlags.Peek);

if (bytesAvailable > 0)
{
    if (peekBuffer[0] == 0x16) // ClientHello?
    {
        SslStream secureStream = new SslStream(targetTcpClient.GetStream());

    }
}

GreatIdea!您认为服务器方法会调用Read方法来读取ClientHello吗?我试试看asap@Jamby从文档中可以看出,任何从流中读取的方法最终都会调用
Read()
函数,因此应该使用您的重写。请注意,
Stream.Read()
从链接答案中的
StreamReader.Read()
获取不同的参数,另外需要缓冲多个字节,但基本概念是相同的。祝你好运不幸的是,根据Reflector所说,SSLStream没有使用
Read
方法。我已经证明,通过简单地重写
Read
方法以及
ReadByte
BeginRead
方法,放置一个断点,当我调用
authenticatesServer
@Jamby时,它就不会碰到断点,这不是我在对流进行子类化时看到的行为。尝试该子类只是传递所有内容,并在读写时写入控制台;窥视字节仍然取决于你。很好!我没有想过只看第一个字节来检查它。即使可能不完全可靠,它也可以工作!我要试试看!