1

我有一台服务器正在使用一种TcpListener.BeginAcceptTcpClient()方法侦听客户端。当客户端连接时,该EndAcceptTcpClient方法会为我提供TcpClient对象,然后我调用该客户端流NetworkStream.BeginRead()以侦听从客户端传输的数据。

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

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

如果有已知的标头,是否可以向客户端发送响应以告诉它身份验证失败(通过 NetworkStream)?

4

2 回答 2

1

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

来自 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>,(2 字节版本),这是一个 2 字节长的消息,致命警报,“握手失败” 3

于 2013-03-20T17:44:55.867 回答
0

SSL/TLS 客户端将通过发送Client 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;

在这里,您看到的是在此之前:它是记录层0x16,用于具有协议 TLS 1.0 ( )的握手消息 ( 0x0301)。它后面应该跟着一个长度,然后0x01是“Client Hello”和一个版本(可能不同:客户端支持的最高版本)。

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

于 2013-03-20T17:43:34.673 回答