1

我正在开发一个需要管理不同 SSL 服务的服务器应用程序。每个服务都有自己的证书(当然,有不同的 CN)。我想使用SNI来提供正确的证书,但是在对流进行身份验证之前,我正在努力阅读 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 方法中永远循环。

4

2 回答 2

2

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

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());

    }
}
于 2014-08-05T08:24:41.623 回答
1

一旦您从中读取数据TargetStream就消失了,您SslStream将错过握手的开始。

我相信你需要做的就是用你自己的子类包装Stream你得到的东西。在您的子类中,您可以从流中读取字节以解析 Client Hello,但您应该将所有这些字节保存在缓冲区中。您的子类应该覆盖Stream.Read() - 当您的覆盖被调用时,如果缓冲区中有任何内容,则返回它,否则将调用转发到包装的流。该方法类似于此答案,除了子类并且仅缓冲单个字符。TargetTcpClient.GetStream()StreamStreamReader

于 2013-07-02T19:02:46.213 回答