curl 库 CURLOPT_DOH_SSL_VERIFYHOST 详解:DoH 服务器证书主机名校验的安全开关
curl 库 CURLOPT_DOH_SSL_VERIFYHOST 详解DoH 服务器证书主机名校验的安全开关【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl本指南围绕 libcurl 的CURLOPT_DOH_SSL_VERIFYHOST选项展开讲解它在 DNS-over-HTTPSDoH请求中如何校验 DoH 服务器证书的主机名并给出默认值、取值语义、命令行对应参数与底层源码实现。读完你将掌握何时需要关闭 DoH 主机名校验、关闭后带来的安全风险以及该选项与CURLOPT_SSL_VERIFYHOST、CURLOPT_DOH_SSL_VERIFYPEER之间的区别与配合方式。选项概览CURLOPT_DOH_SSL_VERIFYHOST用于控制 libcurl 是否校验 DoHDNS-over-HTTPS服务器 SSL 证书中的主机名字段。它只作用于发往 DoH 服务器的请求是 CURLOPT_SSL_VERIFYHOST 在 DoH 场景下的对应物DoH equivalent。#include curl/curl.h CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DOH_SSL_VERIFYHOST, long verify);选项类型long取值只能为 0、1 或 2。协议TLS仅影响 HTTPS 形式的 DoH 请求。适用 TLS 后端全部OpenSSL、GnuTLS、Schannel、wolfSSL、mbedTLS 等。加入版本7.76.0Added-in: 7.76.0。在 libcurl 的选项注册表中该选项被声明为CURLOT_LONG类型见 lib/easyoptions.c即它接受一个长整型数值而非布尔开关。取值语义2、1、0 分别代表什么设为 2推荐严格校验主机名传入2L表示要求 curl校验DoH 服务器证书中的名称字段是否与主机名匹配。此时 DoH 服务器提供的 SSL 证书必须表明服务器名与你打算连接的服务名一致否则连接失败。curl 判定 DoH 服务器为预期服务器intended one的条件是证书中的Common NameCN字段或Subject Alternative NameSAN字段与你在 DoH URL 中告诉 curl 连接的主机名相匹配。注意现代 CA 签发的证书普遍使用 SAN 扩展承载主机名CN 字段常为空或仅为组织名因此 SAN 匹配是实际校验的关键路径。设为 1与 2 等效但不建议当值设为1L时其行为与2L完全相同treated the same as 2L。但文档明确建议为了与其他*_VERIFYHOST选项保持一致应使用 2 而不是 1。设为 0完全跳过主机名校验当值设为0L时无论证书中使用什么名称连接都会成功the connection succeeds regardless of the names used in the certificate。文档特别警告请谨慎使用这一能力Use that ability with caution。从源码看0和2是两个真正有差异的状态而1被归一化为2的行为在 lib/vdns/doh.c 中libcurl 内部创建 DoH 探测用的临时 easy handle 时是这样映射的if(maybe_https) { ERROR_CHECK_SETOPT(CURLOPT_SSL_VERIFYHOST, >#ifndef CURL_DISABLE_DOH set-doh_verifyhost TRUE; set-doh_verifypeer TRUE; #endifCurl_init_userdefined在创建 easy handle 时把doh_verifyhost初始化为TRUE结合上面TRUE ? 2L : 0L的映射等价于默认值 2。同类项doh_verifypeer对应CURLOPT_DOH_SSL_VERIFYPEER默认也是开启的因此在默认配置下DoH 请求的证书既要做签名验证也要做主机名校验。与相关选项的搭配关系选项作用默认值CURLOPT_DOH_SSL_VERIFYHOST校验 DoH 服务器证书的主机名2CURLOPT_DOH_SSL_VERIFYPEER校验 DoH 服务器证书的数字签名证书链真实性1CURLOPT_SSL_VERIFYHOST校验目标站点如https://example.com证书主机名2CURLOPT_SSL_VERIFYPEER校验目标站点证书签名1CURLOPT_PROXY_SSL_VERIFYHOST校验 HTTPS 代理证书主机名2CURLOPT_PROXY_SSL_VERIFYPEER校验 HTTPS 代理证书签名1三者目标站点、DoH 服务器、代理的主机名校验彼此独立分别由各自的VERIFYHOST选项控制。文档中See-also列表也明确指向了上述这些兄弟选项。另外从实现注释看lib/vdns/doh.cDoH 请求不会继承用户传输会话的代理服务器设置因此代理相关的 SSL 校验选项对 DoH 连接不生效也就无需担心CURLOPT_PROXY_SSL_VERIFYHOST影响 DoH。完整示例显式关闭 DoH 主机名校验以下代码来自选项文档的官方示例EXAMPLE小节演示了如何为 DoH 服务器关闭主机名校验int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; curl_easy_setopt(curl, CURLOPT_URL, https://example.com); curl_easy_setopt(curl, CURLOPT_DOH_URL, https://cloudflare-dns.com/dns-query); /* Disable hostname verification of the DoH server */ curl_easy_setopt(curl, CURLOPT_DOH_SSL_VERIFYHOST, 0L); result curl_easy_perform(curl); curl_easy_cleanup(curl); } }要点解读CURLOPT_DOH_URL指定 DoH 解析服务器这里使用 Cloudflare 公共 DoH 端点cloudflare-dns.com/dns-query该选项对应的内部字符串槽位为STRING_DOH见 lib/urldata.h 与 lib/setopt.c。CURLOPT_DOH_SSL_VERIFYHOST设为0L后curl 在解析example.com的主机名时不再校验 DoH 服务器证书的主机名。CURLOPT_SSL_VERIFYHOST未被改动因此目标站点example.com本身的证书主机名校验仍然保持默认的严格模式2两者的影响范围互不干扰。命令行对应curl 工具的 --doh-insecurecurl 命令行工具提供了对应的高级开关--doh-insecure它同时关闭 DoH 连接的证书对端校验peer与主机名校验host。相关实现位于 src/tool_getparam.ccase C_DOH_INSECURE: /* --doh-insecure */ config-doh_insecure_ok toggle;当该标志置位后工具在 src/config2setopts.c 中会向 libcurl 写入对应的 DoH 校验关闭选项最终作用于底层doh_verifyhost/doh_verifypeer两个位标志。也就是说--doh-insecure等价于在代码中同时设置CURLOPT_DOH_SSL_VERIFYHOST 0L与CURLOPT_DOH_SSL_VERIFYPEER 0L。典型用法curl --doh-url https://cloudflare-dns.com/dns-query --doh-insecure https://example.com底层实现原理DoH 探测请求如何被构造理解该选项背后的机制需要了解 libcurl 的 DoH 实现。DoH 解析逻辑集中在 lib/vdns/doh.c入口为Curl_doh()声明见 lib/vdns/doh.h它在Curl_doh_wanted()判定用户设置了 DoH 后被调用见 lib/vdns/hostip.c。关键流程对应 lib/vdns/doh.c编码 DNS 查询doh_req_encode()把要解析的主机名与 DNS 类型A/AAAA编码为 wire format 的 DNS 报文存入req_body。创建内部 easy handle调用Curl_open()内部版curl_easy_init()创建一个临时Curl_easy *doh专门用于向 DoH 服务器发送 HTTP POST 请求。组装 HTTP 请求设置CURLOPT_URL为 DoH URL、CURLOPT_POSTFIELDS为 DNS 报文并附加Content-Type: application/dns-message头lib/vdns/doh.c在 HTTPS 场景下默认协商 HTTP/2CURL_HTTP_VERSION_2TLS。强制 HTTPS非调试构建下强制只允许 HTTPS 协议访问 DoHCURLOPT_PROTOCOLS, CURLPROTO_HTTPS见 lib/vdns/doh.c避免 DNS 查询内容以明文传输。继承校验设置并映射选项即上文展示的doh_verifyhost ? 2L : 0L映射把用户的 DoH 校验偏好翻译为内部 handle 的CURLOPT_SSL_VERIFYHOST同时仅继承 CA 相关设置CURLOPT_CAINFO、CURLOPT_CAINFO_BLOB、CURLOPT_CAPATH等并显式注释说明不继承代理 SSL 设置。回调接收响应doh_probe_write_cb()lib/vdns/doh.c把服务器返回的 DNS 响应报文累积到resp_body随后由Curl_doh_take_result()解析出最终 IP 地址。因此CURLOPT_DOH_SSL_VERIFYHOST的真正作用点是在第 5 步决定内部 DoH handle 的 TLS 主机名校验强度。当它取默认值 2 时若 DoH 服务器证书的 CN/SAN 与 DoH URL 中的主机名不匹配TLS 握手会在校验阶段失败进而导致 DNS 解析失败——这正是防止 DoH 流量被中间人劫持到伪造服务器上的核心保障。安全建议与使用注意保持默认值 2DoH 本身用于对抗 DNS 劫持/污染若同时关闭证书主机名校验攻击者只需伪造一个名称不匹配的证书即可截获你的 DNS 查询内容包括查询域名本身安全性将大打折扣。0 值仅用于调试仅在自建 DoH 服务、自签名证书、测试环境或临时排查问题时使用0L并配合CURLOPT_DOH_SSL_VERIFYPEER 0L使用生产环境不要关闭。1 值不要使用虽然行为与 2 相同但为了代码可读性与一致性一律写2L。不影响目标站点校验本选项只作用于 DoH 服务器https://example.com自身的证书校验仍由CURLOPT_SSL_VERIFYHOST控制两者独立配置、互不干扰。构建前提该选项在CURL_DISABLE_DOH编译宏开启的构建中不可用lib/setopt.c 中整个分支被#ifndef CURL_DISABLE_DOH保护使用前可通过curl_version_info()或官方文档确认构建包含 DoH 支持。返回值curl_easy_setopt(3)返回CURLcode以指示成功或失败CURLE_OK0选项设置成功非零值发生错误具体错误码见 libcurl-errors(3)。注意该返回值只反映选项是否被接受与 DoH 证书校验是否通过无关证书校验失败发生在后续curl_easy_perform()阶段并以CURLE_PEER_FAILED_VERIFICATION等错误码返回。参考文档选项手册docs/libcurl/opts/CURLOPT_DOH_SSL_VERIFYHOST.md设置逻辑lib/setopt.c默认值初始化lib/url.c内部标志定义lib/urldata.hDoH 探测与选项映射lib/vdns/doh.cDoH 入口声明lib/vdns/doh.h命令行--doh-insecuresrc/tool_getparam.c【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考