Self-hosted service
farrokhi/dnsdiag avatar
farrokhi/dnsdiag

dnsdiag answers three questions about a resolver: slow, redirected, or wrong

DNS Measurement, Troubleshooting and Security Auditing Toolset

1,068 stars111 forksPythonBSD-2-Clause

At a glance

What is it?
dnsdiag is a BSD licensed Python toolset of three commands, dnsping, dnstraceroute and dnseval, that measure DNS latency, trace the path of a query to a resolver and compare resolvers against each other. It is installable with uv, pip, prebuilt binaries or a Docker image, and its value is the comparison between two queries to the same server.
Who is it for?
dnsdiag suits a network engineer or a curious user who needs to establish whether a resolver is slow, whether a query is being redirected, and which of several resolvers actually performs best for their network, without setting up a monitoring stack. It does not suit a team that needs continuous measurement over weeks, since it is a command line tool that reports on a run, and it is not the place to enforce DNSSEC policy.
Can I use it commercially?
Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Three commands for three different suspicions

dnsdiag describes itself as a DNS measurement, troubleshooting and security auditing toolset, and the questions it is built around are the ones a person asks when something feels wrong with their name resolution. Is your provider intercepting your DNS traffic, is a response behaving unusually, or have you been redirected to the wrong address.

The toolset answers those with three separate programs rather than one mode. dnsping measures the response time of a DNS server for arbitrary queries, offering comparable functionality to the regular ping utility, so you can monitor server responsiveness. dnstraceroute traces the route of a DNS request to its destination, so you can verify that it is not being redirected or intercepted, and by comparing DNS queries sent to the same server you can observe differences in the paths taken, which alerts you to possible issues. dnseval assesses multiple DNS resolvers to help you choose the best one for your network, comparing them on performance, meaning latency, and reliability, meaning packet loss.

The split is the design. Each tool answers one question, and each produces output you can read on its own, which matters when the answer you need is a single sentence rather than a report.

The recommended audience is anyone who runs a resolver, and the project is unusually opinionated about one thing in the README: using your own DNS resolver is recommended to avoid reliance on third-party resolvers, with dnseval there to help when you need to pick a public one anyway.

dnsping chooses one transport and reports more than a time

The interesting part of dnsping is that it is not a ping with a different name. It can speak DNS over several transports, and the transport is chosen explicitly with mutually exclusive options: --tcp, --tls, --doh, --quic or --http3, with UDP as the default. Only one protocol can be specified per command.

That is the feature that makes it a measurement tool rather than a resolver test. Comparing a resolver over UDP against the same resolver over DoH or QUIC tells you something about the path, not just the server, and the per transport comparison of response times is listed among the interesting use cases.

The inspection flags go further into the response. --flags displays response flags including EDNS flags for each response, and --dnssec requests DNSSEC validation where it is available. Extended DNS Error messages under RFC 8914 are displayed automatically when present, --nsid shows the Name Server Identifier under RFC 5001 when available, --ecs adds EDNS Client Subnet information for geographic routing optimisation, and --cookie displays DNS cookies under RFC 7873 when present in the response.

That set of flags is the security auditing half of the tool. A resolver that answers quickly but without the DNSSEC bit, or that returns an error with an EDE code explaining why, is telling you something a latency number cannot.

The output reports the minimum, maximum and average response times, along with jitter, which is the standard deviation, and the packet loss percentage. The full flag set in practice looks like this:

shell
./dnsping.py -c 5 --dnssec --flags --tls -t AAAA -s 8.8.8.8 brokendnssec.net

Five queries, over TLS, for AAAA records, against a server that is expected to fail DNSSEC validation, and every response comes back with SERVFAIL and an extended error explaining that the failure is for the SOA of the domain. The example in the README is deliberately a failing case, which is a good choice for a tool, because a successful query tells you less.

dnstraceroute looks for divergence between two queries

The interception question is answered by comparison rather than by inspection. dnstraceroute traces the route of a DNS request to its destination, and the README is explicit about the method: by comparing DNS queries sent to the same server, it lets you observe any differences in the paths taken, alerting you to possible issues.

That framing is what separates this from a normal traceroute. A path trace on its own shows a route, and routes are not necessarily suspicious. What matters is that two queries to the same destination should not arrive by materially different paths, so a divergence between runs is the signal, not the route itself.

The tool is therefore about drift as much as about redirection. A resolver that is normally reached over one path and occasionally over another is either load balancing, or a middlebox, and telling those apart is the user's judgement call.

The other tool in the same family, dnseval, works at a different level again. It assesses multiple DNS resolvers so you can choose one, comparing them on latency and packet loss to give a comprehensive view for informed decision making. It reads its candidate list from a file, and the repository ships one:

bash
uvx --from dnsdiag dnseval -f public-servers.txt github.com

The file public-servers.txt sits at the top level of the repository, alongside public-v4.txt and rootservers.txt, so the candidate set is data you can edit rather than a hardcoded list. The repository also contains rootservers.txt, which suggests the same comparison can be pointed at the root servers as well as at public resolvers.

uv is the recommended install, and Docker covers the rest

The README says there are several ways to use the toolset, and recommends running it directly from the source code for optimal flexibility and control. Running from source or installing with pip requires Python 3.11 or newer.

The uv section is marked as recommended, and it is the shortest path, since uv can run the tools directly without installation:

bash
# Run dnsping directly without installation
uvx --from dnsdiag dnsping google.com

# Run with specific options
uvx --from dnsdiag dnsping -c 5 --tls -s 8.8.8.8 example.com

For a persistent installation there is a tool install and an upgrade command:

bash
uv tool install dnsdiag
uv tool upgrade dnsdiag

The other routes are pip, with pip3 install dnsdiag, a source checkout where you clone the repository, cd into it and install from requirements.txt, and prebuilt binaries for Windows, macOS and Linux that are released from time to time.

The platform list has a gap that the README explains rather than hides. Prebuilt binaries exist for Linux on x86_64 and ARM64, macOS on Intel and Apple Silicon, and Windows on x86_64. Windows ARM64 is not currently supported, because the build dependencies require native compilation toolchains that are not readily available, and the advice for Windows on ARM is to use the Windows Subsystem for Linux or install from source.

The container route avoids the local install entirely:

bash
docker run --network host -it --rm farrokhi/dnsdiag dnsping.py

The --network host flag is there because DNS measurement against your real network path is the point, and a container with its own network namespace would measure a different path.

The output format is the tool's fingerprint

The dnsping output is worth reading closely, because the format is doing diagnostic work rather than decoration.

Each response line carries the bytes returned, the sequence number, the time in milliseconds, the response code, the flags, and the EDNS flags, followed by the extended error in brackets when one is present. The example line ends with an EDE code and its parenthesised text, so a failing query tells you which part of the resolution failed rather than only that it did.

The header line states the whole context of the measurement, in the form of the server and port, the hostname, the protocol, the class and the type, and the query flags:

code
dnsping.py DNS: 8.8.8.8:853, hostname: brokendnssec.net, proto: TLS, class: IN, type: AAAA, flags: [RD]

The summary block at the end is the part you would put in a monitoring log, with the requests transmitted, responses received, the loss percentage, and the minimum, average and maximum times with the standard deviation.

Two details are worth noticing in that summary. The server is written as 8.8.8.8:853 because the query went over TLS, so the port is part of the identity of the endpoint, which is what lets you compare the same resolver across transports without confusing the results. And the average in the example is lower than the minimum of the individual samples shown above it, which is an arithmetic inconsistency in the published example rather than something you should expect to reproduce.

Overall the format is a deliberate blend of the ping tradition and a DNS debugger, and it is close enough to the ping output that anyone who has used that tool will read it without instruction.

A recent release line, standard packaging, and a short dependency set

dnsdiag is BSD-2-Clause licensed, the repository is not archived, and the last push was on 2026-10-14, the same day as the v2.10.0 release. Before that came v2.9.4 in July 2026 and v2.9.3 in February 2026, so the release cadence in 2026 has been a few point releases a year, with the classifier in the package metadata marking the project as Production/Stable.

The packaging is plain setuptools with a pyproject.toml, and the module layout is unusual in a useful way. There is a dnsdiag/ package, and the three entry points are single modules at the top level, dnsping.py, dnstraceroute.py and dnseval.py, exposed as console scripts named dnsping, dnstraceroute and dnseval. The pyproject lists both packages and py-modules, so the package installs the shared library and the thin entry modules together.

The runtime dependencies are four, and they explain the feature set. dnspython with the doh and doq extras is the DNS library, and its DoH and DoQ support is what makes the encrypted transports possible. cryptography is there for DNSSEC validation and the certificate handling that TLS and DoH need. httpx2 is the HTTP client, which serves the DoH and HTTP3 paths. And cymruwhois is a Team Cymru whois client, which is a clue that at least one of the tools looks up address or routing information beyond plain DNS.

The repository has a tests/ directory, a mypy configuration in pyproject.toml, a Dockerfile based on python:3.14-alpine that installs from requirements.txt, a build-pkgs.sh for the binary packages, and a MANIFEST.in for the source distribution. The changelog is generated rather than written, with git-changelog configured to parse conventional commits and insert them into CHANGELOG.md at a marker line, which is why the file at the root is a reliable record of what changed.

Editorial conclusion

dnsdiag suits a network engineer or a curious user who needs to establish whether a resolver is slow, whether a query is being redirected, and which of several resolvers actually performs best for their network, without setting up a monitoring stack. It does not suit a team that needs continuous measurement over weeks, since it is a command line tool that reports on a run, and it is not the place to enforce DNSSEC policy. Verify first that the transport you need is supported by the resolver you are testing, since the transport flags are mutually exclusive, and read the response flags in the output rather than the timing alone, because a fast SERVFAIL with an extended DNS error is a different problem from a fast successful answer.

Frequently asked questions

What tools does dnsdiag provide?

Three console commands: dnsping measures the response time of a resolver for arbitrary queries, dnstraceroute traces the route of a DNS request to spot redirection or interception, and dnseval compares multiple resolvers on latency and packet loss.

How do I run dnsdiag without installing it?

With uv, using uvx --from dnsdiag dnsping google.com for a one-off run, or uv tool install dnsdiag for a persistent installation that can be upgraded with uv tool upgrade dnsdiag. Running from source or installing with pip requires Python 3.11 or newer.

Which DNS transports does dnsping support?

UDP by default, with --tcp, --tls, --doh, --quic and --http3 available to select another transport. Those transport options are mutually exclusive, so only one protocol can be specified per command.

How does dnsdiag detect DNS interception?

dnstraceroute compares the paths taken by DNS queries sent to the same server, and differences between the paths are the signal that something may be redirecting or intercepting the traffic.

Is dnsdiag available on Windows on ARM?

No prebuilt binary is provided for Windows ARM64, because the build dependencies require native compilation toolchains that are not readily available. The README suggests running it under WSL2 or installing from source.

Official sources

  1. farrokhi/dnsdiag on GitHub
  2. License: BSD-2-Clause
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/farrokhi-dnsdiag.svg)](https://hysenlabs.com/projects/farrokhi-dnsdiag)

Was this useful?