mrwick/notebook

drag or arrow keys to move · scroll to zoom · esc to exit

My own DNS resolver for my phone

I used NextDNS on my phone for ad blocking. It works well. But I already pay for a VPS, so I moved the job to AdGuard Home on that VPS.

The shape

That last point matters most. A public resolver on port 53 becomes an open resolver. Open resolvers get abused for amplification attacks. DoT and DoH need a TLS handshake first, which makes them poor amplifiers.

Certificates

Caddy already gets a certificate for the hostname. AdGuard reads the same files from Caddy’s data directory for DoT. So there is only one certificate to renew.

I am not sure AdGuard reloads a renewed certificate on its own. I have not tested it. So a weekly timer restarts the container. It costs a few seconds of DNS downtime once a week.

The admin page

The DoH path stays open, because DNS clients cannot log in. The admin UI sits behind my single sign-on page (see One VPS, one login).

dns.example.com {
	handle /dns-query* {
		reverse_proxy adguard:80
	}
	handle {
		import sso
		reverse_proxy adguard:80
	}
}

Block lists

I added a few rules of my own for my phone vendor’s ad domains and some analytics hosts.

Against NextDNS

I tested both from my laptop on the same day. This is one sample, not a benchmark.

AdGuard on my VPS NextDNS
Warm query latency ~32 ms ~47 ms
Blocked, of 31 test hosts 25 26

So: slightly faster for me, and slightly less strict. The VPS is in the same country as me, which likely explains the latency.

Monitoring

If the resolver dies, my phone stops resolving names. That is a bad failure, so a timer on my laptop checks DoT and DoH every two minutes. After two failures in a row it sends me a Telegram message. It sends another one on recovery.

A gotcha for the check: AdGuard’s DoH endpoint wants the wire format (?dns=<base64> with Accept: application/dns-message). The JSON form (?name=) returns 400.