ossl-guide-quic-introduction
名称
ossl-guide-quic-introduction - OpenSSL 指南:OpenSSL 中 QUIC 简介
简介
本页将介绍一些基本的 QUIC 概念和背景,以及它如何在 OpenSSL 中使用。它假设您对 UDP/IP 和套接字有一定的了解。它还假设您熟悉一些 OpenSSL 和 TLS 基础知识(参见 ossl-guide-libraries-introduction(7) 和 ossl-guide-tls-introduction(7))。
什么是 QUIC?
QUIC 是一种通用协议,使应用程序能够通过网络安全通信。它在 RFC9000 中定义(参见 https://datatracker.ietf.org/doc/rfc9000/)。QUIC 集成了 TLS 协议的部分内容用于连接建立,但独立地保护数据包。它提供了与 TLS 相似的安全保证,例如机密性、完整性和身份验证(参见 ossl-guide-tls-introduction(7))。
QUIC 提供了许多优势
- 多路流
-
它支持多路通信流(参见下面的 "QUIC 流"),允许在 QUIC 上构建的应用程序协议为客户端和服务器之间的通信创建任意数量的字节流。这允许应用程序协议避免一个数据包因等待另一个数据包传递而被阻塞的问题(通常称为“排队阻塞”)。它还使应用程序能够在无需客户端和服务器之间进行数据包的往返交换的情况下打开额外的逻辑流,而这在打开额外的 TLS/TCP 连接时是必需的。
- HTTP/3
-
由于 QUIC 是 HTTP/3 的基础,因此对 QUIC 的支持也使应用程序能够使用合适的第三方库使用 HTTP/3。
- 快速连接启动
-
未来版本的 OpenSSL 将提供对 0-RTT 连接启动的支持,允许在没有任何等待时间的情况下启动与服务器的连接并传输应用程序数据。这类似于 TLS 1.3 的 0-RTT 功能,但也避免了打开 TCP 套接字所需的往返行程;因此,它类似于 TLS 1.3 0-RTT 和 TCP Fast Open 的组合。
- 连接迁移
-
未来版本的 OpenSSL 将提供对连接迁移的支持,允许连接无缝地应对 IP 地址变化。
- 基于数据报的使用案例
-
未来版本的 OpenSSL 将提供对 QUIC 数据报扩展的支持,允许在单个连接上支持 TLS 和 DTLS 样式的使用案例。
- 作为应用程序库实现
-
由于大多数 QUIC 实现,包括 OpenSSL 的实现,都是作为应用程序库而不是由操作系统实现的,因此应用程序可以获得 QUIC 的好处,而无需等待 OS 更新的部署。QUIC 协议的未来演进和增强可以像应用程序更新一样快速地交付,而无需依赖于 OS 更新节奏。
- 通过单个 UDP 套接字进行多路复用
-
由于 QUIC 基于 UDP,因此可以在与其他基于 UDP 的协议(如 RTP)相同的 UDP 套接字上多路复用 QUIC 连接。
QUIC 基于时间的事件
OpenSSL 中的 TLS 实现和 QUIC 实现之间的关键区别在于时间的处理方式。QUIC 协议要求定期执行各种操作,无论是否正在传输或接收应用程序数据。
OpenSSL 引入了新的函数 SSL_handle_events(3),它将自动处理必须处理的任何未决的基于时间的事件。或者,调用任何 I/O 函数,例如 SSL_read_ex(3) 或 SSL_write_ex(3),也将处理这些事件。还有 SSL_get_event_timeout(3),它告诉应用程序在必须调用 SSL_handle_events(3)(或任何 I/O 函数)之前剩下的时间量。
幸运的是,不使 QUIC 连接处于空闲状态且定期调用 I/O 函数的阻塞应用程序通常不必担心这个问题。但是,如果您正在开发非阻塞应用程序或可能使 QUIC 连接处于空闲状态一段时间,那么您将需要安排调用这些函数。
OpenSSL 提供可选的“线程辅助模式”,它将自动创建一个后台线程,并定期以线程安全的方式调用 SSL_handle_events(3)。这为应用程序提供了一种简单的方法来满足 QUIC 对基于时间的事件的要求,而无需实现特殊逻辑来完成它。
QUIC 和 TLS
QUIC 在其实现中重复使用 TLS 协议的一部分。特别是 TLS 握手也存在于 QUIC 中。TLS 握手消息被包装在 QUIC 协议消息中,以便将它们发送到对等方。一旦 TLS 握手完成,所有应用程序数据都完全使用 QUIC 协议消息发送,而无需使用 TLS - 尽管在某些情况下仍然可以发送一些 TLS 握手消息。
QUIC 和 TLS 之间的这种关系意味着 OpenSSL 中许多适用于 TLS 连接的 API 函数也适用于 QUIC 连接,应用程序可以使用它们完全相同的方式。有些函数根本不适用于 QUIC,而另一些函数的语义则发生了改变。您应该参考每个函数的文档页面,以了解它如何应用于 QUIC。通常,如果 QUIC 未在手册页中提到,那么这些函数适用于 TLS 和 QUIC。
QUIC 流
QUIC 引入了“流”的概念。流为在端点之间发送和接收应用程序数据提供了一种可靠的机制。传输的字节保证以与它们发送相同的顺序接收,而不会丢失任何数据或重新排序字节。TLS 应用程序实际上每个 TLS 连接有一个双向流可用。QUIC 应用程序可以为每个连接拥有多个单向或双向流可用。
在 OpenSSL 中,SSL 对象用于表示连接和流。QUIC 应用程序创建一个初始 SSL 对象来表示连接(称为连接 SSL 对象)。连接完成后,可以创建额外的 SSL 对象来表示流(称为流 SSL 对象)。除非另有配置,否则连接 SSL 对象还会关联一个“默认”流,因此您仍然可以向其写入数据并从中读取数据。某些 OpenSSL API 函数只能与连接 SSL 对象一起使用,而另一些只能与流 SSL 对象一起使用。检查每个函数的文档以确认在任何特定上下文中可以使用哪种类型的 SSL 对象。连接 SSL 对象(它附带一个默认流)可以在需要连接 SSL 对象的上下文中使用,也可以在需要流 SSL 对象的上下文中使用。
套接字和阻塞
TLS 假设其底层传输层协议的“流”类型语义(通常通过使用 TCP 实现)。但是,QUIC 通过使用 UDP 假设“数据报”类型语义。使用 QUIC 的 OpenSSL 应用程序负责创建 BIO 来表示底层传输层。此 BIO 必须支持数据报,通常是 BIO_s_datagram(3),但还有其他 BIO 选择可用。参见 bio(7) 以了解 OpenSSL 的 BIO 概念的介绍。
OpenSSL TLS 应用程序和 OpenSSL QUIC 应用程序之间的重大区别是阻塞的实现方式。在 TLS 中,如果您的应用程序期望阻塞行为,则将底层套接字配置为阻塞。相反,如果您的应用程序希望非阻塞行为,则将底层套接字配置为非阻塞。
对于 OpenSSL QUIC 应用程序,底层套接字必须始终配置为非阻塞。但是,SSL 对象默认情况下仍将以阻塞模式运行。因此,从应用程序的角度来看,对 SSL_read_ex(3)、SSL_write_ex(3) 和其他 I/O 函数等函数的调用仍然会阻塞。OpenSSL 本身为 QUIC 提供了这种阻塞功能,而不是套接字。如果需要非阻塞行为,则应用程序必须调用 SSL_set_blocking_mode(3)。
进一步阅读
参见 ossl-guide-quic-client-block(7),以查看将这些概念应用于编写简单阻塞 QUIC 客户端的示例。
参见
ossl-guide-introduction(7)、ossl-guide-libraries-introduction(7)、ossl-guide-libssl-introduction(7)、ossl-guide-tls-introduction(7)、ossl-guide-tls-client-block(7)、ossl-guide-quic-client-block(7)、bio(7)
版权
版权所有 2023 OpenSSL 项目作者。保留所有权利。
根据 Apache 许可证 2.0 版(“许可证”)许可。除符合许可证的规定外,您不得使用此文件。您可以在源代码分发中的 LICENSE 文件或 https://www.openssl.org/source/license.html 中获取副本。