检测一个SslStream(客户端)连接到一个不安全的服务器(NetworkStream)

本文关键字:一个 服务器 NetworkStream 不安全 SslStream 检测 客户端 连接 | 更新日期: 2023-09-27 18:04:49

我有一个使用TcpListener.BeginAcceptTcpClient()方法侦听客户端的服务器。当客户端连接时,EndAcceptTcpClient方法给我TcpClient对象,然后我调用该客户端流的NetworkStream.BeginRead()来侦听从客户端传输的数据。

在客户端(期望服务器支持SSL)尝试连接到(不安全的)服务器之前,一切工作正常。当客户端尝试进行SSL握手时,从NetworkStream.BeginRead()回调中检索到的数据当然是乱码,但是在读取数据与来自客户端的"正常"消息之后检测此握手的正确方法是什么?

SSL握手是否有一个已知的头/签名标识符,我可以通过查看接收到的消息的前几个字节来检查,以区分正常消息和SSL握手之间的区别?从接收到的字节检查来看,它看起来可能是ASCII 0x16 0x03 0x01 0x00(又名<SYN><ETX><SOH><NUL>)。

如果有一个已知的头,是否有一个响应我可以发送到客户端告诉它认证失败(通过NetworkStream)?

检测一个SslStream(客户端)连接到一个不安全的服务器(NetworkStream)

我找到了一些关于SSL协议的信息(参考1,2),并且有一个标准头,我可以查找:

来自IBM参考站点2:

Byte   0       = SSL record type = 22 (SSL3_RT_HANDSHAKE)
Bytes 1-2      = SSL version (major/minor)
Bytes 3-4      = Length of data in the record (excluding the header itself).
Byte   5       = Handshake type
Bytes 6-8      = Length of data to follow in this record
Bytes 9-n      = Command-specific data

所以我可以寻找以0x16 [0x?? 0x??] [0x?? 0x??] 0x01开头的消息(SSL "Client Hello"消息)。

对于拒绝消息,看起来我可以发送0x15 0x?? 0x?? 0x00 0x02 0x02 0x28,它被翻译成<NACK>, (2byte版本),这是一个2字节长的消息,致命警报,"握手失败" 3.

SSL/TLS客户端将通过发送客户端Hello消息来发起握手。

在XDR符号中,这是:

  struct {
      ProtocolVersion client_version;
      Random random;
      SessionID session_id;
      CipherSuite cipher_suites<2..2^16-2>;
      CompressionMethod compression_methods<1..2^8-1>;
      select (extensions_present) {
          case false:
              struct {};
          case true:
              Extension extensions<0..2^16-1>;
      };
  } ClientHello;

这里,你看到的是在那之前:它是记录层,用于协议TLS 1.0 (0x0301)的握手消息(0x16)。它应该后跟一个长度,然后是0x01,用于"客户端你好"。和一个版本(可能不同:客户端支持的最高版本)。

从实用的角度来看,使用Wireshark查看实际的数据包(例如HTTPS)是值得的。本页上有一些示例捕获和示例(尽管您不需要破译流量来尝试做什么)。