dnsvalidator: filtering a candidate DNS resolver list down to the honest ones
Maintains a list of IPv4 DNS servers by verifying them against baseline servers, and ensuring accurate responses.
At a glance
- What is it?
- dnsvalidator tests candidate IPv4 DNS servers against trusted baseline resolvers and against spoofing probes, and keeps only the ones that answer correctly. It is a GPL-3.0 command line tool with a Docker image, and it warns that high thread counts can get you blocked.
- Who is it for?
- dnsvalidator is worth using if you maintain a resolver list of your own, because it separates resolvers that answer consistently from resolvers that return local or hijacked answers, and it ships as a plain command plus a container image. It is the wrong tool if you need a single reliable resolver, since a public resolver such as 1.1.1.1 or 8.8.8.8 already provides that.
- Can I use it commercially?
- Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 41 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 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A resolver list is only useful if the answers agree
Public IPv4 DNS resolvers are easy to collect and hard to trust. The premise of this tool is that a list of addresses, however long, is worth nothing unless every resolver on it returns the same answer as a trusted reference, and unless it refuses to invent records for domains that should not exist. A resolver that quietly returns a different address, for example one from an ISP that injects a portal page, passes a naive reachability test and then poisons whatever the list is used for.
dnsvalidator therefore maintains a list of IPv4 DNS servers by verifying them against baseline servers and ensuring accurate responses. The audience is anyone who curates such a list, which in practice means security testers checking whether open resolvers on a network are really open, and researchers assembling a measurement set.
The difference from other DNS query validation tools, as the project puts it, is that the validation is multi-step and applied to each resolver individually. Two checks run, and a resolver that fails either one is dropped immediately rather than being flagged and passed on to the next stage.
The packaging is honest about the intended use. The setup metadata describes the tool as maintaining a list of DNS servers useful for brute forcing, and the licence is GPL-3.0, with the repository listing a `CREDITS.md` and a `LICENSE` file at the top level.
Stage one compares answers against 1.1.1.1, 8.8.8.8 and 9.9.9.9
The first validation step baselines non geolocated domain names against the trusted public resolvers `1.1.1.1`, `8.8.8.8` and `9.9.9.9`. For every resolver under test, the tool checks that each baselined domain name resolves to the same IP address. A resolver whose answer differs from the baseline is skipped at once.
The interesting part of that sentence is the requirement that the baseline domains be non geolocated. A domain such as `google.com` or `facebook.com` returns a different address depending on where the query comes from, so using one of those as a baseline would mark every resolver outside the operator's own region as wrong. That is a configuration error rather than a resolver defect, and the project calls it out separately, because the symptom, a list containing only local resolvers, looks like a bug in the tool.
The baseline domains are not hard coded in the way the trusted resolvers are. They come from the command line, through the `-r` argument, which must be a root domain that returns the same IP address regardless of where it is resolved from.
The second step tests the opposite property. The tool performs a DNS lookup of known commonly spoofed DNS addresses and requires that NXDOMAIN is returned when it is expected. A resolver that does not return NXDOMAIN for random subdomains of those known target domains is skipped. A resolver that answers anyway is not merely wrong, it is the shape of the behaviour that makes DNS hijacking work, and that is the reason to drop it rather than to note it.
Installing with setup.py puts dnsvalidator on your path
Installation is the older style. The README gives a single command, and the dependencies are installed with it.
$ python3 setup.py installAfter that the tool is added to the path as `dnsvalidator`. The Python dependencies are listed in `requirements.txt` and read by the setup script, so they are installed as part of the same step.
requests
dnspython
colorclass
netaddr
ipaddress`dnspython` is the resolver library that does the actual lookups, `netaddr` and `ipaddress` handle address handling and filtering, `requests` fetches remote target lists, and `colorclass` produces the coloured terminal output that the `--no-color` option exists to turn off. The setup script also registers the console entry point `dnsvalidator = dnsvalidator.dnsvalidator:main`, declares the package data for the bundled text files, and sets pytest as the test runner.
One detail in the metadata tells you the age of the codebase. The project advertises Python 3.2 and 3.6 support, and the container image is built on a Python 3.7 alpine base, so this is a tool written against an older Python and an older packaging style.
Targets, exclusions and the resolver query name
The command line is a small table of switches, and two of them do the interesting work. `-t` names a single target DNS server to verify, and `-tL` takes a list of targets or a URL pointing at a list. The same pairing exists for exclusions with `-e` and `-eL`, so a known bad range can be filtered out of a large sweep. Target lists can also arrive on standard input, which is what the pipe notation in the argument table is for.
The `-r` argument sets the root domain used for the comparison, and the documentation is explicit that it must be non geolocated or most resolvers will fail. The `-q` argument selects the resolver query to use, with `dnsvalidator` as the default. That last detail is worth understanding: a query name is the label the tool asks for, and changing it is how a caller works around a network that blocks the default name or wants to distinguish its own traffic from other users of the same tool.
Resource control is done with `-threads`, whose default is 5, and `-timeout`, a per thread timeout in seconds whose default is 600. Output handling is handled by `-o` to write successful results to a file, `--silent` to show only the successfully resolved servers with banners and other information redacted, `--no-color` to strip the terminal colours, and `-v` for verbose output.
The Docker image runs the validator as a separate user
A container build is documented for people who would rather not install the package on the host. The build command tags the image locally.
$ docker build -t dnsvalidator .The run example mounts the current directory into the container and writes the resolver list into it.
$ docker run -v $(pwd):/dnsvalidator/output -t dnsvalidator -tL https://publicdns.info/nameservers.txt -threads 20 -o /dnsvalidator/output/resolvers.txtThe image definition is small and shows the project's care about how the tool is run. It starts from a python alpine base, adds bash and shadow for user management, creates a directory for the tool, and creates a dedicated `dnsvalidator` user with a home directory and a non login shell. The source is copied in, the ownership is changed to that user, the package is installed during the build, and the container switches to that user before starting. The entry point is the installed `dnsvalidator` binary, so passing arguments to `docker run` passes them straight to the tool.
The volume mount in the example is the other detail that matters. The output file is written inside the mounted directory, which is how the result escapes the container, and the same path is used for the target list if you want to feed the tool a local file instead of a URL.
High thread counts get you blocked, and geolocated baselines empty the list
The caveats section is unusually blunt, and both entries are things that will happen to a user who ignores them. The first is a warning to keep the thread count to a reasonable level and, where appropriate, to use a VPS or VPN, because pushing the thread count too high can look like an attempt to attack DNS servers and can result in network level DNS blocks from your ISP. The README ends that warning with a rhetorical aside about how they know this, which is a fair indicator that the behaviour has been observed rather than theorised.
That caveat is really about the line between validating resolvers and abusing them. A resolver that answers for anyone is exactly the kind of infrastructure that gets used to amplify traffic against a third party, so the tool's own documentation draws the line for its users.
The second caveat is the geolocation trap described earlier, and it has a precise failure mode: using a geo-located root domain as the baseline results in only resolvers local to the user being returned as valid. The consequence is a list that looks plausible and is silently wrong.
Taken together, the two caveats say the same thing about the tool's shape. It is built to sweep a large candidate set, and it is built to be careful about how that sweep looks from the outside, because the operators running it and the operators of the resolvers being tested can end up on the same side of an abuse report.
Where a single trusted resolver differs from a validated list
The alternative is obvious and often better: use one known public resolver and configure it everywhere. `1.1.1.1`, `8.8.8.8` and `9.9.9.9` are the three the tool itself treats as trusted baselines, and they are the same three that most distributions and applications point at by default. That approach has no sweep, no thread count, no list to maintain and nothing that can be blocked.
The difference in approach is the difference between one resolver you depend on and a set of resolvers you have measured. dnsvalidator exists for the case where a single resolver is not acceptable, for instance when a network must not send queries to one operator, when a measurement needs many vantage points, or when the question being asked is which resolvers on a range are open in the first place. In those cases the output is a set of addresses with the property that they agree with a reference and refuse to invent records.
That output is also the tool's weakness, in a way worth stating plainly. A validated list is a snapshot. A resolver that is correct today can be hijacked next month, and the tool does not schedule its own re-verification, so keeping the list honest means running the validation again and comparing. The repository has no releases, so there is no version history to consult and no upgrade notes to read; the last push was on 2026-09-14.
Editorial conclusion
dnsvalidator is worth using if you maintain a resolver list of your own, because it separates resolvers that answer consistently from resolvers that return local or hijacked answers, and it ships as a plain command plus a container image. It is the wrong tool if you need a single reliable resolver, since a public resolver such as 1.1.1.1 or 8.8.8.8 already provides that. Before running a large sweep, decide on a non geolocated root domain for the `-r` baseline, keep `-threads` low enough to stay under your provider's radar, and remember that the repository has no releases, so the last push on 2026-09-14 is the version you get.
Frequently asked questions
What does the dnsvalidator tool check on a DNS resolver?
It baselines non geolocated domain names against the trusted resolvers 1.1.1.1, 8.8.8.8 and 9.9.9.9 and requires the resolver under test to return the same IP address, and it checks that NXDOMAIN is returned for random subdomains of known commonly spoofed target domains. A resolver that fails either check is skipped immediately.
How do I install dnsvalidator?
The README documents `python3 setup.py install`, which installs the dependencies from requirements.txt and adds the tool to the path as `dnsvalidator`. The dependencies are requests, dnspython, colorclass, netaddr and ipaddress.
Which command line options does dnsvalidator accept?
Targets are given with -t for one server and -tL for a list or a URL, exclusions with -e and -eL, and target lists can also be piped in on standard input. The baseline root domain is set with -r, the resolver query name with -q, and the sweep is controlled by -threads, which defaults to 5, and -timeout, which defaults to 600 seconds per thread.
How do I run dnsvalidator in Docker?
Build the image with `docker build -t dnsvalidator .` and run it with the `docker run` command, mounting a host directory so the output file is reachable. The image is based on a python alpine image, installs the package at build time and runs as a dedicated dnsvalidator user with the installed binary as its entry point.
Why should I not set a high thread count in dnsvalidator?
The README warns that pushing the thread count too high can look like an attempt to attack DNS servers and can result in network level DNS blocks from your ISP. It also warns that a geo-located baseline root domain makes the tool return only resolvers local to the user as valid.
Official sources
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.
[](https://hysenlabs.com/projects/vortexau-dnsvalidator)Was this useful?