目录

第一阶段:准备阶段 - DNS 解析

第二阶段:建立连接 - 三层握手与加密信道

步骤 1: TCP 三次握手 (建立可靠连接)

步骤 2: TLS 四次握手 (建立安全加密)

第三阶段:数据传输 - 加密的 HTTP 通信

第四阶段:连接终止 - 四次挥手


第一阶段:准备阶段 - DNS 解析

在正式通信开始前,客户端需要知道服务器的 IP 地址。

  1. DNS 查询: 浏览器会检查本地缓存和 Hosts 文件,如果没有找到 www.example.com 对应的 IP 地址,它会向配置的 DNS 服务器发起查询。

  2. 获取 IP: DNS 服务器返回 www.example.com 的 IP 地址,例如 93.184.216.34。至此,客户端知道了目标在哪里。

第二阶段:建立连接 - 三层握手与加密信道

现在,客户端(浏览器)和服务器(93.184.216.34)需要建立一条可靠的、加密的通信信道。这个过程是分层的。

步骤 1: TCP 三次握手 (建立可靠连接)

目标:在客户端和服务器之间建立一条可靠的 TCP 连接。默认端口是 443。

  1. SYN (同步)

    • 客户端发送一个 TCP 数据包到服务器。这个包的特殊之处在于,其 TCP 头部的SYN标志位被设置为 1。

    • 同时,客户端会随机生成一个初始序列号 Seq = X,并放在包中。

    • 此时状态: 客户端进入 SYN-SENT 状态。

  2. SYN-ACK (同步-确认)

    • 服务器收到 SYN 包后,如果同意连接,会回复一个 TCP 数据包。

    • 这个包的 TCP 头部同时设置了SYNACK 标志位。

    • 服务器会确认客户端的序列号:Acknowledgment Number = X + 1

    • 服务器也会随机生成自己的初始序列号 Seq = Y

    • 此时状态: 服务器进入 SYN-RECEIVED 状态。

  3. ACK (确认)

    • 客户端收到 SYN-ACK 包后,会再次向服务器发送一个确认包。

    • 这个包的 TCP 头部ACK标志位被设置为 1。

    • 确认号 Acknowledgment Number = Y + 1,自己的序列号 Seq = X + 1

    • 此时状态: 客户端和服务器都进入 ESTABLISHED 状态。

至此,TCP 连接已建立。这是一个双向的、可靠的字节流通道。接下来,所有的 HTTPS 素材都将经过这个通道传输。

步骤 2: TLS 四次握手 (建立安全加密)

目标:在已建立的 TCP 连接之上,建立一个安全的加密信道。这个过程就是 TLS 握手。

  1. ClientHello

    • 客户端向服务器发送一条明文消息,内容包括:

      • 协助的 TLS 版本(如 TLS 1.2)。

      • 客户端生成的随机数(Client Random)。

      • 支持的密码套件列表(如 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)。

      • 支撑的压缩方式。

      • (可选)服务器名称指示(SNI),用于告诉服务器客户端想访问哪个域名(在虚拟主机场景下至关重要)。

  2. ServerHello

    • 服务器回应一条明文消息,内容包括:

      • 选定的 TLS 版本。

      • 服务器生成的随机数(Server Random)。

      • 从客户端列表中选择的一个密码套件。

      • 服务器的数字证书。这个证书含有了服务器的公钥,并由证书颁发机构(CA)签名,用于向客户端证明身份。

  3. 客户端验证与密钥交换

    • 证书验证: 客户端(浏览器)验证服务器的证书:

      • 检查证书是否在有效期内。

      • 检查证书的签发者是否是受信任的 CA。

      • (可选)检查证书中的域名是否与访问的域名一致。

      • 采用 CA 的公钥验证证书的签名,确保证书未被篡改。

    • 生成预备主密钥: 客户端会再生成一个随机数,称为 "Pre-Master Secret"。

    • 加密并发送: 客户端使用服务器证书中的公钥加密这个 "Pre-Master Secret",然后将加密后的结果发送给服务器。

  4. 服务器确认与密钥交换

    • 解密预备主密钥: 服务器用自己的私钥解密客户端发来的数据,得到 "Pre-Master Secret"。

    • (对于支持前向保密的密钥交换,如 ECDHE): 服务器可能会发送一个包含其 DH 参数的 Server Key Exchange 消息,并由证书私钥签名。客户端验证签名后,双方通过 DH 算法协商出 "Pre-Master Secret"。

  5. 生成会话密钥

    • 此时,客户端和服务器都拥有了三个相同的随机数:Client Random, Server Random, 和 Pre-Master Secret。

    • 双方使用相同的密钥派生函数,根据这三个随机数,生成用于本次会话的主密钥(Master Secret)

    • 最后,再由主密钥派生出实际用于加密和解密的对称会话密钥(例如 AES 密钥),以及用于验证数据完整性的 MAC 密钥。

  6. 握手完成

    • 客户端和服务器互相发送一条 "Change Cipher Spec" 消息,通知对方:“从现在开始,后续的所有通信都将使用刚刚协商的会话密钥进行加密。”

    • 继而双方再发送一条 "Finished" 消息,这条消息本身已经是加密的,里面含有了对之前所有握手内容的摘要,用于验证整个握手过程是否被篡改。

至此,TLS 安全连接已建立。接下来,所有在 TCP 连接上传输的 HTTP 数据,都会先被 TLS 层加密。

第三阶段:数据传输 - 加密的 HTTP 通信

现在,我们有了一个建立在 TCP 之上的、加密的 TLS 隧道。

  1. 应用层数据(HTTP): 浏览器构造一个普通的 HTTP 请求,例如 GET /index.html HTTP/1.1

  2. TLS 加密: TLS 层收到该明文的 HTTP 请求,使用协商好的对称会话密钥对其进行加密,形成TLS 记录

  3. TCP 分段: TCP 层将加密后的 TLS 数据视为普通数据流。它可能会将其分割成合适大小的TCP 段,并为每个段加上 TCP 头部(包含源端口、目标端口、序列号、确认号等)。

  4. IP 封装与路由: IP 层收到 TCP 段后,为其加上IP 头部,形成 IP 包。IP 头部包括:

    • 源 IP 地址: 你的电脑的 IP。

    • 目标 IP 地址93.184.216.34

    • 其他信息(如 TTL、协议号等)。

    路由过程开始

    • 操作系统根据目标 IP 地址和本地路由表,判断该包应该发送到哪个网关(通常是路由器)。

    • 电脑通过局域网(如 Wi-Fi)将 IP 包发送给路由器。

    • 路由器查看目标 IP,并根据自己的路由表,决定下一个要发送到的路由器。这个过程在互联网上的每一个路由器上重复,直到数据包到达目标服务器所在的网络。

    • 每个中间路由器都会解开 MAC 头部,查看 IP 头部,根据路由表做出转发决策,继而重新封装一个新的 MAC 头部,发往下一跳。这就是“路由”

  5. 物理传输: 最终,IP 包被转换成电信号或光信号,在物理线路上传输。

服务器端的反向流程:

  1. 服务器的网络接口收到数据帧,层层解封装。

  2. IP 层 TCP,将数据交给 TCP 层。就是: 去掉 IP 头部,发现协议

  3. TCP 层: 去掉 TCP 头部,根据端口号 443,将信息段重组为完整的数据流,交给 TLS 层。

  4. TLS 层: 启用会话密钥解密数据,得到明文的 HTTP 请求。

  5. HTTP 层: Web 服务器(如 Nginx)处理 GET /index.html 请求,准备响应数据(如 HTML 文件)。

响应流程与请求完全对称:服务器的 HTTP 响应 -> TLS 加密 -> TCP 分段 -> IP 封装 -> 路由 -> 访问端电脑 -> 反向解封装 -> TLS 解密 -> 浏览器渲染 HTML。

第四阶段:连接终止 - 四次挥手

通信完成后,双方需要优雅地关闭连接。

  1. FIN (结束)

    • 客户端主动发送一个 TCP 包,其FIN标志位设置为 1,表示数据发送完毕,请求关闭连接。

  2. ACK (确认)

    • 服务器收到 FIN 后,发送一个 ACK 包进行确认。

    • (此时,从客户端到服务器的单向连接关闭,但服务器到客户端的连接可能还在传输数据)。

  3. FIN (结束)

    • 当服务器也数据发送完毕后,它会发送一个自己的 FIN 包给客户端。

  4. ACK (确认)

    • 客户端收到服务器的 FIN 后,发送一个 ACK 包进行确认。

    • 客户端会等待一个超时时间(TIME_WAIT),确保服务器收到了这个 ACK,之后完全关闭连接。

至此,整个 TCP+TLS 连接完全关闭。