Git Product home page Git Product logo

dnsvalidator's Introduction

DNS Validator

Maintains a list of IPv4 DNS servers by verifying them against baseline servers, and ensuring accurate responses.

Python 3.2|3.6 License Twitter Twitter

DNSValidator

DNS Validator's approach is different to other DNS query validation tools. This tool performs multiple validation steps on each resolver:

  • Baselines non-geolocated domain names against "trusted" public DNS resolvers, 1.1.1.1, 8.8.8.8 and 9.9.9.9
    • For each resolver being tested DNS Validator ensures that each baselined domain name resolves to the same IP Address.
      • Servers that return an answer that differs from the baseline are immediately skipped
  • Performs DNS lookup of known commonly spoofed DNS addresses to ensure NXDOMAIN is returned when expected.
    • Resolvers that do not return NXDOMAIN for random subdomains of known target domains are immediately skipped.

Usage

Argument Description
(stdin) Pipe target lists from another application to verify.
-t Specify a target DNS server to verify.
-tL Specify a list of targets or a URL to a list of targets
-e Specify a target exclusion.
-eL Specify a list of targets or a URL to a list of targets to exclude.
-r Specify a root domain to compare to. Must be non-geolocated or most resolvers will fail.
-q Specify a resolver query to use (default:dnsvalidator)
-threads Specify the maximum number of threads to run at any one time (DEFAULT:5)
-timeout Specify a timeout value in seconds for any single thread (DEFAULT:600)
-o Specify an output file to write successful output to.
--no-color If set then any foreground or background colours will be stripped out
--silent If set then only successfully resolved servers will be displayed and banners and other information will be redacted.
-v If set then verbose output will be displayed in the terminal.

Setup

Install using:

$ python3 setup.py install

Dependencies will then be installed and DNS Validator will be added to your path as dnsvalidator.

Examples:

CLI:

$ dnsvalidator -tL https://public-dns.info/nameservers.txt -threads 20 -o resolvers.txt

Docker:

Build

$ docker build -t dnsvalidator .

Run:

$ docker run -v $(pwd):/dnsvalidator/output -t dnsvalidator -tL https://public-dns.info/nameservers.txt -threads 20 -o /dnsvalidator/output/resolvers.txt

Caveats

  • WARNING Keep the thread count to a reasonable level and/or use a VPS/VPN appropriately. Pushing the thread count too high can make it look like you are attempting to attack DNS servers, resulting in network level DNS blocks from your ISP. Ask us how we know...
  • Root domains used for baseline tests must not be geolocated; specifically they must return the same IP address regardless of the location on the planet they are resolved from. Domains such as google.com or facebook.com (and many others) are not suitable for baselines, as they return a geo-located IP address when resolved.
    • Using a root domain that is geo-located will result in only resolvers local to the user being returned as valid.

dnsvalidator's People

Contributors

codingo avatar evildaemond avatar fabaff avatar jburger avatar mhmdiaa avatar vortexau avatar wisdom-in-snow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dnsvalidator's Issues

dns.resolver.NoNameservers: All nameservers failed to answer the query bet365.com. IN A: Server 1.1.1.1 UDP port 53 answered [Errno 101] Network is unreachable

HI,
I am trying to run command -
dnsvalidator -tL https://public-dns.info/nameservers.txt -threads 100 -o resolvers.txt

but its showing this error -

[05:45:52] [INFO] [1.1.1.1] resolving baseline
Traceback (most recent call last):
File "/usr/local/bin/dnsvalidator", line 33, in
sys.exit(load_entry_point('DNSValidator==0.1', 'console_scripts', 'dnsvalidator')())
File "/usr/local/lib/python3.9/dist-packages/DNSValidator-0.1-py3.9.egg/dnsvalidator/dnsvalidator.py", line 120, in main
File "/usr/lib/python3/dist-packages/dns/resolver.py", line 1089, in query
return self.resolve(qname, rdtype, rdclass, tcp, source,
File "/usr/lib/python3/dist-packages/dns/resolver.py", line 1040, in resolve
(nameserver, port, tcp, backoff) = resolution.next_nameserver()
File "/usr/lib/python3/dist-packages/dns/resolver.py", line 598, in next_nameserver
raise NoNameservers(request=self.request, errors=self.errors)
dns.resolver.NoNameservers: All nameservers failed to answer the query bet365.com. IN A: Server 1.1.1.1 UDP port 53 answered [Errno 101] Network is unreachable

I verified my network was fine. not able to resolve the issue. please help

telegram.com return a geolocated IP address when resolved

Domain telegram.com return a geolocated IP address when resolved. As mentioned in the README file root domains used for baseline tests must not be geolocated because it will result in only resolvers local to the user being returned as valid.

[email protected] (Cloudflare):
telegram.com. 4800 IN A 146.75.34.62
[email protected] (Google):
telegram.com. 3784 IN A 151.101.70.62

You can check if a domain is geolocated using check-host.net to ping from different locations.
Thanks.

Log resolvers that are poisoning responses to a separate log file.

This tool is good at detecting resolvers that exist simply to poison Internet DNS traffic, however the initial form of the tool simply discards this information as it is not useful in the core usage of the tool.

Performing further research on the blocked servers would be interesting, so it would be handy to optionally log these to a separate file for further research.

Over time it would be possible to build an exclusion list for known-bad resolvers that can simply be ignored.

Please create a release

Please create a release and/or publish the tool on PyPI.

Would be much easier for package maintainers to include it into distributions. Thanks.

Revalidate resolvers after a wait time has elapsed.

To be implemented in the future; revalidate servers after a wait time to ensure they are not performing tricks such as returning valid results initially, and then poisoned responses after X amount of time.

File Operations append to files, existing checks on launch

#5 introduced file operations however these are currently performed in append mode, as per:


        if self.output and level == 2:
            f = open(self.output, 'a')
            f.writelines("\n" + target)
            f.close()

This is a quick solution, and not ideal, as it wont' overwrite previous files. A flag should either be added to remove previous files before execution (not ideal) or the code should be update to create an open file handler with argparse and then perform a write operation throughout the programs execution. This last option would also have the added benefit of preventing continual file open/close operations throughout execution.

No arguments doesn't parse

If using no arguments defaults aren't used an no execution happens. Passing a single argument of any kind resolves this.

Release

It would be very nice if there is a release of dnsvalidator. This would simplify the process of creating packages for distributions.

Thanks in advance.

buffers don't write to tee or > etc'

When using tee or redirecting output with > output completely stalls. Normally this would be resolved by launching as:

python3 -u <application

However this isn't an option as everything has been built into a package. Further investigation needs to be done to resolve this.

Program exiting after validating ~2k resolvers, in some situations.

In so far unknown circumstances, the program will "complete" at around 2000 resolvers written to disk. Potentially related to exception handling, but this is a guess at the moment.

Using the list provided in example commands the expected output size is ~13k valid IPv4 resolvers.

Timeout parameter unused

At first I assumed it was the timeout of each dns-lookup, however it is supposed to be the thread timeout.

In any way, the parameter value does not seem to be used anywhere in the code.

Change the installation instruction .

Oh man , pissed me so much , was working with chatgpt to resolve my endless errors i was recieving when running :
$ python3 setup.py install

At end i found solution to use latest installtion method to fix all the installation errors :

cd ~/
git clone https://github.com/vortexau/dnsvalidator.git
pip install --use-pep517 ~/dnsvalidator

Update the installation instruction as per above , for everyone .

Regards,

argument -tL: invalid <lambda> value error on specifying local file

Hi vortex,

I have been trying dnsvalidator and while it seems to be running well with the -tL argument value as url but when I am passing a local file path it is giving this error:

image

Can you please look into this and correct me if I am doing something wrong.

Thanks :)

DNS Timeout exception not handled in baseline checks.

When querying DNS servers, occasionally a 30 second timeout is encountered (UDP gonna UDP!) and the exception generated is not handled correctly.

Example:

[21:51:50] [INFO] [1.1.1.1] resolving baseline
[21:51:55] [INFO] [8.8.8.8] resolving baseline
Traceback (most recent call last):
  File "/usr/local/bin/dnsvalidator", line 11, in <module>
    load_entry_point('DNSValidator==0.1', 'console_scripts', 'dnsvalidator')()
  File "/usr/local/lib/python3.7/dist-packages/DNSValidator-0.1-py3.7.egg/dnsvalidator/dnsvalidator.py", line 134, in main
  File "/usr/lib/python3/dist-packages/dns/resolver.py", line 992, in query
    timeout = self._compute_timeout(start, lifetime)
  File "/usr/lib/python3/dist-packages/dns/resolver.py", line 799, in _compute_timeout
    raise Timeout(timeout=duration)
dns.exception.Timeout: The DNS operation timed out after 30.00101947784424 seconds

A baseline domain has a wildcard DNS setup leading to inaccurate results

Description

telegram.com is one of the domains used by dnsvalidator to check for DNS poisoning. If a resolver responds with a non-NXDOMAIN response for a random subdomain, it's dismissed.

nxdomainchecks = ["facebook.com", "paypal.com", "google.com",
                  "bet365.com", "telegram.com", "wikileaks.com"]
...
    for nxdomaincheck in nxdomainchecks:
        # make sure random subdomains are NXDOMAIN
        try:
            positivehn = "{rand}.{domain}".format(
                rand=rand(),
                domain=nxdomaincheck
            )
            posanswer = resolver.query(positivehn, 'A')

            # nxdomain exception was not thrown, we got records when we shouldn't have.
            # Skip the server.
            output.terminal(Level.ERROR, server,
                            "DNS poisoning detected, passing")
            return

The issue is that telegram.com is a wildcard.

$ dig '*.telegram.com'

; <<>> DiG 9.10.6 <<>> *.telegram.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25491
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1220
;; QUESTION SECTION:
;*.telegram.com.			IN	A

;; ANSWER SECTION:
*.telegram.com.		9600	IN	CNAME	wh158-gbahn.production.gannettdigital.com.
wh158-gbahn.production.gannettdigital.com. 300 IN A 159.54.247.168

;; Query time: 127 msec
;; SERVER: 192.168.1.1#53(192.168.1.1)
;; WHEN: Wed Nov 02 22:36:46 EET 2022
;; MSG SIZE  rcvd: 111

So any resolver that correctly responds with NOERROR for randomstring.telegram.com is disregarded with a DNS poisoning detected, passing message.


PoC

$ dnsvalidator -t 8.8.8.8
=======================================================
dnsvalidator v0.1	by James McLean (@vortexau)
                	& Michael Skelton (@codingo_)
=======================================================
[22:41:46] [INFO] [1.1.1.1] resolving baseline
[22:41:46] [INFO] [8.8.8.8] resolving baseline
[22:41:47] [INFO] [9.9.9.9] resolving baseline
[22:41:47] [INFO] [8.8.8.8] Checking...
[22:41:48] [ERROR] [8.8.8.8] DNS poisoning detected, passing
[22:41:48] [INFO] Finished. Discovered 0 servers

Baseline check only saves last returned IP for the last baseline resolver

The goodip comparison isn't working as expected here:

if responses[goodresponse]["goodip"] == goodip:

The reason is because goodip is getting overwritten in the loop:

for rr in goodanswer:
baseline_server["goodip"] = str(rr)
goodip = str(rr)

It would essentially mean that goodip value will have the last IP address of the root domain for the last resolver.

Ideally, I'd suggest avoiding the use of global variables. It makes the flow of the code a bit confusing and could potentially cause problems down the road.

Another improvement would be to restructure the code so that program fails if the baseline resolvers produce different results. The goodip, nxdomain status, poison checks happen for all baseline resolvers - if they all produce the same results, program should continue. If not, exit with a fatal error. This will also avoid the need for comparing the results of individual resolvers with that of all the three baseline resolvers - they're all the same, so only one of them needs to be checked.

not setup install properlly

here i type the command for setups install after the clone python3 setup.py install give this error try all thing not loved

Traceback (most recent call last):
zip_safe flag not set; analyzing archive contents...
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 157, in save_modules
yield saved
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 198, in setup_context
yield
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 255, in run_setup
DirectorySandbox(setup_dir).run(runner)
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 285, in run
return func()
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 253, in runner
_execfile(setup_script, ns)
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 47, in _execfile
exec(code, globals, locals)
File "/tmp/easy_install-mrd3q35u/pytest-runner-5.2/setup.py", line 21, in
url="https://github.com/vortexau/dnsvalidator",
File "/usr/lib/python3.7/distutils/core.py", line 148, in setup
dist.run_commands()
File "/usr/lib/python3.7/distutils/dist.py", line 966, in run_commands
self.run_command(cmd)
File "/usr/lib/python3.7/distutils/dist.py", line 985, in run_command
cmd_obj.run()
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 209, in run
os.path.join(archive_root, 'EGG-INFO'), self.zip_safe()
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 245, in zip_safe
return analyze_egg(self.bdist_dir, self.stubs)
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 355, in analyze_egg
safe = scan_module(egg_dir, base, name, stubs) and safe
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 395, in scan_module
symbols = dict.fromkeys(iter_symbols(code))
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 414, in iter_symbols
for name in code.co_names:
AttributeError: type object 'StopIteration' has no attribute 'co_names'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "setup.py", line 32, in
include_package_data=True)
File "/usr/lib/python3.7/distutils/core.py", line 108, in setup
_setup_distribution = dist = klass(attrs)
File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 317, in init
self.fetch_build_eggs(attrs['setup_requires'])
File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 372, in fetch_build_eggs
replace_conflicting=True,
File "/usr/lib/python3/dist-packages/pkg_resources/init.py", line 846, in resolve
dist = best[req.key] = env.best_match(req, ws, installer)
File "/usr/lib/python3/dist-packages/pkg_resources/init.py", line 1118, in best_match
return self.obtain(req, installer)
File "/usr/lib/python3/dist-packages/pkg_resources/init.py", line 1130, in obtain
return installer(requirement)
File "/usr/lib/python3/dist-packages/setuptools/dist.py", line 440, in fetch_build_egg
return cmd.easy_install(req)
File "/usr/lib/python3/dist-packages/setuptools/command/easy_install.py", line 699, in easy_install
return self.install_item(spec, dist.location, tmpdir, deps)
File "/usr/lib/python3/dist-packages/setuptools/command/easy_install.py", line 725, in install_item
dists = self.install_eggs(spec, download, tmpdir)
File "/usr/lib/python3/dist-packages/setuptools/command/easy_install.py", line 906, in install_eggs
return self.build_and_install(setup_script, setup_base)
File "/usr/lib/python3/dist-packages/setuptools/command/easy_install.py", line 1145, in build_and_install
self.run_setup(setup_script, setup_base, args)
File "/usr/lib/python3/dist-packages/setuptools/command/easy_install.py", line 1131, in run_setup
run_setup(setup_script, args)
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 258, in run_setup
raise
File "/usr/lib/python3.7/contextlib.py", line 130, in exit
self.gen.throw(type, value, traceback)
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 198, in setup_context
yield
File "/usr/lib/python3.7/contextlib.py", line 130, in exit
self.gen.throw(type, value, traceback)
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 169, in save_modules
saved_exc.resume()
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 144, in resume
six.reraise(type, exc, self._tb)
File "/usr/lib/python3/dist-packages/pkg_resources/_vendor/six.py", line 685, in reraise
raise value.with_traceback(tb)
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 157, in save_modules
yield saved
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 198, in setup_context
yield
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 255, in run_setup
DirectorySandbox(setup_dir).run(runner)
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 285, in run
return func()
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 253, in runner
_execfile(setup_script, ns)
File "/usr/lib/python3/dist-packages/setuptools/sandbox.py", line 47, in _execfile
exec(code, globals, locals)
File "/tmp/easy_install-mrd3q35u/pytest-runner-5.2/setup.py", line 21, in
url="https://github.com/vortexau/dnsvalidator",
File "/usr/lib/python3.7/distutils/core.py", line 148, in setup
dist.run_commands()
File "/usr/lib/python3.7/distutils/dist.py", line 966, in run_commands
self.run_command(cmd)
File "/usr/lib/python3.7/distutils/dist.py", line 985, in run_command
cmd_obj.run()
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 209, in run
os.path.join(archive_root, 'EGG-INFO'), self.zip_safe()
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 245, in zip_safe
return analyze_egg(self.bdist_dir, self.stubs)
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 355, in analyze_egg
safe = scan_module(egg_dir, base, name, stubs) and safe
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 395, in scan_module
symbols = dict.fromkeys(iter_symbols(code))
File "/usr/lib/python3/dist-packages/setuptools/command/bdist_egg.py", line 414, in iter_symbols
for name in code.co_names:
AttributeError: type object 'StopIteration' has no attribute 'co_names'

plz some help

Multithreading

Self-described. Threading needs to be added to verification.

Unable to run ImportError

python3 /dnsvalidator/dnsvalidator.py  -h
traceback (most recent call last):
  File "dnsvalidator/dnsvalidator.py", line 15, in <module>
    from .lib.core.input import InputParser, InputHelper
ImportError: attempted relative import with no known parent package

on Ubuntu 20.04.3 LTS machine

set up problem

    It is possible a package already installed in your system
    contains an version that is invalid according to PEP 440.
    You can try `pip install --use-pep517` as a workaround for this problem,
    or rely on a new virtual environment.

    If the problem refers to a package that is not installed yet,
    please contact that package's maintainers or distributors.

Traceback (most recent call last):
File "setup.py", line 13, in
setup(
File "/usr/local/lib/python3.8/dist-packages/setuptools/init.py", line 107, in setup
_install_setup_requires(attrs)
File "/usr/local/lib/python3.8/dist-packages/setuptools/init.py", line 80, in _install_setup_requires
_fetch_build_eggs(dist)
File "/usr/local/lib/python3.8/dist-packages/setuptools/init.py", line 85, in _fetch_build_eggs
dist.fetch_build_eggs(dist.setup_requires)
File "/usr/local/lib/python3.8/dist-packages/setuptools/dist.py", line 879, in fetch_build_eggs
resolved_dists = pkg_resources.working_set.resolve(
File "/usr/local/lib/python3.8/dist-packages/pkg_resources/init.py", line 815, in resolve
dist = self._resolve_dist(
File "/usr/local/lib/python3.8/dist-packages/pkg_resources/init.py", line 844, in _resolve_dist
env = Environment(self.entries)
File "/usr/local/lib/python3.8/dist-packages/pkg_resources/init.py", line 1044, in init
self.scan(search_path)
File "/usr/local/lib/python3.8/dist-packages/pkg_resources/init.py", line 1077, in scan
self.add(dist)
File "/usr/local/lib/python3.8/dist-packages/pkg_resources/init.py", line 1096, in add
dists.sort(key=operator.attrgetter('hashcmp'), reverse=True)
File "/usr/local/lib/python3.8/dist-packages/pkg_resources/init.py", line 2631, in hashcmp
self.parsed_version,
File "/usr/local/lib/python3.8/dist-packages/pkg_resources/init.py", line 2685, in parsed_version
raise packaging.version.InvalidVersion(f"{str(ex)} {info}") from None
pkg_resources.extern.packaging.version.InvalidVersion: Invalid version: '0.23ubuntu1' (package: distro-info)
root@vmi1101989:~/tools/dnsvalidator# pip install --use-pep517

uname -a
Linux vmi1101989.contaboserver.net 5.4.0-105-generic #119-Ubuntu SMP Mon Mar 7 18:49:24 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.