目录 ← 首页
CS168

TLS:安全字节流

安全字节流

TCP 本身无法抵御网络攻击者。网络中的某些角色(例如恶意路由器、在网络线路上嗅探数据包的攻击者)可能会在 TCP 数据包传输过程中读取甚至修改它们。

此外,使用 TCP 时,你可能会连接到攻击者而非真正的服务器。假设你想连接到一个银行网站,你对www.bank.com进行 DNS 查询。攻击者(例如入侵了解析器或路由器的人)篡改了 DNS 响应,使www.bank.com映射到攻击者的 IP 地址 6.6.6.6。现在,当你与银行网站建立 TCP 连接时,实际上是在与攻击者通信。你可能最终会把银行密码发送给攻击者!

为了解决这些安全问题,我们在 TCP 之上添加了一种新的协议 ——传输层安全(TLS)

TLS 可以被视为一种 4.5 层协议,位于 TCP 和 HTTP 等应用层协议之间。(我们使用 4.5 这样奇怪的数字,是因为已过时的第 5 层和第 6 层与安全性无关。)TLS 依赖于 TCP 的字节流抽象,因此它不考虑单个数据包或数据包丢失 / 重排序的问题。TLS 向应用程序提供与 TCP 完全相同的字节流抽象,但该字节流现在可以抵御网络攻击者。这就是为什么 HTTP 和 HTTPS 是语义上完全相同的协议。唯一的区别是,HTTPS 运行在 TLS-over-TCP 的安全字节流之上,而 HTTP 则运行在没有 TLS 的原始 TCP 之上。

img

为了区分 HTTPS 和 HTTP,我们使用 80 端口用于 HTTP 连接,443 端口用于 HTTPS 连接。服务器可以通过将所有 80 端口的请求重定向到 443 端口,强制用户使用 HTTPS。

TLS 握手

从高层次来看,TLS 使用加密技术对通过字节流发送的消息进行加密。TLS 还使用其他加密协议(消息认证码)来防止攻击者在消息通过网络传输时对其进行篡改。

为了加密流量,TLS 必须先进行额外的握手,以交换密钥并验证服务器的身份(例如,确认是真正的银行,而不是冒充银行的人)。

由于 TLS 构建在 TCP 之上,TCP 三次握手首先会正常进行。这会创建一个(不安全的)字节流,使所有后续消息(包括 TLS 握手)都可以无需考虑单个数据包而进行传输。

此时,TLS 握手可以开始了:

img

  1. 客户端和服务器交换问候消息。问候消息包含随机数,这确保每次握手都会生成不同的密钥。(如果我们每次都使用相同的密钥,而攻击者入侵并获取了该密钥,那将是很糟糕的。)问候消息还允许客户端和服务器协商使用特定的加密协议。客户端的问候消息列出了客户端支持的所有加密方案,服务器的问候消息会从中选择一个使用。

  2. 服务器发送真实性证书。这将使客户端能够验证它正在与真正的服务器通信,而不是冒充者。客户端实际验证此证书的过程有些复杂,这里我们不做讨论。

  3. 客户端和服务器推导出一个只有它们两者知道的秘密。由于此时字节流仍然不安全,它们需要一种加密协议,能够在不安全的信道上共享秘密。这里我们不讨论细节,但如果你熟悉 RSA 公钥加密(例如加州大学伯克利分校的 CS 70 课程中涉及的内容),这就是一种可能用于此处的加密方案。客户端使用服务器的公钥加密一个秘密并发送给服务器。只有服务器知道相应的私钥,能够解密该消息并获取秘密。

  4. 客户端和服务器根据共享的秘密以及问候消息中的随机值推导出密钥。使用该秘密确保攻击者无法获取密钥。使用随机值确保我们每次都能推导出不同的密钥。这种推导由客户端和服务器在本地独立完成。密钥实际上从未在网络上传输,因此攻击者没有机会获取它们。

  5. 客户端和服务器交换一些确认信息,以确认它们推导出了相同的秘密,并且到目前为止通过网络发送的消息没有被任何人篡改(因为此时字节流仍然不安全)。

至此,握手完成,所有后续消息都使用密钥进行加密(同时也使用消息认证码来防止篡改)。我们现在已经在 TCP 连接之上建立了一个安全的字节流,应用程序可以在这个安全的字节流之上交换数据。

(注:文档部分内容可能由 AI 生成)