ssl - 如何检测传入的 SSL (https) 握手(SSL 有线格式)?

标签 ssl protocols handshake

我正在编写一个接受传入 TCP 连接的服务器。假设服务器已经接受了一个 TCP 连接,并且已经从客户端接收到 16(或更多)字节。知道这 16 个字节后,服务器如何检测客户端是否要发起 SSL 握手?

我做了一个实验,表明在我的 Linux 系统上通过 SSL 连接到本地主机(127.0.0.1 或 AF_UNIX)使客户端发送以下握手(hexdump),后跟 16 个看似随机的字节:

8064010301004b0000001000003900003800003500001600001300000a07
00c000003300003200002f03008000000500000401008000001500001200
0009060040000014000011000008000006040080000003020080

服务器应该如何探测这前几个字节,以便能够确定客户端是否正在发送 SSL 握手?探测器必须为所有有效的 SSL 握手返回 true,并且它必须以高概率为客户端发送的不是 SSL 握手的消息返回 false。不允许使用任何库(如 OpenSSL)进行探测。探针必须是简单的代码(例如 C 或 Python 中的几十行代码)。

最佳答案

客户端总是首先发送所谓的 HelloClient 消息。它可以是 SSL 2 格式或 SSL 3.0 格式(与 TLS 1.0、1.1 和 1.2 中的格式相同)。

而且 SSL 3.0/TLS 1.0/1.1/1.2 客户端也有可能发送旧格式 (SSL 2) 的 HelloClient,只是数据中的版本号更高。因此,对于较新的客户端,检测 SSL 2 HelloClient 也是必要的。 (例如 Java SSL 实现就是这样做的)

假设“b”是您的缓冲区。我试图绘制消息格式图。

SSL 2

+-----------------+------+-------
| 2 byte header   | 0x01 | etc.
+-----------------|------+-------
  • b[0] & 0x80 == 0x80(这意味着 b[0] 的最高有效位是'1')

  • ((b[0] & 0x7f) << 8 | b[1]) > 9 (表示 b[0] 的低 7 位和 b[1] 是数据的长度。你你的缓冲区中可以有更少的东西,所以你不能检查它们。但是从消息格式我们知道有 3 个 2 字节的字段(长度字段),并且密码列表字段中至少有一个项目(大小为 3)。所以应该有至少为 9 个字节(数据长度 >= 9)。

  • b[2] 必须是 0x01(消息类型“ClientHello”)

SSL 3.0 或 TLS 1.0、1.1 和 1.2

+-------+------------------+------------------+--------+------
| 0x16  | 2 bytes version  |  2 bytes length  |  0x01  |  etc.
+-------+------------------+------------------+--------+------
  • b[0] == 0x16(消息类型“SSL 握手”)

  • b[1] 应该是 0x03(目前最新的主要版本,但谁知道将来呢?)

  • b[5]必须是0x01(握手协议(protocol)消息“HelloClient”)

引用可以看http://www.mozilla.org/projects/security/pki/nss/ssl/draft02.htmlhttps://www.rfc-editor.org/rfc/rfc4346

关于ssl - 如何检测传入的 SSL (https) 握手(SSL 有线格式)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3897883/

相关文章:

ios - id<>delegate 这个语法是什么意思?

ios - conformsToProtocol 不会用自定义协议(protocol)编译

c# - Http 请求在从 ServiceBase.OnShutdown 发送时中止,但在 OnStop 中未中止

Apache、Ubuntu、SSL、别名和虚拟

documentation - 有没有办法在 protobuf (proto2) 中创建类型别名?

java - 禁止 Java (JSSE) 中的 SSL 重新握手?

ssl - 客户端的 TLS 握手

sockets - 如何在 JAVA JSSE 中操作 TLS/SSL 中的握手消息?

ssl - 去接受来自远程主机的自签名证书

ssl - 将 SSL 证书上传到 Cloudfront 的 IAM