I run a local DNS filter on my home network, the same idea as Pi-hole: the router hands out one resolver, queries hit that box, and ads or trackers I do not want never get an answer. That works for phones and laptops that honor DHCP. It does not work for every cheap camera, plug or feeder.
Some devices never send those queries to your resolver at all. They talk to a public DNS service directly. From the filter's point of view, nothing happened. The device still reaches vendor.example.com just fine.
I added detection for this in iotaudit 0.1.19, the local CLI and MCP server I use to audit devices I own. This post is about the three patterns it looks for, and what the report is and is not allowed to claim.
Three ways a device skips your resolver
1. Classic DNS to a public resolver. The device sends plain UDP (or TCP) DNS to a well-known address such as 8.8.8.8, 1.1.1.1 or 9.9.9.9, including the usual IPv6 counterparts. Port 53 is how DNS has always worked. Your Pi-hole never sees the question because it was never asked.
2. DNS-over-TLS (DoT). The device opens TLS on port 853, which IANA assigned to encrypted DNS. The query is not visible as plaintext, but the port is distinctive. A connection to 1.1.1.1:853 is almost certainly DNS, not a web session.
3. DNS-over-HTTPS (DoH). The device uses HTTPS, usually on port 443, to a known DoH hostname such as dns.google or cloudflare-dns.com (visible as TLS SNI, HTTP Host, or a DNS name that already resolved). That traffic looks like ordinary HTTPS unless you check the name. If you only see HTTPS to a known resolver IP, with no hostname, that is a weaker signal: it often is DoH, but the same address can be used for other services, so I treat it as high confidence, not as a certainty.
None of this is proof that a vendor is doing something malicious. It is an observed routing choice: the device is not using the resolver your router offered.
How to spot it on a network you own
You need to see traffic from the device itself. A browser on your laptop will not show you what the camera queries. On a network you own, capture that device (for example with ARP on the LAN, a hotspot the device joins, or a pcap you already have), then look at destinations:
- port 53 to a public resolver IP
- port 853 to anyone, especially a known resolver
- port 443 whose SNI or domain is a known DoH name
iotaudit does that pass for you. After a capture or iotaudit analyze capture.pcap, a device that did this gets a finding, and the one-line verdict names it, for example "uses public DNS directly" or "uses DNS-over-HTTPS".
A synthetic example of the kind of line you should see (no real addresses from my LAN):
Device 192.168.0.50 DNS-over-TLS (bypasses router) Device sent DNS-over-TLS (port 853) to 1.1.1.1, bypassing your router's DNS. Queries may leave your network even if you run Pi-hole. Install and run it locally. There is no account and no telemetry:
pip install -U iotaudit iotaudit analyze capture.pcap # or, on a network you own, after the consent prompt: sudo iotaudit auto The HTML report and the one-line verdict are the useful parts. The grade moves a little when public DNS is present (it is a medium finding, same weight as the older hardcoded-DNS check). I would not treat the letter as a moral score. It is a way to sort devices that deserve a second look.
What this does not tell you
- It does not decrypt DoT or DoH. You learn that encrypted DNS was used, not which names were asked.
- HTTPS to a resolver IP without a DoH hostname is a hint, not a fact. The finding is worded that way on purpose.
- A device that uses your router DNS will not show these findings. That is success, not a gap in the tool.
- You should only capture networks and devices you own, and you should accept the consent prompt. This is not a scanner for other people's Wi-Fi.
If you want a shareable report later, iotaudit report AUDIT.json --redact replaces local IPs, MACs and hostnames first.
What I do when I see it
Blocking port 53 to the internet on the router is the easy first step, and it stops the classic case. It does not stop DoT or DoH. For those, I also block outbound 853, and I think about whether 443 to known resolver IPs or DoH names should be denied on the IoT network. Some devices fall back to the router DNS and keep working. Some break until you allow the vendor's cloud.
A guest or IoT VLAN still helps: even if a device bypasses the filter, it is not sitting on the same segment as your laptop.
I wrote earlier about what a pet feeder did on the network and about listing UPnP port forwards read-only. This is the next gap I kept hitting: the filter was fine, the device simply never asked it.
Code, docs and the 0.1.19 notes are at github.com/emirmrkaljevic/iotaudit.