Envoy DNS Resolver 扩展详解:c-ares、Apple、getaddrinfo 与 Hickory DNS 的配置与原理 📅 发布时间:2026/9/13 13:30:52 👁 浏览次数: Envoy DNS Resolver 扩展详解c-ares、Apple、getaddrinfo 与 Hickory DNS 的配置与原理【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoyEnvoy 通过可插拔的 DNS resolver 扩展机制为集群服务发现strict DNS / logical DNS、动态正向代理Dynamic Forward Proxy和 UDP DNS Filter 等组件提供域名解析能力默认使用 c-ares 库同时内置 AppleiOS/macOS、getaddrinfo 与 Hickory DNS 三套可选实现。本文以docs/root/api-v3/config/dns_resolver/dns_resolver.rst索引所覆盖的四个 DNS resolver 扩展为骨架结合api/envoy/extensions/network/dns_resolver/下的 proto 定义、source/extensions/network/dns_resolver/下的实现源码与动态正向代理的完整配置示例系统讲解各解析器的配置字段、默认值、适用场景与运行统计帮助读者掌握在集群、动态正向代理缓存等场景中定制 DNS 解析行为的完整方法。一、Envoy 的 DNS 解析扩展机制Envoy 中多个组件都会触发 DNS 解析不同集群类型strict DNS、logical DNS、动态正向代理系统由集群与 HTTP Filter 组合而成、UDP DNS Filter 等。为了统一管理这些场景的解析行为Envoy 将 DNS 解析抽象为可插拔扩展每个扩展通过工厂注册表Registry注册配置时使用TypedExtensionConfig按名字加载对应的 typed config。相关架构说明见 DNS Resolution 架构文档。从源码source/common/network/dns_resolver/dns_factory_util.cc可以确认默认行为makeDefaultDnsResolverConfig会优先尝试 Apple API受 runtime 特性envoy.restart_features.use_apple_api_for_dns_lookups控制否则回退到 c-ares即c-ares 是 Envoy 的默认 DNS 解析库在 Apple 系操作系统上可通过 runtime 特性启用 Apple 原生 API。1.1 内置的四个 DNS resolver 扩展Envoy 内置了四个 DNS resolver 扩展其 proto 定义分别位于扩展名typed_dns_resolver_config.nameproto 定义文件核心特性envoy.network.dns_resolver.carescares_dns_resolver.proto默认实现基于 c-ares功能最丰富envoy.network.dns_resolver.appleapple_dns_resolver.proto仅 iOS/macOS基于 Apple 系统 APIenvoy.network.dns_resolver.getaddrinfogetaddrinfo_dns_resolver.proto调用系统getaddrinfo()独立线程执行envoy.network.dns_resolver.hickoryhickory_dns_resolver.proto纯 Rust 实现支持 DoT / DoH / DNSSEC其中 Hickory DNS 是基于 Hickory DNS 的纯 Rust 解析器通过动态模块框架dynamic modules framework集成运行在独立的 Tokio runtime 线程上与 Envoy 的事件循环线程隔离因此 DNS 解析不会阻塞 dispatcher 线程。二、DNS 解析器的配置入口DNS resolver 的 typed config 通过typed_dns_resolver_config字段注入主要出现在三个位置Cluster 级别Cluster.typed_dns_resolver_config替换旧的Cluster.dns_resolution_config见 dns_cluster.proto 中的说明DNS 集群扩展DnsCluster.typed_dns_resolver_config当集群通过cluster_type使用envoy.clusters.dns扩展时该字段优先级最高——若它与 Cluster 上的 resolver 配置同时存在Envoy 会采用此处的配置并忽略 Cluster 中的相关字段动态正向代理 DNS 缓存DnsCacheConfig.typed_dns_resolver_configFilter 与 Cluster 必须配置相同的 DNS 缓存参数才能协同工作。2.1 通用解析选项DnsResolverOptions 与 DnsResolutionConfig在api/envoy/config/core/v3/resolver.proto中定义了两个通用消息DnsResolverOptions控制解析器的基础行为包含两个布尔开关use_tcp_for_dns_lookups所有 DNS 查询改用 TCP 而非默认的 UDPno_default_search_domain不使用系统默认搜索域仅按主机名原样或别名查询。DnsResolutionConfig是较早期的配置形态包含resolversDNS 解析器地址列表至少 1 项与dns_resolver_options。若未指定resolvers则使用系统默认解析器如 Unix 下的/etc/resolv.conf。该字段现已逐渐被typed_dns_resolver_config取代。三、c-ares 解析器默认CaresDnsResolverConfigc-ares 是 Envoy 的默认解析器其配置消息CaresDnsResolverConfig定义于 cares_dns_resolver.proto字段编号已用到 12属于[#next-free-field: 13]。各字段说明如下字段类型默认值说明resolvers重复的config.core.v3.Address系统默认DNS 解析器地址列表是否覆盖系统默认值取决于use_resolvers_as_fallbackuse_resolvers_as_fallbackboolfalse为true时仅在 c-ares 无法从系统如/etc/resolv.conf获取 nameserver 时才使用resolvers否则resolvers将覆盖系统默认解析器filter_unroutable_familiesboolfalse查询可用网络接口若某个 IP 族IPv4/IPv6没有任何可用接口则从结果中过滤该族的地址dns_resolver_optionsconfig.core.v3.DnsResolverOptions—复用通用选项TCP 查询、禁用搜索域udp_max_queriesUInt32Value—限制基于 UDP 的 DNS 查询数量上限当前仅 c-ares 适用query_timeout_secondsUInt64ValueEnvoy 默认5秒每个 nameserver 首次应答的超时秒数注意 c-ares 库默认 2 秒Envoy 未设置时默认 5 秒这是为了保持旧行为、避免用户反馈的解析耗时上升。校验规则要求 1query_triesUInt32ValueEnvoy 默认4次放弃前的最大查询尝试次数每次尝试可能使用不同 nameserverc-ares 库默认 3 次Envoy 未设置时默认 4 次。校验规则要求 1rotate_nameserversboolfalse开启后按轮询方式选择 nameserver分散查询负载关闭默认时按配置顺序依次尝试。该设置会覆盖系统对 nameserver 轮转的配置edns0_max_payload_sizeUInt32Valuec-ares 内部默认通常 1232EDNS0 UDP 负载上限字节。设置后 c-ares 会在查询中携带 EDNS0并用该值作为最大 UDP 响应大小。推荐值1232安全默认避免分片、4096最大值。校验规则要求512 x 4096max_udp_channel_durationDuration不设置则不刷新若设置解析器会周期性重新初始化 c-ares channel避免陈旧 socket 状态、改善 UDP 端口负载分布reinit_channel_on_timeoutboolfalse当 DNS 查询以ARES_ETIMEOUT失败时重新初始化 c-ares channel帮助从 UDP socket 不可用等罕见故障中恢复。若超时源于间歇性网络问题开启可能增加 channel 重建频率可考虑改用max_udp_channel_duration做周期刷新qcache_max_ttlUInt32ValueEnvoy 默认0关闭查询缓存c-ares 查询缓存的最大 TTL秒。设为非 0 时启用缓存并遵守 DNS 响应中的 TTL不超过该上限。c-ares 库默认缓存 1 小时而 Envoy 默认关闭3.1 实现细节与统计指标c-ares 解析器的实现位于 source/extensions/network/dns_resolver/cares/dns_impl.h 与dns_impl.cc。其统计宏ALL_CARES_DNS_RESOLVER_STATS定义了 6 项指标挂在dns.cares统计树stats tree下名称类型说明resolve_totalCounterDNS 查询总数pending_resolutionsGauge进行中的 DNS 查询数not_foundCounter返回NXDOMAIN或NODATA的查询数get_addr_failureCounter查询期间的一般性失败次数timeoutsCounter超时查询数reinitsCounterc-ares channel 重新初始化次数实现上DnsResolverImpl的所有调用与回调都发生在创建它的 dispatcher 线程上c-ares 仅支持 channel 级取消因此PendingResolution::cancel只是标记cancelled_并跳过回调网络事件仍会继续见dns_impl.h中PendingResolution的实现注释。四、Apple 解析器AppleDnsResolverConfigApple 解析器仅适用于 iOS/macOS 平台配置消息定义于 apple_dns_resolver.proto仅有一个字段include_unroutable_familiesbool默认false开启后绕过系统仅返回可路由的 IPv4/IPv6 地址的启发式逻辑返回所有可能的地址。该设置在 DNS 查询族被限定为 v4-only 或 v6-only 时会被忽略。绝大多数场景应保持false但在自行过滤地址例如实现 Happy Eyeballs时可能有用。其统计指标挂在dns.apple统计树下见 DNS Resolution 架构文档名称类型说明connection_failureCounter连接 DNS 服务器失败的次数get_addr_failureCounter调用 GetAddrInfo API 时的一般性失败次数network_failureCounter网络连通性导致的失败次数processing_failureCounter处理 DNS 服务器返回数据时的失败次数socket_failureCounter获取连接 DNS 服务器的 socket 文件描述符失败的次数timeoutCounter超时查询数在启用 Apple 解析器时需要借助 runtime 特性envoy.restart_features.use_apple_api_for_dns_lookups参见 dns_factory_util.cc 中tryUseAppleApiForDnsLookups的逻辑。五、getaddrinfo 解析器GetAddrInfoDnsResolverConfiggetaddrinfo 解析器直接调用系统getaddrinfo()函数解析主机名配置消息定义于 getaddrinfo_dns_resolver.protonum_retriesUInt32Value放弃前的重试次数未指定时解析器会无限重试直到成功或 DNS 查询超时。num_resolver_threadsUInt32Value用于解析待处理 DNS 查询的线程数未指定时使用 1 个线程。该消息的文档中有两处重要提示解析结果使用硬编码 60 秒 TTL因为getaddrinfo()API 不提供真实 TTL目前固定为 60 秒未来如需可再增加配置实现层面从 getaddrinfo.h 的注释可见该解析器在专用解析线程上调用getaddrinfo()目前只适合相对低频率的解析场景未来可扩展为线程池。此外getaddrinfo 解析器当前不产生任何解析器专属统计指标。六、Hickory DNS 解析器HickoryDnsResolverConfigHickory DNS 是 Envoy 中较新的纯 Rust 解析器支持标准 DNSUDP/TCP、DNS-over-TLSDoT、DNS-over-HTTPSDoH以及 DNSSEC 校验。配置消息定义于 hickory_dns_resolver.proto字段类型默认值说明resolvers重复的config.core.v3.Address系统配置标准 UDP/TCP 解析的 DNS 地址列表未指定且use_system_config未显式设为false时使用系统配置Unix 下/etc/resolv.confdns_over_tlsDnsOverTlsConfig—DoT 配置指定后查询将经 TLS 发送至配置的服务器dns_over_httpsDnsOverHttpsConfig—DoH 配置指定后查询将经 HTTPS 发送至配置的端点enable_dnssecboolfalse启用 DNSSEC 校验验证签名并拒绝校验失败的响应cache_sizeUInt32Value1024DNS 响应缓存条目上限LRU 淘汰策略支持负缓存缓存NXDOMAIN/NODATA响应num_resolver_threadsUInt32Value2异步解析所用 Tokio runtime 线程数最大16每个解析器实例运行自己的 Tokio runtimeuse_system_configBoolValue未配置resolvers/dns_over_tls/dns_over_https时为true是否读取系统 DNS 配置nameserver 与搜索域同时指定resolvers时以resolvers优先query_timeoutDuration5秒单次查询尝试的超时时间校验要求 1msquery_triesUInt32Value3放弃前的最大查询尝试次数每次可能使用不同 nameserver校验要求 1其中两个子消息DnsOverTlsConfigserversDoT 服务器地址列表端口通常为 853tls_server_nameTLS 校验使用的 SNI 主机名指定servers时必填至少 1 个字符DnsOverHttpsConfigserver_urlsDoH 端点 URL 列表如https://dns.google/dns-query每个 URL 至少 1 个字符。Hickory 解析器的统计指标挂在dns.hickory统计树下包括resolve_total完成的查询数、pending_resolutions进行中查询数、not_found、get_addr_failure、timeouts。其实现位于 source/extensions/network/dns_resolver/hickory/hickory_dns_impl.cc。七、完整配置示例动态正向代理中的 typed_dns_resolver_config官方文档 dynamic_forward_proxy_filter.rst 给出了将 c-ares 解析器配置到动态正向代理 DNS 缓存的完整示例源文件为 dns-cache-circuit-breaker.yaml。其中 Filter 与 Cluster 通过同名的dns_cache_configdynamic_forward_proxy_cache_config关联并在typed_dns_resolver_config中指定envoy.network.dns_resolver.cares及其参数admin: address: socket_address: protocol: TCP address: 127.0.0.1 port_value: 9901 static_resources: listeners: - name: listener_0 address: socket_address: protocol: TCP address: 0.0.0.0 port_value: 10000 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: type: type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: local_service domains: [*] routes: - match: prefix: /force-host-rewrite route: cluster: dynamic_forward_proxy_cluster typed_per_filter_config: envoy.filters.http.dynamic_forward_proxy: type: type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.PerRouteConfig host_rewrite_literal: www.example.org - match: prefix: / route: cluster: dynamic_forward_proxy_cluster http_filters: - name: envoy.filters.http.dynamic_forward_proxy typed_config: type: type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.FilterConfig dns_cache_config: name: dynamic_forward_proxy_cache_config dns_lookup_family: V4_ONLY dns_cache_circuit_breaker: max_pending_requests: 1024 typed_dns_resolver_config: name: envoy.network.dns_resolver.cares typed_config: type: type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig resolvers: - socket_address: address: 8.8.8.8 port_value: 53 dns_resolver_options: use_tcp_for_dns_lookups: true no_default_search_domain: true - name: envoy.filters.http.router typed_config: type: type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: dynamic_forward_proxy_cluster lb_policy: CLUSTER_PROVIDED cluster_type: name: envoy.clusters.dynamic_forward_proxy typed_config: type: type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig dns_cache_config: name: dynamic_forward_proxy_cache_config dns_lookup_family: V4_ONLY dns_cache_circuit_breaker: max_pending_requests: 1024 typed_dns_resolver_config: name: envoy.network.dns_resolver.cares typed_config: type: type.googleapis.com/envoy.extensions.network.dns_resolver.cares.v3.CaresDnsResolverConfig resolvers: - socket_address: address: 8.8.8.8 port_value: 53 dns_resolver_options: use_tcp_for_dns_lookups: true no_default_search_domain: true transport_socket: name: envoy.transport_sockets.tls typed_config: type: type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext common_tls_context: validation_context: trusted_ca: {filename: /etc/ssl/certs/ca-certificates.crt}该示例同时展示了两个层面的要点Filter 与 Cluster 必须成对配置并指向同一套 DNS 缓存参数示例中还包含 DNS 缓存级熔断dns_cache_circuit_breaker.max_pending_requests: 1024与标准集群熔断circuit_breakers前者限制待处理 DNS 请求数、防止压垮解析器后者限制到上游主机的连接/请求/重试等地址族策略dns_lookup_family: V4_ONLY限定仅解析 IPv4该字段的完整取值定义于 dns_cluster.proto 引用的common.dns.v3.DnsLookupFamilyAUTO为默认值。如需在 iOS/macOS 上改用 Apple 解析器只需将typed_dns_resolver_config替换为以下形态参见 dns-cache-circuit-breaker-apple.yamltyped_dns_resolver_config: name: envoy.network.dns_resolver.apple typed_config: type: type.googleapis.com/envoy.extensions.network.dns_resolver.apple.v3.AppleDnsResolverConfig八、DNS 集群DnsCluster中的解析器配置与刷新语义除了动态正向代理DNS 发现型集群envoy.clusters.dns扩展同样通过typed_dns_resolver_config接入自定义解析器。结合 dns_cluster.proto 的字段说明其关键刷新参数与解析器配置协同工作dns_refresh_rate集群 DNS 刷新间隔未设置时默认5000ms最小 1msdns_failure_refresh_rate查询失败时的刷新间隔含base_interval与可选的max_interval后者默认是 base 的 10 倍respect_dns_ttl为true时按 DNS 资源记录 TTL 设置刷新速率配合dns_min_refresh_rate可设置 TTL 下限至少 1 秒TTL 更短的记录按该下限刷新dns_jitter为刷新加入随机延迟上限为配置值避免大量请求同时触发 DNS 的惊群效应dns_lookup_family解析地址族默认AUTOall_addresses_in_single_endpoint所有返回地址视为单个端点logical DNS 语义否则每个地址视为独立端点strict DNS 语义。该消息的注释还明确说明了配置优先级当DnsCluster.typed_dns_resolver_config、Cluster.typed_dns_resolver_config、Cluster.dns_resolution_config同时存在时若集群通过cluster_type使用DnsCluster扩展Envoy 采用DnsCluster.typed_dns_resolver_config并忽略 Cluster 中的解析器相关字段否则回退到Cluster.typed_dns_resolver_config。九、实践建议与注意事项默认行为无需配置绝大多数场景直接使用默认的 c-ares 解析器即可系统 nameserver 会自动从/etc/resolv.conf读取自定义 nameserver 时注意 fallback 语义CaresDnsResolverConfig的resolvers默认会覆盖系统配置如需保留系统配置作为兜底应显式设置use_resolvers_as_fallback: true超时与重试的默认值差异c-ares 解析器的query_timeout_secondsEnvoy 默认 5s vs 库默认 2s与query_triesEnvoy 默认 4 vs 库默认 3都做了调整以保持 Envoy 旧版行为避免解析耗时上升配置时需知悉这一默认值差异EDNS0 负载建议edns0_max_payload_size推荐使用 1232 字节的安全默认值以避免 UDP 分片最大允许 4096缓存策略差异c-ares 的qcache_max_ttl在 Envoy 中默认关闭0而库默认 1 小时Hickory 默认开启 1024 条目 LRU 缓存并支持负缓存且自带 DoT/DoH/DNSSEC 能力适合对解析安全性与协议有更高要求的场景getaddrinfo 的适用限制固定 60 秒 TTL、专用线程执行、无解析器专属统计仅适合低频率解析场景统计观测c-ares、Apple、Hickory 分别挂载于dns.cares、dns.apple、dns.hickory统计树可用于监控解析量、超时率、失败率与 channel 重建次数reinits。如需深入了解 DNS 解析器在各类集群与过滤器中的完整接入方式可继续阅读 dns_resolution.rst、dynamic_forward_proxy_filter.rst 以及四个解析器扩展的源码实现cares、apple、getaddrinfo、hickory。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考