daniel.haxx.se

cURL and libcurl

cURL 中的 HTTPS RR

2025年3月31日 Daniel Stenberg 发表评论

RFC 9460 描述了一种名为 HTTPS 的 DNS 资源记录 (RR)。为了强调我们讨论的正是这个名为 HTTPS 的 DNS 记录,我们尽量始终将它称为 HTTPS RR。

cURL 目前在 git 中提供 实验性 的 HTTPS RR 支持。 实验性意味着您需要在构建时显式启用它才能使用。

cmake -DUSE_HTTPSRR=ON ...

或者

configure --enable-httpsrr ...

HTTPS RR 有什么用?

它是一个 DNS 字段,提供关于目标主机名的服务元数据。 在很多方面,它是 SRV 和 URI 的替代记录,而后者从未真正用于 Web 和 HTTP。 它也在某种程度上取代了 HSTS 和 alt-svc 头部。

以下是它提供的一些数据:

ECH 配置

ECH 是 Encrypted Client Hello 的缩写,是用于加密 TLS 握手中 SNI 字段的既定系统。 您可能还记得,SNI 字段是 HTTPS 连接中最后剩余的以明文形式发送的部分之一,因此会向主动监听者揭示客户端打算与哪个站点通信。 ECH 通过加密名称来隐藏此信息。

为了使 ECH 能够工作,客户端需要在实际执行握手之前获取信息,而该字段提供了此数据。 cURL 具有实验性的 ECH 支持。

ECH 已经开发了几年,但尚未在 RFC 中发布。

ALPN 列表

提供了一个 ALPN 标识符列表。 这些标识符基本上告诉客户端此服务器想要使用哪些 HTTP 版本(通过 HTTPS)。 如果此列表包含 HTTP/1.1 并且我们被要求执行 HTTP:// 传输,则意味着客户端应升级到 HTTPS。 因此,某种程度上取代了 HSTS。

我认为这里提供的关键 ALPN ID 是 'h3',它告诉客户端此服务器支持 HTTP/3,我们可以尝试在第一次传输时使用它。 以前_正确_升级到 HTTP/3 的选项是等待 alt-svc 响应头部,该头部可以指示后续的连接尝试。 然后,由于客户端通常首选重用当时已经存在的 HTTP/2 或 HTTP/1 连接,因此会显着延迟升级。

目标

该服务在另一个主机名上提供。 类似于 alt-svc。 它还可以提供有关如何为不同的“服务”访问此站点的信息,以便 TCP/TLS 连接采用一种方式,而 QUIC 连接采用另一种方式。

端口

它可以告诉客户端该服务托管在不同的端口号上。

IP 地址

它可以提供名称的 IPv4 和 IPv6 地址列表。 据说是在同时没有检索到 A 或 AAAA 字段的情况下使用。

获取 DNS 记录

不幸的是,将 HTTPS RR 支持添加到现有的 TCP 客户端(例如 cURL)中,并不像我们希望的那么简单。

一个主要障碍是,常规的主机名解析是通过 POSIX 函数 getaddrinfo() 完成的,并且此函数不了解或不支持 HTTPS RR,并且预计将来也不会添加此类支持。 该 API 实际上不允许这样做。 像 cURL 这样的客户端只需使用其他方式获取额外的记录。

cURL 是如何做的

cURL,或者更确切地说是 libcurl,在源代码中有三种不同的方法来解析主机名,其中大多数构建都具有两个选项:

  1. DoH (DNS-over-HTTPS) – cURL 使用 HTTPS 向指定的服务器发送 DNS 请求。 用户需要明确要求这样做并指出 DoH URL。
  2. 使用本地解析器。 然后,libcurl 构建可以使用 c-ares 或 getaddrinfo() 来解析主机名,以在未使用 DoH 或代理等时使用。

DoH

libcurl 中的 DoH 代码是原生实现(它不使用任何第三方库),并且 libcurl 具有用于发送 HTTPS RR 请求和解析响应的代码。

getaddrinfo

当使用此 API 进行名称解析时,仍然需要使用 c-ares 构建 libcurl,以便提供请求 HTTPS RR 的服务。 然后,libcurl 使用 getaddrinfo() “正常”地解析主机名(通常在单独的辅助线程中启动),并使用 c-ares 并行请求 HTTPS RR。

c-ares

c-ares 用于名称解析时,它也会同时请求 HTTPS RR。 这意味着 c-ares 会请求 A、AAAA 和 HTTPS 记录。

现有的缺点

我们尚未提供运行时选项来禁用使用 HTTPS-RR,因此,如果您在启用它的情况下进行构建,则始终会尝试使用它。 我认为我们需要提供这样一个选项,以便在 HTTPS 记录完全错误或用户想要调试或以其他方式进行试验时使用。

cURL 目前尚未处理相当复杂的 HTTPS RR 的每个方面。 我们已决定缓慢推进,并将我们的实现重点放在似乎已部署并实际使用的资源字段部分上。

已部署

今天已经有站点在使用这些记录。 例如,Cloudflare 似乎为其托管的许多站点提供它。 如果您今天启用 HTTPS-RR,则有很多机会可以试用它。 既可以用于常规服务和协议切换,也可以用于 ECH。

请继续并在构建中启用它,试用它并告诉我们哪些有效,哪些无效。 我们很乐意在此基础上继续前进,如果我们从用户那里得到确认它确实有效,我们可能很快就能将其从实验状态中移出。

cURL and libcurldnsECHHTTPS-RR