You need a Linux machine (or WSL on Windows) and two small tools:
dig (from dnsutils on Debian/Ubuntu, bind-utils on
Fedora) and dnsmasq, a tiny DNS server. Install both with
sudo apt install dnsutils dnsmasq. Check dig is there with
dig -v.
The first four steps run a private practice resolver on a high port
(5354) that answers only from a file you write. It never touches your system’s
real DNS settings and needs no internet. On the machine that produced the output below, the
lab ran inside a throwaway network sandbox because the build environment blocks outbound DNS;
on your own computer the same commands run directly, and the numbers you see will match.
How DNS Works
The Domain Name System (DNS) translates human-readable domain names (like finkatana.com) into IP addresses (like 78.111.67.116) that computers use to communicate. Every time you visit a website, a DNS query happens first.
The lookup chain works like this:
Why DNS is a Privacy Risk
Traditional DNS has a critical privacy problem: queries are sent in plain text.
- Your ISP can see every website you visit via DNS queries
- Network operators (on public WiFi, corporate networks) can log your DNS traffic
- Attackers can intercept and modify DNS responses (DNS spoofing/hijacking)
- Governments can compel ISPs to provide DNS logs of your browsing history
HTTPS encrypts the content of your connection, but the DNS query revealing which domain you are visiting is sent before the HTTPS connection is established.
Encrypted DNS: DoH and DoT
Both prevent your ISP and network operators from seeing your DNS queries.
Recommended DNS Providers
Configuring DNS
On Your Router (Recommended)
Changing DNS on your router protects all devices on the network:
- Log into your router admin panel
- Find DNS settings (often under WAN, Internet, or DHCP settings)
- Replace the ISP DNS with your preferred provider (e.g., 1.1.1.1 and 1.0.0.1)
On Linux
# Temporary (resets on reboot):
sudo resolvectl dns eth0 1.1.1.1 1.0.0.1
# Check current DNS:
resolvectl status
In Firefox (DoH)
Firefox supports DoH natively:
- Go to Settings > Privacy & Security > scroll to "DNS over HTTPS"
- Select "Max Protection" and choose Cloudflare or a custom provider
DNS Leak Testing
After changing your DNS, verify it is working by visiting a DNS leak test site. The results should show your chosen DNS provider, not your ISP.
Now Do It Yourself: See DNS — and DNS Attacks — in Five Steps
DNS turns a name you can remember into an address a computer can reach. That lookup is also the single most trusted step in everything you do online, which makes it a favourite thing to attack. You will run your own tiny resolver, watch it answer a lookup, read every part of that answer, see what happens when a name does not exist, and then — the whole point — watch a poisoned resolver hand back an attacker’s address for a name you trust. Every line of output below was produced by running these exact commands.
Go: open a terminal in a folder you can write to.
Do: write a one-line lookup table, start dnsmasq answering
only from it on port 5354, then ask it for example.test. (If
dnsmasq prints a permission error, put sudo in front of it —
it still touches nothing but its own port.)
printf '93.184.216.34 example.test\n' > myzone
dnsmasq --no-daemon --no-resolv --no-hosts --addn-hosts=myzone --listen-address=127.0.0.1 --port=5354 --bind-interfaces &
dig @127.0.0.1 -p 5354 example.test A +short
You should see: the address your table gave, and nothing else:
93.184.216.34
That is DNS in one line: you asked a resolver for a name, it returned an address. Stop the
server later with kill %1.
If not: failed to bind... Address already in use means port
5354 is taken — change both the --port and the -p to 5355.
If dig prints connection refused, the server did not start; scroll
up for the dnsmasq error, usually a typo in the long flag line.
Go: same terminal, server still running.
Do: drop +short and ask for the answer plus the summary
lines.
dig @127.0.0.1 -p 5354 example.test A +noall +answer +stats
You should see: the record in full, then who answered and how long it took:
example.test. 0 IN A 93.184.216.34
;; Query time: 0 msec
;; SERVER: 127.0.0.1#5354(127.0.0.1) (UDP)
Read it left to right: the name, the TTL (how many seconds this answer
may be cached — 0 here means do not cache), the class IN, the
type A, and the address. The SERVER: line names which
resolver replied — remember that line; step 4 is about trusting it.
If not: a real public resolver returns a large TTL like
3600 instead of 0; that is caching at work and is normal. The
shape of the line is the constant.
Go: same terminal.
Do: look up a name your table never defined, and read the status line.
dig @127.0.0.1 -p 5354 doesnotexist.test A +noall +comments
You should see: no answer, and a status that is not
NOERROR — this practice server replies REFUSED because it has
no record and no upstream to ask:
;; ->>HEADER<<- opcode: QUERY, status: REFUSED, id: 4532
;; flags: qr rd ra; QUERY: 1, ANSWER: 0
On the real internet you would instead see NXDOMAIN — “this name
does not exist”. Either way the lesson is that a resolver can say no, and your
software must handle that, not assume every lookup succeeds.
If not: if you get an address here, you left the wrong name in
myzone — only example.test should resolve.
Go: same terminal. Stop the honest server first: kill %1.
Do: imagine an attacker who controls whichever resolver answers you. They write the same name pointing at their server, start it, and you ask the same question you trusted before.
printf '203.0.113.66 example.test\n' > evilzone
dnsmasq --no-daemon --no-resolv --no-hosts --addn-hosts=evilzone --listen-address=127.0.0.1 --port=5354 --bind-interfaces &
dig @127.0.0.1 -p 5354 example.test A +short
You should see: a completely different address for the name you never changed:
203.0.113.66
Nothing in the question changed — only who answered. That is DNS spoofing
and cache poisoning in miniature: whoever controls the reply controls where
example.test sends your traffic, and your browser shows the name you typed while
connecting to the attacker’s server. This is why the defences matter:
DNSSEC signs answers so a forged one is rejected, and
DoH/DoT encrypt the query so a machine on the path cannot see it or swap the
reply.
If not: if you still get 93.184.216.34, the old server is
still running — run kill %1 (or kill %2) until
dig shows the new address, or the poisoned server never took the port.
Go: the same terminal, now querying the real internet on your own machine.
Stop the practice server first (kill %1).
Do: look up a real domain, then read the SERVER: line to see
which resolver you actually use — and that your query left in plaintext.
dig example.com A +noall +answer +comments
You should see: a real answer with a real TTL, and a
SERVER: line naming your resolver — often your router
(192.168.1.1#53) or your ISP. Port 53 is unencrypted: every domain
you resolve is visible to your network and your ISP.
If not: no answer at all usually means you are offline. To fix the privacy problem this step exposes, turn on encrypted DNS: in Firefox, Settings → Privacy & Security → Enable DNS over HTTPS; in Chrome, Settings → Privacy and security → Use secure DNS. After that, your lookups travel over HTTPS and the machines between you and the resolver can no longer read or rewrite them.
Without scrolling up: in step 4 the question example.test never changed,
yet the address came back different. What changed, and which two defences would have stopped
it? Answer: the resolver answering the query changed — a poisoned or attacker-run
resolver replied instead of the honest one. DNSSEC would have made the forged answer fail its
signature check, and DoH/DoT would have encrypted the query end-to-end so a man in the middle
could neither read it nor substitute a reply.
Now do it without the page: point your myzone file at a
second name of your own — say 203.0.113.9 shop.test on its own line
— restart the practice resolver, and confirm with dig that
shop.test resolves while a name you did not list still comes back
REFUSED. You have just run an authoritative resolver for your own zone.
Summary
In this tutorial, you learned:
- How DNS works and the lookup chain
- Why traditional DNS is a privacy risk
- Encrypted DNS options: DoH and DoT
- Trusted DNS providers to use
- How to configure DNS on your router, Linux, and Firefox
Switching to an encrypted DNS provider is one of the simplest and most effective privacy improvements you can make.