[M94 Dev][Tizen] Fix for compiler and linker errors
[platform/framework/web/chromium-efl.git] / net / docs / proxy.md
1 # Proxy support in Chrome
2
3 This document establishes basic proxy terminology and describes Chrome-specific
4 proxy behaviors.
5
6 [TOC]
7
8 ## Proxy server identifiers
9
10 A proxy server is an intermediary used for network requests. A proxy server can
11 be described by its address, along with the proxy scheme that should be used to
12 communicate with it.
13
14 This can be written as a string using either the "PAC format" or the "URI
15 format".
16
17 The PAC format is how one names a proxy server in [Proxy
18 auto-config](https://en.wikipedia.org/wiki/Proxy_auto-config) scripts. For
19 example:
20 * `PROXY foo:2138`
21 * `SOCKS5 foo:1080`
22 * `DIRECT`
23
24 The "URI format" instead encodes the information as a URL. For example:
25 * `foo:2138`
26 * `http://foo:2138`
27 * `socks5://foo:1080`
28 * `direct://`
29
30 The port number is optional in both formats. When omitted, a per-scheme default
31 is used.
32
33 See the [Proxy server schemes](#Proxy-server-schemes) section for details on
34 what schemes Chrome supports, and how to write them in the PAC and URI formats.
35
36 Most UI surfaces in Chrome (including command lines and policy) expect URI
37 formatted proxy server identifiers. However outside of Chrome, proxy servers
38 are generally identified less precisely by just an address -- the proxy
39 scheme is assumed based on context.
40
41 In Windows' proxy settings there are host and port fields for the
42 "HTTP", "Secure", "FTP", and "SOCKS" proxy. With the exception of "SOCKS",
43 those are all identifiers for insecure HTTP proxy servers (proxy scheme is
44 assumed as HTTP).
45
46 ## Proxy resolution
47
48 Proxying in Chrome is done at the URL level.
49
50 When the browser is asked to fetch a URL, it needs to decide which IP endpoint
51 to send the request to. This can be either a proxy server, or the target host.
52
53 This is called proxy resolution. The input to proxy resolution is a URL, and
54 the output is an ordered list of [proxy server
55 identifiers](#Proxy-server-identifiers).
56
57 What proxies to use can be described using either:
58
59 * [Manual proxy settings](#Manual-proxy-settings) - proxy resolution is defined
60   using a declarative set of rules. These rules are expressed as a mapping from
61   URL scheme to proxy server identifier(s), and a list of proxy bypass rules for
62   when to go DIRECT instead of using the mapped proxy.
63
64 * PAC script - proxy resolution is defined using a JavaScript program, that is
65   invoked whenever fetching a URL to get the list of proxy server identifiers
66   to use.
67
68 * Auto-detect - the WPAD protocol is used to probe the network (using DHCP/DNS)
69   and possibly discover the URL of a PAC script.
70
71 ## Proxy server schemes
72
73 When using an explicit proxy in the browser, multiple layers of the network
74 request are impacted, depending on the scheme that is used. Some implications
75 of the proxy scheme are:
76
77 * Is communication to the proxy done over a secure channel?
78 * Is name resolution (ex: DNS) done client side, or proxy side?
79 * What authentication schemes to the proxy server are supported?
80 * What network traffic can be sent through the proxy?
81
82 Chrome supports these proxy server schemes:
83
84 * [DIRECT](#DIRECT-proxy-scheme)
85 * [HTTP](#HTTP-proxy-scheme)
86 * [HTTPS](#HTTPS-proxy-scheme)
87 * [SOCKSv4](#SOCKSv4-proxy-scheme)
88 * [SOCKSv5](#SOCKSv5-proxy-scheme)
89 * [QUIC](#QUIC-proxy-scheme)
90
91 ### DIRECT proxy scheme
92
93 * Default port: N/A (neither host nor port are applicable)
94 * Example identifier (PAC): `DIRECT`
95 * Example identifier (URI): `direct://`
96
97 This is a pseudo proxy scheme that indicates instead of using a proxy we are
98 sending the request directly to the target server.
99
100 It is imprecise to call this a "proxy server", but it is a convenient abstraction.
101
102 ### HTTP proxy scheme
103
104 * Default port: 80
105 * Example identifier (PAC): `PROXY proxy:8080`, `proxy` (non-standard; don't use)
106 * Example identifiers (URI): `http://proxy:8080`, `proxy:8080` (can omit scheme)
107
108 Generally when one refers to a "proxy server" or "web proxy", they are talking
109 about an HTTP proxy.
110
111 When using an HTTP proxy in Chrome, name resolution is always deferred to the
112 proxy. HTTP proxies can proxy `http://`, `https://`, `ws://` and `wss://` URLs.
113 (Chrome's FTP support is deprecated, and HTTP proxies cannot proxy `ftp://` anymore)
114
115 Communication to HTTP proxy servers is insecure, meaning proxied `http://`
116 requests are sent in the clear. When proxying `https://` requests through an
117 HTTP proxy, the TLS exchange is forwarded through the proxy using the `CONNECT`
118 method, so end-to-end encryption is not broken. However when establishing the
119 tunnel, the hostname of the target URL is sent to the proxy server in the
120 clear.
121
122 HTTP proxies in Chrome support the same HTTP authentiation schemes as for
123 target servers: Basic, Digest, Negotiate, NTLM.
124
125 ### HTTPS proxy scheme
126
127 * Default port: 443
128 * Example identifier (PAC): `HTTPS proxy:8080`
129 * Example identifier (URI): `https://proxy:8080`
130
131 This works like an [HTTP proxy](#HTTP-proxy-scheme), except the
132 communication to the proxy server is protected by TLS, and may negotiate
133 HTTP/2 (but not QUIC).
134
135 Because the connection to the proxy server is secure, https:// requests
136 sent through the proxy are not sent in the clear as with an HTTP proxy.
137 Similarly, since CONNECT requests are sent over a protected channel, the
138 hostnames for proxied https:// URLs is also not revealed.
139
140 In addition to the usual HTTP authentication methods, HTTPS proxies also
141 support client certificates.
142
143 HTTPS proxies using HTTP/2 can offer better performance in Chrome than a
144 regular HTTP proxy due to higher connection limits (HTTP/1.1 proxies in Chrome
145 are limited to 32 simultaneous connections across all domains).
146
147 Chrome, Firefox, and Opera support HTTPS proxies; however, most older HTTP
148 stacks do not.
149
150 Specifying an HTTPS proxy is generally not possible through system proxy
151 settings. Instead, one must use either a PAC script or a Chrome proxy setting
152 (command line, extension, or policy).
153
154 See the dev.chromium.org document on [secure web
155 proxies](http://dev.chromium.org/developers/design-documents/secure-web-proxy)
156 for tips on how to run and test against an HTTPS proxy.
157
158 ### SOCKSv4 proxy scheme
159
160 * Default port: 1080
161 * Example identifiers (PAC): `SOCKS4 proxy:8080`, `SOCKS proxy:8080`
162 * Example identifier (URI): `socks4://proxy:8080`
163
164 SOCKSv4 is a simple transport layer proxy that wraps a TCP socket. Its use
165 is transparent to the rest of the protocol stack; after an initial
166 handshake when connecting the TCP socket (to the proxy), the rest of the
167 loading stack is unchanged.
168
169 No proxy authentication methods are supported for SOCKSv4.
170
171 When using a SOCKSv4 proxy, name resolution for target hosts is always done
172 client side, and moreover must resolve to an IPv4 address (SOCKSv4 encodes
173 target address as 4 octets, so IPv6 targets are not possible).
174
175 There are extensions to SOCKSv4 that allow for proxy side name resolution, and
176 IPv6, namely SOCKSv4a. However Chrome does not allow configuring, or falling
177 back to v4a.
178
179 A better alternative is to just use the newer version of the protocol, SOCKSv5
180 (which is still 20+ years old).
181
182 ### SOCKSv5 proxy scheme
183
184 * Default port: 1080
185 * Example identifier (PAC): `SOCKS5 proxy:8080`
186 * Example identifiers (URI): `socks://proxy:8080`, `socks5://proxy:8080`
187
188 [SOCKSv5](https://tools.ietf.org/html/rfc1928) is a transport layer proxy that
189 wraps a TCP socket, and allows for name resolution to be deferred to the proxy.
190
191 In Chrome when a proxy's scheme is set to SOCKSv5, name resolution is always
192 done proxy side (even though the protocol allows for client side as well). In
193 Firefox client side vs proxy side name resolution can be configured with
194 `network.proxy.socks_remote_dns`; Chrome has no equivalent option and will
195 always use proxy side resolution.
196
197 No authentication methods are supported for SOCKSv5 in Chrome (although some do
198 exist for the protocol).
199
200 A handy way to create a SOCKSv5 proxy is with `ssh -D`, which can be used to
201 tunnel web traffic to a remote host over SSH.
202
203 In Chrome SOCKSv5 is only used to proxy TCP-based URL requests. It cannot be
204 used to relay UDP traffic.
205
206 ### QUIC proxy scheme
207
208 * Default (UDP) port: 443
209 * Example identifier (PAC): `QUIC proxy:8080`
210 * Example identifier (URI): `quic://proxy:8080`
211
212 A QUIC proxy uses QUIC (UDP) as the underlying transport, but otherwise
213 behaves as an HTTP proxy. It has similar properties to an [HTTPS
214 proxy](#HTTPS-proxy-scheme), in that the connection to the proxy server
215 is secure, and connection limits are less restrictive.
216
217 Support for QUIC proxies in Chrome is currently experimental and not
218 ready for production use. In particular, sending https:// and wss://
219 URLs through a QUIC proxy is [disabled by
220 default](https://bugs.chromium.org/p/chromium/issues/detail?id=969859).
221
222 Another caveat is that QUIC does not currently support
223 client certificates since it does not use a TLS
224 handshake. This may change in future versions.
225
226 ## Manual proxy settings
227
228 The simplest way to configure proxy resolution is by providing a static list of
229 rules comprised of:
230
231 1. A mapping of URL schemes to [proxy server identifiers](#Proxy-server-identifiers).
232 2. A list of [proxy bypass rules](#Proxy-bypass-rules)
233
234 We refer to this mode of configuration as "manual proxy settings".
235
236 Manual proxy settings can succinctly describe setups like:
237
238 * Use proxy `http://foo:8080` for all requests
239 * Use proxy `http://foo:8080` for all requests except those to a `google.com`
240   subdomain.
241 * Use proxy `http://foo:8080` for all `https://` requests, and proxy
242   `socsk5://mysocks:90` for everything else
243
244 Although manual proxy settings are a ubiquituous way to configure proxies
245 across platforms, there is no standard representation or feature set.
246
247 Chrome's manual proxy settings most closely resembles that of WinInet. But it
248 also supports idioms from other platforms -- for instance KDE's notion of
249 reversing the bypass list, or Gnome's interpretation of bypass patterns as
250 suffix matches.
251
252 When defining manual proxy settings in Chrome, we specify three (possibly
253 empty) lists of [proxy server identifiers](#Proxy-server-identifiers).
254
255   * proxies for HTTP - A list of proxy server identifiers to use for `http://`
256     requests, if non-empty.
257   * proxies for HTTPS - A list of proxy server identifiers to use for
258     `https://` requests, if non-empty.
259   * other proxies - A list of proxy server identifiers to use for everything
260     else (whatever isn't matched by the other two lists)
261
262 There are a lot of ways to end up with manual proxy settings in Chrome
263 (discussed in other sections).
264
265 The following examples will use the command line method. Launching Chrome with
266 `--proxy-server=XXX` (and optionally `--proxy-bypass-list=YYY`)
267
268 Example: To use proxy `http://foo:8080` for all requests we can launch
269 Chrome with `--proxy-server="http://foo:8080"`. This translates to:
270
271   * proxies for HTTP - *empty*
272   * proxies for HTTPS - *empty*
273   * other proxies - `http://foo:8080`
274
275 With the above configuration, if the proxy server was unreachable all requests
276 would fail with `ERR_PROXY_CONNECTION_FAILED`. To address this we could add a
277 fallback to `DIRECT` by launching using
278 `--proxy-server="http://foo:8080,direct://"` (note the comma separated list).
279 This command line means:
280
281   * proxies for HTTP - *empty*
282   * proxies for HTTPS - *empty*
283   * other proxies - `http://foo:8080`, `direct://`
284
285 If instead we wanted to proxy only `http://` URLs through the
286 HTTPS proxy `https://foo:443`, and have everything else use the SOCKSv5 proxy
287 `socks5://mysocks:1080` we could launch Chrome with
288 `--proxy-server="http=https://foo:443;socks=socks5://mysocks:1080"`. This now
289 expands to:
290
291   * proxies for HTTP - `https://foo:443`
292   * proxies for HTTPS - *empty*
293   * other proxies - `socks5://mysocks:1080`
294
295 The command line above uses WinInet's proxy map format, with some additional
296 features:
297
298 * Instead of naming proxy servers by just a hostname:port, you can use Chrome's
299   URI format for proxy server identifiers. In other words, you can prefix the
300   proxy scheme so it doesn't default to HTTP.
301 * The `socks=` mapping is understood more broadly as "other proxies". The
302   subsequent proxy list can include proxies of any scheme, however if the
303   scheme is omitted it will be understood as SOCKSv4 rather than HTTP.
304
305 ### Mapping WebSockets URLs to a proxy
306
307 [Manual proxy settings](#Manual-proxy-settings) don't have mappings for `ws://`
308 or `wss://` URLs.
309
310 Selecting a proxy for these URL schemes is a bit different from other URL
311 schemes. The algorithm that Chrome uses is:
312
313 * If "other proxies" is non-empty use it
314 * If "proxies for HTTPS" is non-empty use it
315 * Otherwise use "proxies for HTTP"
316
317 This is per the recommendation in section 4.1.3 of [RFC
318 6455](https://tools.ietf.org/html/rfc6455).
319
320 It is possible to route `ws://` and `wss://` separately using a PAC script.
321
322 ### Proxy credentials in manual proxy settings
323
324 Most platforms' [manual proxy settings](#Manual-proxy-settings) allow
325 specifying a cleartext username/password for proxy sign in. Chrome does not
326 implement this, and will not use any credentials embedded in the proxy
327 settings.
328
329 Proxy authentication will instead go through the ordinary flow to find
330 credentials.
331
332 ## Proxy bypass rules
333
334 In addition to specifying three lists of [proxy server
335 identifiers](#proxy-server-identifiers), Chrome's [manual proxy
336 settings](#Manual-proxy-settings) lets you specify a list of "proxy bypass
337 rules".
338
339 This ruleset determines whether a given URL should skip use of a proxy all
340 together, even when a proxy is otherwise defined for it.
341
342 This concept is also known by names like "exception list", "exclusion list" or
343 "no proxy list".
344
345 Proxy bypass rules can be written as an ordered list of strings. Ordering
346 generally doesn't matter, but may when using subtractive rules.
347
348 When manual proxy settings are specified from the command line, the
349 `--proxy-bypass-list="RULES"` switch can be used, where `RULES` is a semicolon
350 or comma separated list of bypass rules.
351
352 Following are the string constructions for the bypass rules that Chrome
353 supports. They can be used when defining a Chrome manual proxy settings from
354 command line flags, extensions, or policy.
355
356 When using system proxy settings, one should use the platform's rule format and
357 not Chrome's.
358
359 ### Bypass rule: Hostname
360
361 ```
362 [ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]
363 ```
364
365 Matches a hostname using a wildcard pattern, and an optional scheme and port
366 restriction.
367
368 Examples:
369
370 * `foobar.com` - Matches URL of any scheme and port, whose normalized host is
371   `foobar.com`
372 * `*foobar.com` - Matches URL of any scheme and port, whose normalized host
373   ends with `foobar.com` (for instance `blahfoobar.com` and `foo.foobar.com`).
374 * `*.org:443` - Matches URLs of any scheme, using port 443 and whose top level
375   domain is `.org`
376 * `https://x.*.y.com:99` - Matches https:// URLs on port 99 whose normalized
377   hostname matches `x.*.y.com`
378
379 ### Bypass rule: Subdomain
380
381 ```
382 [ URL_SCHEME "://" ] "." HOSTNAME_SUFFIX_PATTERN [ ":" PORT ]
383 ```
384
385 Hostname patterns that start with a dot are special cased to mean a subdomain
386 matches. `.foo.com` is effectively another way of writing `*.foo.com`.
387
388 Examples:
389
390 * `.google.com` - Matches `calendar.google.com` and `foo.bar.google.com`, but
391   not `google.com`.
392 * `http://.google.com` - Matches only http:// URLs that are a subdomain of `google.com`.
393
394 ### Bypass rule: IP literal
395
396 ```
397 [ SCHEME "://" ] IP_LITERAL [ ":" PORT ]
398 ```
399
400 Matches URLs that are IP address literals, and optional scheme and port
401 restrictions. This is a special case of hostname matching that takes into
402 account IP literal canonicalization. For example the rules `[0:0:0::1]` and
403 `[::1]` are equivalent (both represent the same IPv6 address).
404
405 Examples:
406
407 * `127.0.0.1`
408 * `http://127.0.0.1`
409 * `[::1]` - Matches any URL to the IPv6 loopback address.
410 * `[0:0::1]` - Same as above
411 * `http://[::1]:99` - Matches any http:// URL to the IPv6 loopback on port 99
412
413 ### Bypass rule: IPv4 address range
414
415 ```
416 IPV4_LITERAL "/" PREFIX_LENGTH_IN_BITS
417 ```
418
419 Matches any URL whose hostname is an IPv4 literal, and falls between the given
420 address range.
421
422 Note this [only applies to URLs that are IP
423 literals](#Meaning-of-IP-address-range-bypass-rules).
424
425 Examples:
426
427 * `192.168.1.1/16`
428
429 ### Bypass rule: IPv6 address range
430
431 ```
432 IPV6_LITERAL "/" PREFIX_LENGTH_IN_BITS
433 ```
434
435 Matches any URL that is an IPv6 literal that falls between the given range.
436 Note that IPv6 literals must *not* be bracketed.
437
438 Note this [only applies to URLs that are IP
439 literals](#Meaning-of-IP-address-range-bypass-rules).
440
441 Examples:
442
443 * `fefe:13::abc/33`
444 * `[fefe::]/40` -- WRONG! IPv6 literals must not be bracketed.
445
446 ### Bypass rule: Simple hostnames
447
448 ```
449 <local>
450 ```
451
452 Matches hostnames without a period in them, and that are not IP literals. This
453 is a naive string search -- meaning that periods appearing *anywhere* count
454 (including trailing dots!).
455
456 This rule corresponds to the "Exclude simple hostnames" checkbox on macOS and
457 the "Don't use proxy server for local (intranet) addresses" on Windows.
458
459 The rule name comes from WinInet, and can easily be confused with the concept
460 of localhost. However the two concepts are completely orthogonal. In practice
461 one wouldn't add rules to bypass localhost, as it is [already done
462 implicitly](#Implicit-bypass-rules).
463
464 ### Bypass rule: Subtract implicit rules
465
466 ```
467 <-loopback>
468 ```
469
470 *Subtracts* the [implicit proxy bypass rules](#Implicit-bypass-rules)
471 (localhost and link local addresses). This is generally only needed for test
472 setups. Beware of the security implications to proxying localhost.
473
474 Whereas regular bypass rules instruct the browser about URLs that should *not*
475 use the proxy, this rule has the opposite effect and tells the browser to
476 instead *use* the proxy.
477
478 Ordering may matter when using a subtractive rule, as rules will be evaluated
479 in a left-to-right order. `<-loopback>;127.0.0.1` has a subtly different effect
480 than `127.0.0.1;<-loopback>`.
481
482 ### Meaning of IP address range bypass rules
483
484 The IP address range bypass rules in manual proxy settings applies only to URL
485 literals. This is not what one would intuitively expect.
486
487 Example:
488
489 Say we have have configured a proxy for all requests, but added a bypass rule
490 for `192.168.0.0.1/16`. If we now navigate to `http://foo` (which resolves
491 to `192.168.1.5` in our setup) will the browser connect directly (bypass proxy)
492 because we have indicated a bypass rule that includes this IP?
493
494 It will go through the proxy.
495
496 The bypass rule in this case is not applicable, since the browser never
497 actually does a name resolution for `foo`. Proxy resolution happens before
498 name resolution, and depending on what proxy scheme is subsequently chosen,
499 client side name resolution may never be performed.
500
501 The usefulness of IP range proxy bypass rules is rather limited, as they only
502 apply to requests whose URL was explicitly an IP literal.
503
504 If proxy decisions need to be made based on the resolved IP address(es) of a
505 URL's hostname, one must use a PAC script.
506
507 ## Implicit bypass rules
508
509 Requests to certain hosts will not be sent through a proxy, and will instead be
510 sent directly.
511
512 We call these the _implicit bypass rules_. The implicit bypass rules match URLs
513 whose host portion is either a localhost name or a link-local IP literal.
514 Essentially it matches:
515
516 ```
517 localhost
518 *.localhost
519 [::1]
520 127.0.0.1/8
521 169.254/16
522 [FE80::]/10
523 ```
524
525 The complete rules are slightly more complicated. For instance on
526 Windows we will also recognize `loopback`.
527
528 This concept of implicit proxy bypass rules is consistent with the
529 platform-level proxy support on Windows and macOS (albeit with some differences
530 due to their implementation quirks - see compatibility notes in
531 `net::ProxyBypassRules::MatchesImplicitRules`)
532
533 Why apply implicit proxy bypass rules in the first place? Certainly there are
534 considerations around ergonomics and user expectation, but the bigger problem
535 is security. Since the web platform treats `localhost` as a secure origin, the
536 ability to proxy it grants extra powers. This is [especially
537 problematic](https://bugs.chromium.org/p/chromium/issues/detail?id=899126) when
538 proxy settings are externally controllable, as when using PAC scripts.
539
540 Historical support in Chrome:
541
542 * Prior to M71 there were no implicit proxy bypass rules, except if using
543   [`--winhttp-proxy-resolver`](#winhttp_proxy_resolver-command-line-switch).
544 * In M71 Chrome applied implicit proxy bypass rules to PAC scripts
545 * In M72 Chrome generalized the implicit proxy bypass rules to manually
546   configured proxies
547
548 ### Overriding the implicit bypass rules
549
550 If you want traffic to `localhost` to be sent through a proxy despite the
551 security concerns, it can be done by adding the special proxy bypass rule
552 `<-loopback>`. This has the effect of _subtracting_ the implicit rules.
553
554 For instance, launch Chrome with the command line flag:
555
556 ```
557 --proxy-bypass-list="<-loopback>"
558 ```
559
560 Note that there currently is no mechanism to disable the implicit proxy bypass
561 rules when using a PAC script. Proxy bypass lists only apply to manual
562 settings, so the technique above cannot be used to let PAC scripts decide the
563 proxy for localhost URLs.
564
565 ## Evaluating proxy lists (proxy fallback)
566
567 Proxy resolution results in a _list_ of [proxy server
568 identifiers](#Proxy-server-identifiers) to use for a
569 given request, not just a single proxy server identifier.
570
571 For instance, consider this PAC script:
572
573 ```
574 function FindProxyForURL(url, host) {
575     if (host == "www.example.com") {
576         return "PROXY proxy1; HTTPS proxy2; SOCKS5 proxy3";
577     }
578     return "DIRECT";
579 }
580
581 ```
582
583 What proxy will Chrome use for connections to `www.example.com`, given that
584 we have a choice of three separate proxy server identifiers to choose from
585 {`http://proxy1:80`, `https://proxy2:443`, `socks5://proxy3:1080`}?
586
587 Initially, Chrome will try the proxies in order. This means first attempting
588 the request through `http://proxy1:80`. If that "fails", the request is
589 next attempted through `https://proxy2:443`. Lastly if that fails, the
590 request is attempted through `socks5://proxy3:1080`.
591
592 This process is referred to as _proxy fallback_. What constitutes a
593 "failure" is described later.
594
595 Proxy fallback is stateful. The actual order of proxy attempts made be Chrome
596 is influenced by the past responsiveness of proxy servers.
597
598 Let's say we request `http://www.example.com/`. Per the PAC script this
599 resolves to a list of three proxy server identifiers:
600
601 {`http://proxy1:80`, `https://proxy2:443`, `socks5://proxy3:1080`}
602
603 Chrome will first attempt to issue the request through these proxies in the
604 left-to-right order.
605
606 Let's say that the attempt through `http://proxy1:80` fails, but then the
607 attempt through `https://proxy2:443` succeeds. Chrome will mark
608 `http://proxy1:80` as _bad_ for the next 5 minutes. Being marked as _bad_
609 means that `http://proxy1:80` is de-prioritized with respect to
610 other proxy server identifiers (including `direct://`) that are not marked as
611 bad.
612
613 That means the next time `http://www.example.com/` is requested, the effective
614 order for proxies to attempt will be:
615
616 {`https://proxy2:443`, `socks5://proxy3:1080`, `http://proxy1:80`}
617
618 Conceptually, _bad_ proxies are moved to the end of the list, rather than being
619 removed from consideration all together.
620
621 What constitutes a "failure" when it comes to triggering proxy fallback depends
622 on the proxy type. Generally speaking, only connection level failures
623 are deemed eligible for proxy fallback. This includes:
624
625 * Failure resolving the proxy server's DNS
626 * Failure connecting a TCP socket to the proxy server
627
628 (There are some caveats for how HTTPS and QUIC proxies count failures for
629 fallback)
630
631 Prior to M67, Chrome would consider failures establishing a
632 CONNECT tunnel as an error eligible for proxy fallback. This policy [resulted
633 in problems](https://bugs.chromium.org/p/chromium/issues/detail?id=680837) for
634 deployments whose HTTP proxies intentionally failed certain https:// requests,
635 since that necessitates inducing a failure during the CONNECT tunnel
636 establishment. The problem would occur when a working proxy fallback option
637 like DIRECT was given, since the failing proxy would then be marked as bad.
638
639 Currently there are no options to configure proxy fallback (including disabling
640 the caching of bad proxies). Future versions of Chrome may [remove caching
641 of bad proxies](https://bugs.chromium.org/p/chromium/issues/detail?id=936130)
642 to make fallback predictable.
643
644 To investigate issues relating to proxy fallback, one can [collect a NetLog
645 dump using
646 chrome://net-export/](https://dev.chromium.org/for-testers/providing-network-details).
647 These logs can then be loaded with the [NetLog
648 viewer](https://netlog-viewer.appspot.com/).
649
650 There are a few things of interest in the logs:
651
652 * The "Proxy" tab will show which proxies (if any) were marked as bad at the
653   time the capture ended.
654 * The "Events" tab notes what the resolved proxy list was, and what the
655   re-ordered proxy list was after taking into account bad proxies.
656 * The "Events" tab notes when a proxy is marked as bad and why (provided the
657   event occurred while capturing was enabled).
658
659 When debugging issues with bad proxies, it is also useful to reset Chrome's
660 cache of bad proxies. This can be done by clicking the "Clear bad proxies"
661 button on
662 [chrome://net-internals/#proxy](chrome://net-internals/#proxy). Note the UI
663 will not give feedback that the bad proxies were cleared, however capturing a
664 new NetLog dump can confirm it was cleared.
665
666 ## Arguments passed to FindProxyForURL() in PAC scripts
667
668 PAC scripts in Chrome are expected to define a JavaScript function
669 `FindProxyForURL`.
670
671 The historical signature for this function is:
672
673 ```
674 function FindProxyForURL(url, host) {
675   ...
676 }
677 ```
678
679 Scripts can expect to be called with string arguments `url` and `host` such
680 that:
681
682 * `url` is a *sanitized* version of the request's URL
683 * `host` is the unbracketed host portion of the origin.
684
685 Sanitization of the URL means that the path, query, fragment, and identity
686 portions of the URL are stripped. Effectively `url` will be
687 limited to a `scheme://host:port/` style URL
688
689 Examples of how `FindProxyForURL()` will be called:
690
691 ```
692 // Actual URL:   https://www.google.com/Foo
693 FindProxyForURL('https://www.google.com/', 'www.google.com')
694
695 // Actual URL:   https://[dead::beef]/foo?bar
696 FindProxyForURL('https://[dead::beef]/', 'dead::beef')
697
698 // Actual URL:   https://www.example.com:8080#search
699 FindProxyForURL('https://www.example.com:8080/', 'example.com')
700
701 // Actual URL:   https://username:password@www.example.com
702 FindProxyForURL('https://www.example.com/', 'example.com')
703 ```
704
705 Stripping the path and query from the `url` is a departure from the original
706 Netscape implementation of PAC. It was introduced in Chrome 52 for [security
707 reasons](https://bugs.chromium.org/p/chromium/issues/detail?id=593759).
708
709 There is currently no option to turn off sanitization of URLs passed to PAC
710 scripts (removed in Chrome 75).
711
712 The sanitization of http:// URLs currently has a different policy, and does not
713 strip query and path portions of the URL. That said, users are advised not to
714 depend on reading the query/path portion of any URL
715 type, since future versions of Chrome may [deprecate that
716 capability](https://bugs.chromium.org/p/chromium/issues/detail?id=882536) in
717 favor of a consistent policy.
718
719 ## Resolving client's IP address within a PAC script using myIpAddress()
720
721 PAC scripts can invoke `myIpAddress()` to obtain the client's IP address. This
722 function returns a single IP literal, or `"127.0.0.1"` on failure.
723
724 This API is [inherently ambiguous when used on multi-homed
725 hosts](#myIpAddress_myIpAddressEx_and-multi_homed-hosts), as such hosts can
726 have multiple IP addresses and yet the browser can pick just one to return.
727
728 Chrome's algorithm for `myIpAddress()` favors returning the IP that would be
729 used if we were to connect to the public internet, by executing the following
730 ordered steps and short-circuiting once the first candidate IP is found:
731
732 1. Select the IP of an interface that can route to public Internet:
733     * Probe for route to `8.8.8.8`.
734     * Probe for route to `2001:4860:4860::8888`.
735 2. Select an IP by doing a DNS resolve of the machine's hostname:
736     * Select the first IPv4 result if there is one.
737     * Select the first IP result if there is one.
738 3. Select the IP of an interface that can route to private IP space:
739     * Probe for route to `10.0.0.0`.
740     * Probe for route to `172.16.0.0`.
741     * Probe for route to `192.168.0.0`.
742     * Probe for route to `FC00::`.
743
744 Note that when searching for candidate IP addresses, link-local and loopback
745 addresses are skipped over. Link-local or loopback address will only be returned as a
746 last resort when no other IP address was found by following these steps.
747
748 This sequence of steps explicitly favors IPv4 over IPv6 results, to match
749 Internet Explorer's IPv6 support.
750
751 *Historical note*: Prior to M72, Chrome's implementation of `myIpAddress()` was
752 effectively just `getaddrinfo(gethostname)`. This is now step 2 of the heuristic.
753
754 ## Resolving client's IP address within a PAC script using myIpAddressEx()
755
756 Chrome supports the [Microsoft PAC
757 extension](https://docs.microsoft.com/en-us/windows/desktop/winhttp/myipaddressex)
758 `myIpAddressEx()`.
759
760 This is like `myIpAddress()`, but instead of returning a single IP address, it
761 can return multiple IP addresses. It returns a string containing a semi-colon
762 separated list of addresses. On failure it returns an empty string to indicate
763 no results (whereas `myIpAddress()` returns `127.0.0.1`).
764
765 There are some differences with Chrome's implementation:
766
767 * In Chrome the function is unconditionally defined, whereas in Internet
768   Explorer one must have used the `FindProxyForURLEx` entrypoint.
769 * Chrome [does not necessarily enumerate all of the host's network
770   interfaces](#myIpAddress_myIpAddressEx_and-multi_homed-hosts)
771 * Chrome does not return link-local or loopback addresses (except if no other
772   addresses were found).
773
774 The algorithm that Chrome uses is nearly identical to that of `myIpAddress()`
775 described earlier, but in certain cases may return multiple IPs.
776
777 1. Select all the IPs of interfaces that can route to public Internet:
778     * Probe for route to `8.8.8.8`.
779     * Probe for route to `2001:4860:4860::8888`.
780     * If any IPs were found, return them, and finish.
781 2. Select an IP by doing a DNS resolve of the machine's hostname:
782     * If any IPs were found, return them, and finish.
783 3. Select the IP of an interface that can route to private IP space:
784     * Probe for route to `10.0.0.0`.
785     * Probe for route to `172.16.0.0`.
786     * Probe for route to `192.168.0.0`.
787     * Probe for route to `FC00::`.
788     * If any IPs were found, return them, and finish.
789
790 Note that short-circuiting happens whenever steps 1-3 find a candidate IP. So
791 for example if at least one IP address was discovered by checking routes to
792 public Internet, only those IPs will be returned, and steps 2-3 will not run.
793
794 ## myIpAddress() / myIpAddressEx() and multi-homed hosts
795
796 `myIpAddress()` is a poor API for hosts that have multiple IP addresses, as it
797 can only return a single IP, which may or may not be the one you wanted. Both
798 `myIpAddress()` and `myIpAddressEx()` favor returning the IP for the interface
799 that would be used to route to the public internet.
800
801 As an API, `myIpAddressEx()` offers more flexibility since it can return
802 multiple IP addresses. However Chrome's implementation restricts which IPs a
803 PAC script can see [due to privacy
804 concerns](https://bugs.chromium.org/p/chromium/issues/detail?id=905366). So
805 using `myIpAddressEx()` is not as powerful as enumerating all the host's IPs,
806 and may not address all use-cases.
807
808 A more reliable strategy for PAC scripts to check which network(s) a user is on
809 is to probe test domains using `dnsResolve()` / `dnsResolveEx()`.
810
811 Moreover, note that Chrome does not support the Firefox-specific
812 `pacUseMultihomedDNS` option, so adding that global to a PAC script has no
813 special side-effect in Chrome. Whereas in Firefox it reconfigures
814 `myIpAddress()` to be dependent on the target URL that `FindProxyForURL()` was
815 called with.
816
817 ## Android quirks
818
819 Proxy resolving via PAC works differently on Android than other desktop Chrome
820 platforms:
821
822 * Android Chrome uses the same Chromium PAC resolver, however does not run it
823   out-of-process as on Desktop Chrome. This architectural difference is
824   due to the higher process cost on Android, and means Android Chrome is more
825   susceptible to malicious PAC scripts. The other consequence is that Android
826   Chrome can have distinct regressions from Desktop Chrome as the service setup
827   is quite different (and most `browser_tests` are not run on Android either).
828
829 * [WebView does not use Chrome's PAC
830   resolver](https://bugs.chromium.org/p/chromium/issues/detail?id=989667).
831   Instead Android WebView uses the Android system's PAC resolver, which is less
832   optimized and uses an old build of V8. When the system is configured to use
833   PAC, Android WebView's net code will see the proxy settings as being a
834   single HTTP proxy on `localhost`. The system localhost proxy will in turn
835   evaluate the PAC script and forward the HTTP request on to the resolved
836   proxy. This translation has a number of effects, including what proxy
837   schemes are supported, the maximum connection limits, how proxy fallback
838   works, and overall performance (the current Android PAC evaluator blocks on
839   DNS).
840
841 * Android system log messages for `PacProcessor` are not related to Chrome or
842   its PAC evaluator. Rather, these are log messages generated by the Android
843   system's PAC implementation. This confusion can arise when users add
844   `alert()` to debug PAC script logic, and then refer to output in `logcat` to
845   try and diagnose a resolving issue in Android Chrome.
846
847 ## Downloading PAC scripts
848
849 When a network context is configured to use a PAC script, proxy resolution will
850 stall while downloading the PAC script.
851
852 Fetches for PAC URLs are initiated by the network stack, and behave differently
853 from ordinary web visible requests:
854
855 * Must complete within 30 seconds.
856 * Must complete with an HTTP response code of exactly 200.
857 * Must have an uncompressed body smaller than 1 MB.
858 * Do not follow ordinary HTTP caching semantics.
859 * Are never fetched through a proxy
860 * Are not visible to the WebRequest extension API, or to service workers.
861 * Do not support HTTP authentication (ambient authentication may work, but
862   cannot prompt UI for credentials).
863 * Do not support client certificates (including `AutoSelectCertificateForUrls`)
864 * Do not support auxiliary certificate network fetches (will only used cached
865   OCSP, AIA, and CRL responses during certificate verification).
866
867 ### Caching of successful PAC fetches
868
869 PAC URLs are always fetched from the network, and never from the HTTP cache.
870 After a PAC URL is successfully fetched, its contents (which are used to create
871 a long-lived Java Script context) will be assumed to be fresh until either:
872
873 * The network changes (IP address changes, DNS configuration changes)
874 * The response becomes older than 12 hours
875 * A user explicitly invalidates PAC through `chrome://net-internals#proxy`
876
877 Once considered stale, the PAC URL will be re-fetched the next time proxy
878 resolution is requested.
879
880 ### Fallback for failed PAC fetches
881
882 When the proxy settings are configured to use a PAC URL, and that PAC URL
883 cannot be fetched, proxy resolution will fallback to the next option, which is
884 often `DIRECT`:
885
886 * If using system proxy settings, and the platform supports fallback to manual
887   proxy settings (e.g. Windows), the specified manual proxy servers will be
888   used after the PAC fetch fails.
889 * If using Chrome's proxy settings, and the PAC script was marked as
890   [mandatory](https://developer.chrome.com/extensions/proxy), fallback to
891   `DIRECT` is not permitted. Subsequent network requests will fail proxy
892   resolution and complete with `ERR_MANDATORY_PROXY_CONFIGURATION_FAILED`.
893 * Otherwise proxy resolution will silently fall back to `DIRECT`.
894
895 ### Recovering from failed PAC fetches
896
897 When fetching an explicitly configured PAC URL fails, the browser will try to
898 re-fetch it:
899
900 * In exactly 8 seconds
901 * 32 seconds after that
902 * 2 minutes after that
903 * Every 4 hours thereafter
904
905 This background polling of the PAC URL is only initiated in response to an
906 incoming proxy resolution request, so it will not trigger work when the browser
907 is otherwise idle.
908
909 Similarly to successful fetches, the PAC URL will be also be re-fetched
910 whenever the network changes, the proxy settings change, or it was manually
911 invalidated via `chrome://net-internals#proxy`.
912
913 ### Text encoding
914
915 Note that UTF-8 is *not* the default interpretation of PAC response bodies.
916
917 The priority for encoding is determined in this order:
918
919 1. The `charset` property of the HTTP response's `Content-Type`
920 2. Any BOM at the start of response body
921 3. Otherwise defaults to ISO-8859-1.
922
923 When setting the `Content-Type`, servers should prefer using a mime type of
924 `application/x-ns-proxy-autoconfig` or `application/x-javascript-config`.
925 However in practice, Chrome does not enforce the mime type.
926
927 ## Capturing a Net Log for debugging proxy resolution issues
928
929 Issues in proxy resolution are best investigated using a Net Log.
930
931 A good starting point is to follow the [general instructions for
932 net-export](https://www.chromium.org/for-testers/providing-network-details),
933 *and while the Net Log is being captured perform these steps*:
934
935 1. Reproduce the failure (ex: load a URL that fails)
936 2. If you can reproduce a success, do so (ex: load a different URL that succeeds).
937 3. In a new tab, navigate to `chrome://net-internals/#proxy` and click both
938    buttons ("Re-apply settings" and "Clear bad proxies").
939 4. Repeat step (1)
940 5. Stop the Net Log and save the file.
941
942 The resulting Net Log should have enough information to diagnose common
943 problems. It can be attached to a bug report, or explored using the [Net Log
944 Viewer](https://netlog-viewer.appspot.com/). See the next section for some tips
945 on analyzing it.
946
947 ## Analyzing Net Logs for proxy issues
948
949 Load saved Net Logs using [Net Log Viewer](https://netlog-viewer.appspot.com/).
950
951 ### Proxy overview tab
952
953 Start by getting a big-picture view of the proxy settings by clicking to the
954 "Proxy" tab on the left. This summarizes the proxy settings at the time the
955 _capture ended_.
956
957 * Does the _original_ proxy settings match expectation?
958   The proxy settings might be coming from:
959   * Managed Chrome policy (chrome://policy)
960   * Command line flags (ex: `--proxy-server`)
961   * (per-profile) Chrome extensions (ex: [chrome.proxy](https://developer.chrome.com/extensions/proxy))
962   * (per-network) System proxy settings
963
964 * Was [proxy autodetect (WPAD)](#Web-Proxy-Auto_Discovery-WPAD) specified? In
965   this case the final URL probed will be reflected by the difference between
966   the "Effective" and "Original" settings.
967
968 * Internally, proxy settings are per-NetworkContext. The proxy
969   overview tab shows settings for a *particular* NetworkContext, namely the
970   one associated with the Profile used to navigate to `chrome://net-export`. For
971   instance if the net-export was initiated from an Incognito window, it may
972   show different proxy settings here than a net-export capture initiated by a
973   non-Incognito window. When the net-export was triggered from command line
974   (`--log-net-log`) no particular NetworkContext is associated with the
975   capture and hence no proxy settings will be shown in this overview.
976
977 * Were any proxies marked as bad?
978
979 ### Import tab
980
981 Skim through the Import tab and look for relevant command line flags and active
982 field trials. A find-in-page for `proxy` is a good starting point. Be on the lookout for
983 [`--winhttp-proxy-resolver`](#winhttp_proxy_resolver-command-line-switch) which
984 has [known problems](https://bugs.chromium.org/p/chromium/issues/detail?id=644030).
985
986 ### Events tab
987
988 To deep dive into proxy resolution, switch to the Events tab.
989
990 You can start by filtering on `type:URL_REQUEST` to see all the top level
991 requests, and then keep click through the dependency links to
992 trace the proxy resolution steps and outcome.
993
994 The most relevant events have either `PROXY_`, `PAC_`, or
995 `WPAD_` in their names. You can also try filtering for each of those.
996
997 Documentation on specific events is available in
998 [net_log_event_type_list.h](https://chromium.googlesource.com/chromium/src/+/HEAD/net/log/net_log_event_type_list.h).
999
1000 Network change events can also be key to understanding proxy issues. After
1001 switching networks (ex VPN), the effective proxy settings, as well as content
1002 of any PAC scripts/auto-detect can change.
1003
1004 ## Web Proxy Auto-Discovery (WPAD)
1005
1006 When configured to use WPAD (aka "autotmaticaly detect proxy settings"), Chrome
1007 will prioritize:
1008
1009 1. DHCP-based WPAD (option 252)
1010 2. DNS-based WPAD
1011
1012 These are tried in order, however DHCP-based WPAD is only supported for Chrome
1013 on Windows and Chrome on Chrome OS.
1014
1015 WPAD is the system default for many home and Enterprise users.
1016
1017 ### Chrome on macOS support for DHCP-based WPAD
1018
1019 Chrome on macOS does not support DHCP-based WPAD when configured to use
1020 "autodetect".
1021
1022 However, macOS might perform DHCP-based WPAD and embed this discovered PAC URL
1023 as part of the system proxy settings. So effectively when Chrome is configured
1024 to "use system proxy settings" it may behave as if it supports DHCP-based WPAD.
1025
1026 ### Dangers of DNS-based WPAD and DNS search suffix list
1027
1028 DNS-based WPAD involves probing for the non-FQDN `wpad`. This means
1029 WPAD's performance and security is directly tied to the user's DNS search
1030 suffix list.
1031
1032 When resolving `wpad`, the host's DNS resolver will complete the hostname using
1033 each of the suffixes in the search list:
1034
1035 1. If the suffix list is long this process can very slow, as it triggers a
1036    cascade of NXDOMAIN.
1037 2. If the suffix list includes domains *outside of the administrative domain*,
1038    WPAD may select an attacker controlled PAC server, and can subsequently
1039    funnel the user's traffic through a proxy server of their choice. The
1040    evolution of TLDs further increases this risk, since what were previously
1041    private suffixes used by an enterprise can become publicly registerable.
1042    See also [WPAD Name Collision
1043    Vulnerability](https://www.us-cert.gov/ncas/alerts/TA16-144A)
1044
1045 ## --winhttp-proxy-resolver command line switch
1046
1047 Passing the `--winhttp-proxy-resolver` command line argument instructs Chrome
1048 to use the system libraries for *one narrow part of proxy resolution*: evaluating
1049 a given PAC script.
1050
1051 Use of this flag is NOT a supported mode, and has [known
1052 problems](https://bugs.chromium.org/p/chromium/issues/detail?id=644030): It
1053 can break Chrome extensions (`chrome.proxy` API), the interpretation of
1054 Proxy policies, hurt performance, and doesn't ensure full fidelity
1055 interpretation of system proxy settings.
1056
1057 Another oddity of this switch is that it actually gets interpreted with a
1058 smilar meaning on other platforms (macOS), despite its Windows-specific naming.
1059
1060 This flag was historically exposed for debugging, and to mitigate unresolved
1061 policy differences in PAC execution. In the future this switch [will be
1062 removed](https://bugs.chromium.org/p/chromium/issues/detail?id=644030).
1063
1064 Although Chrome would like full fidelity with Windows proxy settings, there are
1065 limits to those integrations. Dependencies like NRPT for proxy
1066 resolution necessitate using Windows proxy resolution libraries directly
1067 instead of Chrome's. We hope these less common use cases will be fully
1068 addressed by [this
1069 feature](https://bugs.chromium.org/p/chromium/issues/detail?id=1032820)