1# Chrome Host Resolution 2 3Implementation and support of host resolution for the Chrome network stack. 4Includes client implementations of host resolution protocols (DNS and mDNS), 5host resolution caching, support for dealing with system host resolution 6(including reading HOSTS files and tracking system network settings related to 7host resolution), and various related utilities. 8 9*** promo 10Note: "DNS" in this directory (including the directory name) is often used as 11shorthand for all host resolution, not just that using the Domain Name System. 12This document attempts to use "DNS" only to refer to the actual Domain Name 13System, except when referring to strings or paths that contain other usage of 14"DNS". 15*** 16 17[TOC] 18 19## Usage 20 21### From outside the network service 22 23Most interaction with host resolution should be through the [network service](/services/network/README.md) 24[`network::HostResolver`](/services/network/public/mojom/host_resolver.mojom), 25retrieved from [`network::NetworkContext`](/services/network/public/mojom/network_context.mojom) 26using `network::NetworkContext::CreateHostResolver()`. 27 28Host resolution is requested using `network::HostResolver::ResolveHost()`. There 29is also a shortcut using `network::NetworkContext::ResolveHost()` when a 30separate passable object is not needed. 31 32Some general utilities are also available in [`/net/dns/public/`](/net/dns/public/) 33that are intended for use by any code, inside or outside the network service. 34Otherwise, code outside the network service should never interact directly with 35the code in [`/net/dns/`](/net/dns/). 36 37### From inside the network service 38 39Inside the network service or inside the Chrome networking stack, host 40resolution goes through [`net::HostResolver`](/net/dns/host_resolver.h), 41retrieved from [`net::URLRequestContext`](/net/url_request/url_request_context.h). 42 43### Stand-alone tools 44 45Tests and stand-alone tools not part of the browser may interact with host 46resolution directly by creating their own HostResolvers using 47`net::HostResolver::CreateStandaloneResolver()`. 48 49## Test support 50 51### MockHostResolver 52 53[`net::MockHostResolver`](/net/dns/mock_host_resolver.h) 54 55Tests with the ability to inject and replace the used `net::HostResolver` should 56replace it with a `net::MockHostResolver`, allowing rule-based results. 57`net::MockCachingHostResolver` is the same except it includes basic support for 58the caching functionality normally done by prod `net::HostResolver`s. 59 60Some tests may also find `net::HangingHostResolver` useful. It will begin host 61resolution requests, but never complete them until cancellation. 62 63### TestHostResolver 64 65[`content::TestHostResolver`](/content/public/test/test_host_resolver.h) 66 67Used by most browser tests (via [`content::BrowserTestBase`](/content/public/test/browser_test_base.h)), 68`content::TestHostResolver` installs itself on creation globally into all host 69resolvers in the process. By default, only allows resolution of the local host 70and returns `net::ERR_NAME_NOT_RESOLVED` for other hostnames. Allows setting rules 71for other results using a [net::RuleBasedHostResolverProc](/net/dns/mock_host_resolver.h). 72 73*** note 74**Warning:** `content::TestHostResolver` only replaces host address resolution 75to the system and then artificially uses such system resolution for many 76requests that would normally be handled differently (e.g. using the built-in DNS 77client). This means a significant amount of normal prod host resolution logic 78will be bypassed in tests using `content::TestHostResolver`. 79*** 80 81### Request remapping 82 83Most prod logic for creating HostResolvers will check if any global remappings 84have been requested. In the browser, this is requested using the 85["host-resolver-rules"](/services/network/public/cpp/network_switches.h) 86commandline flag. 87 88See [`net::HostMappingRules`](/net/base/host_mapping_rules.h) for details on the 89format of the rules string. Allows remapping any request hostname to another 90hostname, an IP address, or a NOTFOUND error. 91 92## Implementation 93 94### HostResolver 95 96[`net::HostResolver`](/net/dns/host_resolver.h) 97 98The main interface for requesting host resolution within the network stack or 99network service. In prod, generally owned, and retrieved as-needed from 100[`net::URLRequestContext`](/net/url_request/url_request_context.h)s. Created 101using `net::HostResolver::CreateResolver()` or 102`net::HostResolver::CreateStandaloneResolver()`. 103 104Various implementations are used in prod. 105 106#### ContextHostResolver 107 108[`net::ContextHostResolver`](/net/dns/context_host_resolver.h) 109 110The main prod implementation of `net::HostResolver`. Expected to be owned 1:1 by 111a single `net::URLRequestContext`, the `net::ContextHostResolver` owns or keeps 112references to per-URLRequestContext properties used for host resolution, 113including an owned [`net::HostCache`](/net/dns/host_cache.h). 114 115On resolution, calls into an underlying `net::HostResolverManager` with the per- 116context properties. 117 118On destruction, silently cancels all host resolution requests made through the 119`net::ContextHostResolver` instance. This prevents the underlying 120`net::HostResolverManager` from continuing to reference the per-context 121properties that may be destroyed on destruction of the `net::URLRequestContext` 122or `net::ContextHostResolver`. 123 124#### MappedHostResolver 125 126[`net::MappedHostResolver`](/net/dns/mapped_host_resolver.h) 127 128A wrapping implementation around another `net::HostResolver`. Maintains request 129remapping rules to remap request hostnames to other hostnames or IP addresses. 130 131Used to implement the ["host-resolver-rules"](/services/network/public/cpp/network_switches.h) 132commandline flag. 133 134#### StaleHostResolver 135 136[`cronet::StaleHostResolver`](/components/cronet/stale_host_resolver.h) 137 138A wrapping implementation around another `net::HostResolver`. Returns stale 139(expired or invalidated by network changes) data from the `net::HostCache` when 140non-stale results take longer than a configurable timeout. Reduces host 141resolution latency at the expense of accuracy. 142 143Only used and created by [Cronet](/components/cronet/README.md). 144 145### HostResolverManager 146 147[`net::HostResolverManager`](/net/dns/host_resolver_manager.h) 148 149Scheduler and controller of host resolution requests. Contains the logic for 150immediate host resolution from fast local sources (e.g. querying 151`net::HostCache`s, IP address literals, etc). Throttles, schedules, and merges 152asynchronous jobs for resolution from slower network sources. 153 154On destruction, silently cancels all in-progress host resolution requests. 155 156In prod, a single shared `net::HostResolverManager` is generally used for the 157entire browser. The shared manager is owned and configured by the 158[`network::NetworkService`](/services/network/network_service.h). 159 160#### Request 161 162`net::HostResolverManager::RequestImpl` 163 164Implementation of [`net::HostResolver::ResolveHostRequest`](/net/dns/host_resolver.h) 165and overall representation of a single request for resolution from a 166`net::HostResolverManager`. The `RequestImpl` object itself primarily acts only 167as a container of parameters and results for the request, leaving the actual 168logic to the `net::HostResolverManager` itself. 169 170Data collected at this layer: 171 172* "Net.DNS.Request.TotalTime" (recommended for experiments) 173* "Net.DNS.Request.TotalTimeAsync" 174 175#### Job 176 177`net::HostResolverManager::Job` 178 179Representation of an asynchronous job for resolution from slower network 180sources. Contains the logic to determine and query the appropriate source for 181host resolution results with retry and fallback support to other sources. On 182completion adds results to relevant `net::HostCache`s and invokes request 183callbacks. 184 185Multiple requests can be merged into a single Job if compatible. This includes 186merging newly-started Jobs with already-running Jobs. 187 188`net::HostResolverManager` schedules and throttles running 189`net::HostResolverManager::Job`s using a [`net::PrioritizedDispatcher`](/net/base/prioritized_dispatcher.h). 190The throttling is important to avoid overworking network sources, especially 191poorly designed home routers that may crash on only a small number of concurrent 192DNS resolves. 193 194Data collected at this layer: 195 196* "Net.DNS.ResolveSuccessTime" 197* "Net.DNS.ResolveFailureTime" 198* "Net.DNS.ResolveCategory" 199* "Net.DNS.ResolveError.Fast" 200* "Net.DNS.ResolveError.Slow" 201 202### Host resolution sources 203 204Various sources are used to query host resolution. The sources to be used by a 205`net::HostResolverManager::Job` are determined in advance of running the Job by 206`net::HostResolverManager::CreateTaskSequence()`, which outputs a list of 207`net::HostResolverManager::TaskType` specifying the order of sources to attempt. 208By default, this will use internal logic to decide the source to use and will 209often allow fallback to additional sources. 210 211The sources chosen by default are also affected by the Secure DNS mode, by 212default determined from 213[`net::DnsConfig::secure_dns_mode`](/net/dns/dns_config.h) but overridable for 214individual requests using 215`net::HostResolver::ResolveHostParameters::secure_dns_mode_override`. 216 217Specific sources for a request can be 218specified using `net::HostResolver::ResolveHostParameters::source` and 219[`net::HostResolverSource`](/net/dns/host_resolver_source.h). 220 221The Job will then use \*Task objects that implement the behavior specific to the 222particular resolution sources. 223 224#### SYSTEM 225 226`net::HostResolverSource::SYSTEM` 227`net::HostResolverManager::TaskType::SYSTEM` 228 229Implemented by: `net::HostResolverSystemTask` 230 231Usually called the "system resolver" or sometimes the "proc resolver" (because 232it was historically always implemented using net::HostResolverProc). Results 233are queried from the system or OS using the `getaddrinfo()` OS API call. This 234source is only capable of address (A and AAAA) resolves but will also query for 235canonname info if the request includes the `HOST_RESOLVER_CANONNAME` flag. The 236system will query from its own internal cache, HOSTS files, DNS, and sometimes 237mDNS, depending on the capabilities of the system. 238 239When host resolution requests do not specify a source, the system resolver will 240always be used for **address resolves** when **any** of the following are true: 241 242* Requests with the `HOST_RESOLVER_CANONNAME` flag 243* For hostnames ending in ".local" 244* When the Secure DNS mode is `net::SecureDnsMode::OFF` and 245 `net::HostResolverSource::DNS` is not enabled via 246 `net::HostResolverManager::SetInsecureDnsClientEnabled(true)` 247* When a system DNS configuration could not be determined 248 249Secure DNS requests cannot be made using the system resolver. 250 251`net::HostResolverSystemTask`'s behavior can be overridden by an asynchronous 252global override (e.g. in case resolution needs to be brokered out of the current 253process for sandboxing reasons). Otherwise, it posts a blocking task to a 254[`base::ThreadPool`](/base/task/thread_pool.h) to make blocking resolution 255requests in-process. 256On a timeout, additional attempts are made, but previous attempts are not 257cancelled as there is no cancellation mechanism for `getaddrinfo()`. The first 258attempt to complete is used and any other attempt completions are ignored. 259 260In prod, the blocking task runner always calls `SystemHostResolverCall()`, which 261makes the actual call to `getaddrinfo()` using the 262[`net::AddressInfo`](/net/dns/address_info.h) helper. In tests, the blocking 263task runner may use a test implementation of 264[`net::HostResolverProc`](/net/dns/host_resolver_proc.h), which itself can be 265chained. 266 267Data collected specifically for this source: 268 269* "Net.DNS.SystemTask.SuccessTime" 270* "Net.DNS.SystemTask.FailureTime" 271 272#### DNS 273 274`net::HostResolverSource::DNS` 275`net::HostResolverManager::TaskType::DNS` 276`net::HostResolverManager::TaskType::SECURE_DNS` 277 278Implemented by: `net::HostResolverManager::DnsTask` 279 280Usually called the "built-in resolver" or the "async resolver". Results are 281queried from DNS using [`net::DnsClient`](/net/dns/dns_client.h), a Chrome 282network stack implementation of a DNS "stub resolver" or "DNS client". 283 284When host resolution requests do not specify a source, the built-in resolver 285will be used when **all** of the following are true: 286 287* DnsClient is enabled for insecure requests enabled via 288 `net::HostResolverManager::SetInsecureDnsClientEnabled(true)` or 289 the Secure DNS mode is not `net::SecureDnsMode::OFF`. 290* The system DNS configuration could be determined successfully 291* The request hostname does not end in ".local" 292* The request is not an address query with the `HOST_RESOLVER_CANONNAME` flag 293 294The `net::HostResolverManager::DnsTask` will create and run a 295[`net::DnsTransaction`](/net/dns/dns_transaction.h) for each DNS name/type pair 296to be queried. The task will then process successful results from the returned 297[`net::DnsResponse`](/net/dns/dns_response.h). 298 299When a request requires both A and AAAA results, they are handled via two 300separate `net::DnsTransaction`s and the `net::HostResolverManager::DnsTask` will 301request a second slots from the `net::PrioritizedDispatcher` used by 302`net::HostResolverManager`. The A transaction is started immediately on starting 303the `net::HostResolverManager::DnsTask`, and the AAAA transaction is started 304once a second dispatcher slot can be obtained. 305 306Each `net::DnsTransaction` internally makes a series of `net::DnsAttempt`s, each 307representing an individual DNS request. A single `net::DnsTransaction` can run 308many `net::DnsAttempt`s due to retry logic, fallback between multiple configured 309DNS servers, and name permutation due to configured search suffixes. 310 311Data collected specifically for this source (more internally to 312`net::DnsTransaction` implementation not listed here): 313 314* "Net.DNS.DnsTask.SuccessTime" 315* "Net.DNS.InsecureDnsTask.FailureTime" 316* "Net.DNS.JobQueueTime.PerTransaction" 317* "Net.DNS.JobQueueTime.Failure" 318* "Net.DNS.JobQueueTime.Success" 319 320#### MULTICAST_DNS 321 322`net::HostResolverSource::MULTICAST_DNS` 323`net::HostResolverManager::TaskType::MDNS` 324 325Implemented by [`net::HostResolverMdnsTask`](/net/dns/host_resolver_mdns_task.h) 326 327Results are queried from mDNS using [`net::MDnsClient`](/net/dns/mdns_client.h). 328 329When host resolution requests do not specify a source, mDNS is only used for 330non-address requests when the request hostname ends in ".local". 331 332mDNS requests start with [`net::HostResolverMdnsTask`](/net/dns/host_resolver_mdns_task.h), 333which will create and run a [`net::MDnsTransaction`](/net/dns/mdns_client.h) for 334each query type needed. 335 336Unlike `net::HostResolverManager::DnsTask`, each `net::HostResolverMdnsTask` 337will only ever use a single dispatcher slot, even when both A and AAAA types are 338queried concurrently. 339 340`net::MDnsClient` maintains its own cache, separate from the main 341[`net::HostCache`](/net/dns/host_cache.h) owned by the 342[`net::ContextHostResolver`](/net/dns/context_host_resolver.h). As such, mDNS 343results are never cached in the `net::HostCache`. 344 345### IPv6 and connectivity 346 347Some poorly written DNS servers, especially on home routers, are unaware of the 348existence of IPv6 and will result in bad performance or even crash when sent 349AAAA DNS queries. 350 351To avoid such issues, `net::HostResolverManager` heuristically detects IPv4-only 352networks by attempting a UDP connection to `2001:4860:4860::8888` (the IPv6 353address for Google Public DNS). If the connection fails, Chrome will convert 354host resolution requests for `net::DnsQueryType::UNSPECIFIED` to 355`net::DnsQueryType::A`. This generally results in disallowing AAAA requests. 356 357Exceptions when AAAA requests are always allowed despite a failed connectivity 358check: 359 360* The host resolution request explicitly requests `net::DnsQueryType::AAAA` 361* IP address literal resolution including when a hostname request has been 362 rewritten to an IP address literal using `net::MappedHostResolver` 363* Results read from HOSTS files where there is no non-loopback IPv4 result. Note 364 that this exception only applies when Chrome does the read from HOSTS. When 365 Chrome's built-in DNS client is not used, HOSTS is only read by the system 366 where Chrome would only request A results to avoid the system making AAAA DNS 367 queries. 368 369The heuristic for detecting IPv4-only networks is not perfect. E.g., it fails 370and disallows AAAA requests in private (no global internet access including to 371Google Public DNS) IPv6-only networks, which could then break most Chrome usage 372on the network because, being an IPv6-only network, AAAA results are necessary. 373 374Workarounds to allow Chrome to attempt to load IPv6 endpoints when the 375connectivity check fails: 376 377* Starting Chrome with 378 `--host-resolver-rules="MAP the.hostname.com [dead::beef]"` where 379 `the.hostname.com` is the hostname to allow resolving and `dead::beef` is the 380 IPv6 address to resolve it to. `net::MappedHostResolver` acts at a level 381 before IPv6 connectivity checks, and if a hostname is remapped to an IP 382 literal, connectivity checks do not apply. 383* Add entries for the hostnames to resolve to the HOSTS file with just IPv6 384 results. Only works with the built-in DNS client is used. 385* Add a network route to `2001:4860:4860::8888`. Doesn't have to actually be 386 functional (could just drop requests to it). As long as Chrome can connect a 387 UDP socket to the address, it will pass the heuristic checking 388 IPv6-connectivity. 389