ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

libcurl 的 CURLOPT_DNS_LOCAL_IP6:让 DNS 解析绑定到指定本地 IPv6 地址

libcurl 的 CURLOPT_DNS_LOCAL_IP6:让 DNS 解析绑定到指定本地 IPv6 地址 libcurl 的 CURLOPT_DNS_LOCAL_IP6让 DNS 解析绑定到指定本地 IPv6 地址【免费下载链接】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导读CURLOPT_DNS_LOCAL_IP6是 libcurl 提供的一个字符串类型CURLOPT_STRING传输选项用于将异步 DNS 解析器发出的查询绑定到指定的本地 IPv6 地址上。在需要强制 DNS 查询从特定网络接口的 IPv6 地址发出例如多网卡主机、需要走特定链路出口解析域名、或配合防火墙策略的场景时该选项是 libcurl 应用层最直接的入口。读完本文你将掌握该选项的用法、默认行为、底层实现原理c-ares 后端、参数校验规则以及与CURLOPT_DNS_LOCAL_IP4、CURLOPT_DNS_INTERFACE等兄弟选项的配合方式。NAME名称与原型CURLOPT_DNS_LOCAL_IP6—— IPv6 address to bind DNS resolves to即“DNS 解析要绑定到的 IPv6 地址”。其接口原型定义如下对应官方文档 docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md#include curl/curl.h CURLcode curl_easy_setopt(CURL *handle, CURLOPT_DNS_LOCAL_IP6, char *address);该选项自 libcurl7.33.0版本加入docs/libcurl/symbols-in-versions中有记录适用于所有协议DICT、FILE、FTP、HTTP、HTTPS、IMAP、SMTP、MQTT、WS 等全部传输协议因为它作用于 DNS 解析阶段与上层协议无关属于字符串选项在 lib/easyoptions.c 中登记为CURLOT_STRING类型检查宏同样将其列入字符串选项集合见 include/curl/typecheck-gcc.h。DESCRIPTION行为描述设置该选项后libcurl 的 DNS 解析器发出的查询会绑定到指定的本地 IPv6 地址参数类型为char *内容应为一个单独的 IPv6 地址字符串例如fe80::a9ff:fe46:b619将该选项设置为NULL可以恢复默认行为即不绑定任何特定 IP 地址由系统路由表决定出站地址应用层无需在设置选项后继续保留该字符串——libcurl 内部会通过Curl_setstropt做字符串拷贝并接管其生命周期见 lib/setopt.c多次调用该选项时最后一次设置的字符串会覆盖之前的值若想重新禁用再次传入NULL即可。默认值DEFAULT该选项的默认值为NULL即默认不绑定特定本地 IPv6 地址与“未设置”状态等价。与同族 DNS 选项的对比该选项并非孤立存在而是 libcurl 针对 c-ares 后端提供的“DNS 出口控制”选项家族的一员家族成员均登记在 lib/urldata.h 的字符串枚举中并在 lib/setopt.c 中集中处理选项作用引入版本CURLOPT_DNS_SERVERS指定要使用的 DNS 服务器列表7.24.0CURLOPT_DNS_INTERFACE指定 DNS 解析绑定的网络接口名7.21.6CURLOPT_DNS_LOCAL_IP4指定 DNS 解析绑定的本地 IPv4 地址7.33.0CURLOPT_DNS_LOCAL_IP6指定 DNS 解析绑定的本地 IPv6 地址7.33.0四个选项覆盖了“服务器选择、接口绑定、IPv4 出口、IPv6 出口”四个维度可以单独使用也可以组合使用。例如公司内部要求仅通过eth0的 IPv6 地址访问内网 DNS即可同时设置CURLOPT_DNS_INTERFACE与CURLOPT_DNS_LOCAL_IP6。EXAMPLE完整可运行示例#include stdio.h #include curl/curl.h int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result; /* 目标 URL */ curl_easy_setopt(curl, CURLOPT_URL, https://example.com/foo.bin); /* 将 DNS 查询绑定到本地链路本地 IPv6 地址 */ curl_easy_setopt(curl, CURLOPT_DNS_LOCAL_IP6, fe80::a9ff:fe46:b619); result curl_easy_perform(curl); if(result ! CURLE_OK) fprintf(stderr, curl_easy_perform() failed: %s\n, curl_easy_strerror(result)); curl_easy_cleanup(curl); } return 0; }注意示例中的地址fe80::a9ff:fe46:b619为链路本地地址link-local实际部署时应替换为本机接口上真实存在的、可用于出站查询的 IPv6 地址否则解析可能失败。源码级实现原理仅 c-ares 后端支持该选项要求 libcurl 使用支持该操作的解析器后端构建目前唯一支持者是 c-ares 后端。这一点在官方 NOTES 中有明确说明也在源码中得到印证在 lib/setopt.c 中CURLOPT_DNS_LOCAL_IP6的赋值分支被#ifdef USE_RESOLV_ARES包裹——如果 libcurl 不是用 c-ares 构建的该 case 根本不会编译进去选项将落入默认分支返回CURLE_UNKNOWN_OPTION真正生效的逻辑位于 lib/vdns/asyn-ares.c 的async_ares_set_dns_local_ip6()函数绑定动作最终通过调用 c-ares 库的ares_set_local_ip6()完成lib/vdns/asyn-ares.c。参数校验与错误处理从async_ares_set_dns_local_ip6()的实现lib/vdns/asyn-ares.c可以看到完整的校验逻辑static CURLcode async_ares_set_dns_local_ip6(struct Curl_easy *data, struct Curl_resolv_async *async) { #ifdef USE_IPV6 struct async_ares_ctx *ares async ? async-ares : NULL; unsigned char a6[INET6_ADDRSTRLEN]; const char *local_ip6 CURL_EASY_STR(data, STRING_DNS_LOCAL_IP6); if(!local_ip6 || (local_ip6[0] 0)) { /* disabled: do not bind to a specific address */ memset(a6, 0, sizeof(a6)); } else { if(curlx_inet_pton(AF_INET6, local_ip6, a6) ! 1) { DEBUGF(infof(data, bad DNS IPv6 address)); return CURLE_BAD_FUNCTION_ARGUMENT; } } /* if channel is not there, this is a parameter check */ if(ares ares-channel) ares_set_local_ip6(ares-channel, a6); return CURLE_OK; #else /* no IPv6 support */ (void)data; (void)async; return CURLE_NOT_BUILT_IN; #endif }由此可以归纳出三种返回值情形地址字符串为空或为NULL视为“禁用绑定”将 16 字节的 IPv6 地址清零相当于不绑定地址字符串无法通过curlx_inet_pton(AF_INET6, ...)解析为合法 IPv6 地址返回CURLE_BAD_FUNCTION_ARGUMENT并在调试日志DEBUGF中记录bad DNS IPv6 addresslibcurl 构建时未启用 IPv6无USE_IPV6直接返回CURLE_NOT_BUILT_IN。生效时机通道初始化时批量应用该选项并不是每次 DNS 查询临时生效而是在c-ares 通道channel初始化完成后一次性应用。在 lib/vdns/asyn-ares.c 中可以看到调用序列status ares_init_options(ares-channel, options, optmask); ... result async_ares_set_dns_servers(data, async); ... result async_ares_set_dns_interface(data, async); ... result async_ares_set_dns_local_ip4(data, async); ... result async_ares_set_dns_local_ip6(data, async);也就是说服务器列表、接口名、IPv4 本地地址、IPv6 本地地址这四个维度会在每次创建新的 c-ares 通道时按顺序统一应用。源码注释还特别指出通道尚不存在时调用这些 setter 相当于纯参数校验“if channel is not there, this is a parameter check”只有通道存在时才真正调用ares_set_*系列函数写入通道。与其他相关选项的交互CURLOPT_DNS_LOCAL_IP4IPv4 版本行为与 IPv6 版本完全对称可同时设置以覆盖双栈场景参见 docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP4.mdCURLOPT_DNS_INTERFACE以接口名如eth0而非 IP 地址方式绑定 DNS 出口二者可互补参见 docs/libcurl/opts/CURLOPT_DNS_INTERFACE.mdCURLOPT_DNS_SERVERS指定解析目标服务器与本地绑定地址共同决定了“从哪里查询、查询谁”参见 docs/libcurl/opts/CURLOPT_DNS_SERVERS.mdCURLOPT_INTERFACE控制的是数据连接本身的本地绑定而本选项控制的是DNS 查询包的本地绑定两者作用层次不同不要混淆参见 lib/setopt.c 的注释。RETURN VALUE返回值curl_easy_setopt()统一返回CURLcodeCURLE_OK (0)一切正常非零值表示出错具体错误码参见 libcurl-errors(3)非法 IPv6 地址字符串时返回CURLE_BAD_FUNCTION_ARGUMENT构建时未启用 IPv6 时返回CURLE_NOT_BUILT_IN未以 c-ares 后端构建时该选项不可用会走default分支返回CURLE_UNKNOWN_OPTION。使用前提与限制必须使用 c-ares 后端构建 libcurl配置时启用--enable-ares或 CMake 的USE_ARES这是使用本选项的硬性前提必须启用 IPv6 支持USE_IPV6否则返回CURLE_NOT_BUILT_IN指定的 IPv6 地址应为本机实际可用的地址可通过ip -6 addr查看绑定到不存在的地址将导致 DNS 查询失败该选项只影响 DNS 解析查询的源地址不影响后续数据连接的源地址——数据连接的绑定需通过CURLOPT_INTERFACE等选项控制。参考文档索引本选项官方文档docs/libcurl/opts/CURLOPT_DNS_LOCAL_IP6.md同族选项文档CURLOPT_DNS_LOCAL_IP4.md、CURLOPT_DNS_INTERFACE.md、CURLOPT_DNS_SERVERS.md实现源码lib/vdns/asyn-ares.c、lib/setopt.c选项元数据lib/easyoptions.c、lib/urldata.h、docs/libcurl/symbols-in-versions【免费下载链接】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),仅供参考
返回列表