# Encrypted DNS

> Use an agent's DoH URL or DoT host: apply the profile with one command, present the credential as a header or in the path, and check it took effect.

*Source: https://www.whisper.security/docs/network/resolver/encrypted-dns*

---
This puts one machine's name lookups behind your account, so every lookup gets the graph
verdict and your policy. It is the resolver-only tier, and it changes nothing about how the
machine's traffic is routed.

You need an API key on the machine. If you do not have one, get it from
`https://console.whisper.security`.

## 1. Find the endpoint that was minted for you

When you mint an identity, the response carries `doh_url` alongside `resolver_ip`. The URL
has this shape, with a credential inside the path:

```text
https://doh.whisper.online/<your-token>/dns-query
```

Treat that whole URL as a password. Anyone holding it can resolve names as you, so it goes
in a secret store and never into a shared document or a screenshot.

## 2. Preview what will change

`--print` renders the exact profile for this operating system, file by file and command by
command, and changes nothing. It needs no key, so you can read it before you commit:

```bash
whisper resolver --print
```

## 3. Apply it

```bash
whisper resolver --doh
```

On Linux this installs a local forwarder that speaks the encrypted channel upstream. On
Windows it registers the endpoint and one tagged name-resolution rule, and needs an
elevated PowerShell. On macOS it stages a DNS profile for the single approval the operating
system requires in System Settings.

To use your account's own resolver address on plain port 53 instead, where the source
address is the credential, ask for that explicitly:

```bash
whisper resolver --resolver
```

## 4. Confirm the answers come from Whisper

Look up a name your policy blocks. It comes back NXDOMAIN or as your sinkhole address
rather than the real answer. Then read the decision back:

```bash
whisper logs --from -1h --kind dns
```

The row for that name carries a `decision` and a `reason`. If nothing appears, the machine
is still resolving somewhere else; re-run `whisper resolver --print` and compare it against
what is actually configured.

## 5. Put it back

```bash
whisper resolver --off
```

That reverts every file and setting the command applied, and revokes the resolve-only
credential it minted. It is idempotent, so running it on a machine that was never
configured is safe.

## Configuring a client yourself

For a client that speaks DNS over HTTPS natively, the endpoint is RFC 8484 and the wire
format is the only format: GET with `?dns=<base64url>` or POST with
`application/dns-message`. There is no JSON form.

Three ways to present the credential, and exactly one of them per request:

```text
X-API-Key: whisper_live_...
Authorization: Bearer whisper_live_...
https://doh.whisper.online/<your-token>/dns-query
```

Sending two different credentials on two channels in the same request is rejected, so pick
one and stay with it.

For a client that speaks DNS over TLS, use the host returned as `dot_host` on port 853. The
selector label in that hostname carries the credential, which is why the host is
per-credential and not a shared name. Android's Private DNS field takes exactly this value;
that flow is on [Set Up a Device](/docs/network/devices/setup).

## What decides the answers

The endpoint applies your account policy, not a per-host one. Change what is blocked,
allowed or forwarded on [Resolver Policy](/docs/network/resolver/policy), and read
[How Resolution Works](/docs/network/resolver/how-it-works) for what happens to a name
before your lists are consulted.
