# Does DNS over HTTPS work with a proxy? For some lookups

> Does DNS over HTTPS work with a proxy? Through one, the exit resolves each hostname, so Chrome's DoH setting covers only lookups the browser makes itself.

Source: https://mosaicbrowser.com/blog/dns-over-https-with-a-proxy

## What DNS over HTTPS changes when a browser uses a proxy

Does DNS over HTTPS work with a proxy? Through one, the exit resolves each hostname, so Chrome's DoH setting covers only lookups the browser makes itself.

![The exit resolves the name, whatever the browser is set to](https://mosaicbrowser.com/covers/dns-over-https-with-a-proxy.webp)

DNS over HTTPS works with a proxy, but for most of your browsing it is never asked. When Chrome loads a page through an HTTP proxy or a SOCKS5 proxy, it does not resolve the hostname. It hands the name to the proxy, and the exit node looks it up with its own resolver. The browser's Secure DNS setting only decides the lookups the browser still makes itself, and the resolver a site sees is the exit's.

## Where the hostname goes through a proxy

Chromium's [proxy documentation](https://chromium.googlesource.com/chromium/src/+/HEAD/net/docs/proxy.md) spells out who resolves what. With an HTTP or HTTPS proxy, the name travels inside the request: `GET http://example.com/` for plain HTTP, or `CONNECT example.com:443` for an HTTPS site. With SOCKS5, Chrome always uses proxy-side resolution and sends the name rather than an address. Either way the proxy receives a hostname, and resolving it is the proxy's job.

SOCKS4 is the exception. The protocol has room for an IPv4 address and nothing else, so Chrome resolves the target locally before it can ask. That is the one common setup where your own resolver, and so your Secure DNS setting, handles every page you load. ([SOCKS5 and socks5h in Chrome](https://mosaicbrowser.com/blog/socks5-and-socks5h-in-chrome) covers the naming trap that goes with it: Chrome's `socks5://` behaves like curl's `socks5h://`.)

## The lookups a browser still makes behind a proxy

Even with every page going through the proxy, Chrome resolves a few names on its own side:

- the proxy's own hostname, so it can open the connection to it
- any host on the proxy bypass list, which is reached directly
- the DNS prefetcher's guesses, which have no proxy message to travel in
- other components that resolve names directly, which Chromium's [SOCKS proxy page](https://www.chromium.org/developers/design-documents/network-stack/socks-proxy/) says exist when it notes that `--proxy-server` "applies to URL loads only"

These are the lookups Secure DNS covers. Chrome's "Use secure DNS" option either upgrades your system resolver to its DoH endpoint where the provider supports one, or always uses a provider you name. In both cases the question goes over HTTPS to that provider instead of in plain text to your ISP.

Mosaic is a desktop app

Email yourself the link and open it on your computer.

[How it works: Provider minting](https://mosaicbrowser.com/features/proxy-providers)

## What DNS over HTTPS changes with a proxy, and what it does not

DoH hides the names from anyone watching your connection, your ISP included. That is a real gain for the prefetcher's guesses, which are hostnames from the page you are reading, sent next to your home address.

It does not move them. The DoH provider fetches the answer from its own servers, which are usually the ones nearest you, not the ones nearest your exit. So a leak test that plants a unique hostname still sees a lookup that did not come from the exit. It just sees Cloudflare or Google near your home instead of your ISP. The two halves of one visit still disagree, and the test page can still read it.

The fix that holds is the one in [DNS prefetching, the lookup that skips your proxy](https://mosaicbrowser.com/blog/dns-prefetch-and-proxies): map every local lookup to "not found", except the proxy's own address, so nothing can be resolved behind the proxy's back. Once the browser resolves nothing public itself, a Secure DNS setting has nothing left to protect.

## The resolver a site actually sees

For proxied requests the answer comes from the exit, and nothing in the browser reaches it. We measured this when Whoer marked one of our profiles down by 30 percent for "DNS different", its largest single deduction. Six loads in one launch of one profile scored 100, 100, 100, 100, 35 and 30, and the drops arrived when the residential session rotated to a new exit.

The control used `curl` through the same proxy, with no browser at all:

```
through the proxy      resolver Google LLC, Germany, then the Netherlands
the exit itself        Verizon, United States
this machine, direct   resolver kabelplus, Austria

```

The lookups really did go through the proxy, or Whoer would have seen the Austrian ISP. And the exit's resolver was Google in Europe for an exit in the United States. No DoH setting, content setting or engine patch can change that, because the browser never takes part in that lookup. Why Google on that list is not a leak in itself is in [is a Google DNS server in your leak test a leak?](https://mosaicbrowser.com/blog/is-a-public-resolver-a-leak).

## How a Mosaic profile resolves names

In a Mosaic profile with a proxy, the browser's proxy is Mosaic's relay on `127.0.0.1`, which carries the seller's credentials. The relay passes the hostname upstream unresolved, inside the `CONNECT` line for an HTTP gateway or as a domain name in the SOCKS5 request, so the exit resolves it. "Resolve DNS through the proxy only", on a profile's Privacy tab and on by default, launches the engine with:

```
--host-resolver-rules=MAP * ~NOTFOUND , EXCLUDE 127.0.0.1

```

Every local lookup then fails closed. The one name resolved on your own connection is the seller's gateway hostname, which the relay looks up with the computer's normal resolver to reach it. That tells your resolver which seller you use, and nothing about the sites you open.

The exit's resolver is checked where you can still act on it: before the proxy reaches a profile. Mosaic's proxy check asks which resolver served a one-time hostname through the same relay and records its country and ISP. It flags a mismatch with the exit's country as a fact about that exit, with the note that another pool is the only fix. What else that check reads is in [how to check a proxy before you use it](https://mosaicbrowser.com/guides/how-to-check-a-proxy-before-you-use-it).

## Questions

### Does DNS over HTTPS work with a proxy?

It works, but it covers fewer lookups than people expect. For a page loaded through an HTTP or SOCKS5 proxy, Chrome sends the hostname to the proxy and the exit resolves it, so Secure DNS is never consulted for that request.

### Which lookups does Chrome still make itself when a proxy is set?

The proxy's own hostname, any site on the proxy bypass list, the targets of a SOCKS4 proxy, and side paths such as DNS prefetching. Those go through the browser's resolver, and Secure DNS applies to them.

### Can I choose the DNS server my proxy exit uses?

No. The exit node resolves names with whatever resolver it is configured with, and no browser setting reaches it. If a scanner objects to that resolver, the fix is a different pool or a different seller.

### Does DNS over HTTPS stop a DNS leak behind a proxy?

It hides the leaked lookups from your ISP, which is something. It does not move them to the exit, so a leak test still sees a lookup that came from your side of the proxy, answered by your DoH provider instead of the exit's resolver.

## Related

[Is a Google DNS server in your leak test a leak?](https://mosaicbrowser.com/blog/is-a-public-resolver-a-leak): Google DNS in a leak test is not a leak by itself. It depends on where you browse from: the resolver your own ISP runs is the leak, someone else's is not.

[DNS prefetching, the lookup that skips your proxy](https://mosaicbrowser.com/blog/dns-prefetch-and-proxies): Chrome's DNS prefetcher resolves names through your own resolver even with a proxy set. Mapping every name to NOTFOUND makes the leak fail closed.

[socks5 and socks5h: where Chrome resolves the name](https://mosaicbrowser.com/blog/socks5-and-socks5h-in-chrome): In curl, socks5h sends the hostname to the proxy and socks5 resolves it locally. Chrome's socks5 already sends the name; the leak is elsewhere.

[How to check a proxy before you use it](https://mosaicbrowser.com/guides/how-to-check-a-proxy-before-you-use-it): Check that a proxy answers and tunnels, where its exit really is, whether the address is residential or blocklisted, and that the browser stays behind it.

[Chrome's IP Protection was cancelled, and proxies stay your job](https://mosaicbrowser.com/blog/chrome-ip-protection-cancelled): Chrome's IP Protection would have proxied some Incognito traffic to known trackers. Google retired it with Privacy Sandbox, and sites still see your IP.

[A CONNECT to a raw IP means your machine resolved the name](https://mosaicbrowser.com/blog/a-numeric-connect-means-dns-leaked): To check if DNS goes through your proxy, read what the proxy is asked for. CONNECT example.com:443 means it resolved the name; a raw IP means you did.

[A proxy that answers HTTP and refuses CONNECT](https://mosaicbrowser.com/blog/proxy-http-works-https-fails): A proxy that works for HTTP but not HTTPS is refusing CONNECT, the tunnel every HTTPS page needs. A check that fetches a plain-HTTP page cannot see it.

[Our proxy relay told the gateway it was a script](https://mosaicbrowser.com/blog/the-relay-that-looked-like-a-script): Chrome sends Proxy-Connection: keep-alive, lower case, to every proxy. Our relay sent Keep-Alive, no User-Agent and Connection: close, until we copied Chrome.

## Mosaic, on your own computer

The browser this blog is about: its own Chromium, fingerprints from real machines and a proxy exit per profile. Free holds 3 profiles. Pro is $49 a month for any number.

Mosaic is a desktop app

Email yourself the link and open it on your computer.
