23 Commits

Author SHA1 Message Date
25c243efa1 Preparing for v1.6.4
General improvements and fixes
2018-04-03 17:01:50 +04:30
a0c26242ec Add sample input file with IPv4 address of public resolvers
for people who are still on legacy networks from late 20th century.
2018-04-02 22:38:00 +04:30
e93120da19 Fix sample input filename in README 2018-04-02 22:36:02 +04:30
dc7f03eac3 Add CloudFlare's new resolver (v4/v6) (Fixes #51) 2018-04-02 11:52:29 +04:30
7390514877 Deal with failures to open input file (fixes #50) 2018-02-18 07:36:37 +03:30
bbff3b44f6 Use "dnsdiag" keyword when generating random hostnames 2018-01-23 17:36:02 +03:30
d93b87b2a2 Remove a leftover debug message 2018-01-23 17:14:23 +03:30
8a9acd9100 Add -m to force cache-miss measurement in dnseval (Closes #41)
Using `-m` causes dnseval to add a random hostname prefix to the given
domain name (format is "_dnseval_RANDOM_."). This will cause NXDOMAIN
and the query fails, but we do measure the response time anyway.
2018-01-23 15:20:36 +03:30
8283f4dbc2 Ability to have comments in resolvers list (Closes #43) 2018-01-23 12:25:46 +03:30
e3ddfff88e User can specify source address (Fixes #46)
- also respect resolver port number (if specified by user)
2018-01-23 12:13:50 +03:30
1b9849c224 Use more accurate response time measurement method (fixes #44) 2018-01-23 11:32:40 +03:30
76b843d728 Merge pull request #42 from webernetz/patch-1
Update public-servers.txt
2017-11-27 23:03:21 +03:30
037457f0cc Update public-servers.txt
Added the open DNS resolvers from Quad9 and OpenDNS. Both for IPv6 and legacy IP.
2017-11-27 20:31:46 +01:00
4c9aaf921b Merge pull request #38 from will-h/master
Allow '-f -' to denote stdin
2017-11-04 20:12:25 +03:30
f1807d34ea Allow '-f -' to denote stdin 2017-11-01 21:34:56 +00:00
9caa006e5b Change default ping interval to 1 second 2017-10-06 10:46:16 +03:30
5a99d58dd1 Ignore virtualenv directory 2017-10-06 10:38:00 +03:30
c92ea53e57 Use a more readable color in verbose mode 2017-05-02 14:45:03 +04:30
47dbc6afe3 Update installation notes to reflect recent changes 2017-05-02 14:18:52 +04:30
39e564e626 Use cymruwhois from pypi and remove submodule
- cymruwhois maintainer recovered his access to pypi and
  uploaded latest package. There is no need to use it as
  submodule anymore. So we added an external dependency.

- Refactor whois data caching in dnstraceroute and unbreak
  caching mechanism which was broken since previous commit
  due to a bug in time delta calculation.
2017-05-02 14:16:17 +04:30
3df692e6db No more needed 2017-04-30 21:18:45 +04:30
2dcf0e7b78 Fix setuptools 2017-04-30 21:12:08 +04:30
a0f9cae673 Fix setuptool installation and dependecies 2017-04-30 19:35:36 +04:30
12 changed files with 171 additions and 88 deletions

3
.gitignore vendored
View File

@ -1,3 +1,6 @@
# virtualenv
.venv/
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[cod] *.py[cod]

3
.gitmodules vendored
View File

@ -1,3 +0,0 @@
[submodule "cymruwhois"]
path = cymruwhois
url = https://github.com/JustinAzoff/python-cymruwhois.git

View File

@ -1,2 +1 @@
include LICENSE README.md TODO.md public-servers.txt include LICENSE README.md TODO.md public-servers.txt
include cymruwhois/*.py

View File

@ -29,8 +29,6 @@ of view.
This script requires python3 as well as latest This script requires python3 as well as latest
[dnspython](http://www.dnspython.org/) and [dnspython](http://www.dnspython.org/) and
[cymruwhois](https://pythonhosted.org/cymruwhois/). [cymruwhois](https://pythonhosted.org/cymruwhois/).
All required third-party modules are included as GIT submodules. You just need
to run `git submodule update --init` and project directory to pull the required code.
# installation # installation
@ -43,13 +41,13 @@ There are several ways that you can use this toolset. However using the sourceco
``` ```
git clone https://github.com/farrokhi/dnsdiag.git git clone https://github.com/farrokhi/dnsdiag.git
cd dnsdiag cd dnsdiag
git submodule update --init pip3 install -r requirements.txt
``` ```
2. You can alternatively install the package using pip: 2. You can alternatively install the package using pip:
``` ```
pip3 install --process-dependency-links dnsdiag pip3 install dnsdiag
``` ```
## From Binary ## From Binary
@ -99,7 +97,7 @@ dnseval is a bulk ping utility that sends an arbitrary DNS query to a give list
of DNS servers. This script is meant for comparing response time of multiple of DNS servers. This script is meant for comparing response time of multiple
DNS servers at once: DNS servers at once:
``` ```
% ./dnseval.py -t AAAA -f public-v4.txt -c10 yahoo.com % ./dnseval.py -t AAAA -f public-servers.txt -c10 yahoo.com
server avg(ms) min(ms) max(ms) stddev(ms) lost(%) ttl flags server avg(ms) min(ms) max(ms) stddev(ms) lost(%) ttl flags
------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------
8.8.8.8 270.791 215.599 307.498 40.630 %0 298 QR -- -- RD RA -- -- 8.8.8.8 270.791 215.599 307.498 40.630 %0 298 QR -- -- RD RA -- --

Submodule cymruwhois deleted from a34543335c

View File

@ -33,6 +33,8 @@ import signal
import socket import socket
import sys import sys
import time import time
import random
import string
from statistics import stdev from statistics import stdev
import dns.rdatatype import dns.rdatatype
@ -40,7 +42,7 @@ import dns.resolver
__author__ = 'Babak Farrokhi (babak@farrokhi.net)' __author__ = 'Babak Farrokhi (babak@farrokhi.net)'
__license__ = 'BSD' __license__ = 'BSD'
__version__ = "1.6.0" __version__ = "1.6.4"
__progname__ = os.path.basename(sys.argv[0]) __progname__ = os.path.basename(sys.argv[0])
shutdown = False shutdown = False
@ -67,15 +69,16 @@ def usage():
print("""%s version %s print("""%s version %s
usage: %s [-h] [-f server-list] [-c count] [-t type] [-w wait] hostname usage: %s [-h] [-f server-list] [-c count] [-t type] [-w wait] hostname
-h --help show this help -h --help Show this help
-f --file dns server list to use (default: system resolvers) -f --file DNS server list to use (default: system resolvers)
-c --count number of requests to send (default: 10) -c --count Number of requests to send (default: 10)
-w --wait maximum wait time for a reply (default: 2) -m --cache-miss Force cache miss measurement by prepending a random hostname
-t --type DNS request record type (default: A) -w --wait Maximum wait time for a reply (default: 2)
-T --tcp Use TCP instead of UDP -t --type DNS request record type (default: A)
-e --edns Disable EDNS0 (Default: Enabled) -T --tcp Use TCP instead of UDP
-C --color Print colorful output -e --edns Disable EDNS0 (Default: Enabled)
-v --verbose Print actual dns response -C --color Print colorful output
-v --verbose Print actual dns response
""" % (__progname__, __version__, __progname__)) """ % (__progname__, __version__, __progname__))
sys.exit() sys.exit()
@ -137,7 +140,13 @@ def flags_to_text(flags):
return ' '.join(text_flags) return ' '.join(text_flags)
def dnsping(host, server, dnsrecord, timeout, count, use_tcp=False, use_edns=False): def random_string(min_length=5, max_length=10):
char_set = string.ascii_letters + string.digits
length = random.randint(min_length, max_length)
return ''.join(map(lambda unused: random.choice(char_set), range(length)))
def dnsping(host, server, dnsrecord, timeout, count, use_tcp=False, use_edns=False, force_miss=False):
resolver = dns.resolver.Resolver() resolver = dns.resolver.Resolver()
resolver.nameservers = [server] resolver.nameservers = [server]
resolver.timeout = timeout resolver.timeout = timeout
@ -156,16 +165,26 @@ def dnsping(host, server, dnsrecord, timeout, count, use_tcp=False, use_edns=Fal
if shutdown: # user pressed CTRL+C if shutdown: # user pressed CTRL+C
break break
try: try:
if force_miss:
fqdn = "_dnsdiag_%s_.%s" % (random_string(), host)
else:
fqdn = host
stime = time.perf_counter() stime = time.perf_counter()
answers = resolver.query(host, dnsrecord, tcp=use_tcp, answers = resolver.query(fqdn, dnsrecord, tcp=use_tcp,
raise_on_no_answer=False) # todo: response validation in future raise_on_no_answer=False) # todo: response validation in future
etime = time.perf_counter()
except (dns.resolver.NoNameservers, dns.resolver.NoAnswer): except (dns.resolver.NoNameservers, dns.resolver.NoAnswer):
break break
except dns.resolver.Timeout: except dns.resolver.Timeout:
pass pass
except dns.resolver.NXDOMAIN:
etime = time.perf_counter()
if force_miss:
elapsed = (etime - stime) * 1000 # convert to milliseconds
response_times.append(elapsed)
else: else:
elapsed = (etime - stime) * 1000 # convert to milliseconds elapsed = answers.response.time * 1000 # convert to milliseconds
response_times.append(elapsed) response_times.append(elapsed)
r_sent = i + 1 r_sent = i + 1
@ -212,13 +231,15 @@ def main():
fromfile = False fromfile = False
use_tcp = False use_tcp = False
use_edns = True use_edns = True
force_miss = False
verbose = False verbose = False
color_mode = False color_mode = False
hostname = 'wikipedia.org' hostname = 'wikipedia.org'
try: try:
opts, args = getopt.getopt(sys.argv[1:], "hf:c:t:w:TevC", opts, args = getopt.getopt(sys.argv[1:], "hf:c:t:w:TevCm",
["help", "file=", "count=", "type=", "wait=", "tcp", "edns", "verbose", "color"]) ["help", "file=", "count=", "type=", "wait=", "tcp", "edns", "verbose", "color",
"force-miss"])
except getopt.GetoptError as err: except getopt.GetoptError as err:
print(err) print(err)
usage() usage()
@ -238,6 +259,8 @@ def main():
fromfile = True fromfile = True
elif o in ("-w", "--wait"): elif o in ("-w", "--wait"):
waittime = int(a) waittime = int(a)
elif o in ("-m", "--cache-miss"):
force_miss = True
elif o in ("-t", "--type"): elif o in ("-t", "--type"):
dnsrecord = a dnsrecord = a
elif o in ("-T", "--tcp"): elif o in ("-T", "--tcp"):
@ -256,14 +279,25 @@ def main():
try: try:
if fromfile: if fromfile:
with open(inputfilename, 'rt') as flist: if inputfilename == '-':
f = flist.read().splitlines() # read from stdin
with sys.stdin as flist:
f = flist.read().splitlines()
else:
try:
with open(inputfilename, 'rt') as flist:
f = flist.read().splitlines()
except Exception as e:
print(e)
sys.exit(1)
else: else:
f = resolvers f = resolvers
if len(f) == 0: if len(f) == 0:
print("No nameserver specified") print("No nameserver specified")
f = [name.strip() for name in f] f = [name.strip() for name in f] # remove annoying blanks
f = [x for x in f if not x.startswith('#') and len(x)] # remove comments and empty entries
width = maxlen(f) width = maxlen(f)
blanks = (width - 5) * ' ' blanks = (width - 5) * ' '
print('server ', blanks, ' avg(ms) min(ms) max(ms) stddev(ms) lost(%) ttl flags') print('server ', blanks, ' avg(ms) min(ms) max(ms) stddev(ms) lost(%) ttl flags')
@ -277,25 +311,29 @@ def main():
ipaddress.ip_address(server) ipaddress.ip_address(server)
except ValueError: # so it is not a valid IPv4 or IPv6 address, so try to resolve host name except ValueError: # so it is not a valid IPv4 or IPv6 address, so try to resolve host name
try: try:
s = socket.getaddrinfo(server, port=None)[1][4][0] resolver = socket.getaddrinfo(server, port=None)[1][4][0]
except OSError: except OSError:
print('Error: cannot resolve hostname:', server) print('Error: cannot resolve hostname:', server)
s = None resolver = None
except: except:
pass pass
else: else:
s = server resolver = server
if not s: if not resolver:
continue continue
try: try:
(s, r_avg, r_min, r_max, r_stddev, r_lost_percent, flags, ttl, answers) = dnsping(hostname, s, (resolver, r_avg, r_min, r_max, r_stddev, r_lost_percent, flags, ttl, answers) = dnsping(
dnsrecord, hostname,
waittime, resolver,
count, dnsrecord,
use_tcp=use_tcp, waittime,
use_edns=use_edns) count,
use_tcp=use_tcp,
use_edns=use_edns,
force_miss=force_miss
)
except dns.resolver.NXDOMAIN: except dns.resolver.NXDOMAIN:
print('%-15s NXDOMAIN' % server) print('%-15s NXDOMAIN' % server)
continue continue
@ -303,7 +341,7 @@ def main():
print('%s: %s' % (server, e)) print('%s: %s' % (server, e))
continue continue
s = server.ljust(width + 1) resolver = server.ljust(width + 1)
text_flags = flags_to_text(flags) text_flags = flags_to_text(flags)
s_ttl = str(ttl) s_ttl = str(ttl)
@ -315,11 +353,12 @@ def main():
else: else:
l_color = color.N l_color = color.N
print("%s %-8.3f %-8.3f %-8.3f %-8.3f %s%%%-3d%s %-8s %21s" % ( print("%s %-8.3f %-8.3f %-8.3f %-8.3f %s%%%-3d%s %-8s %21s" % (
s, r_avg, r_min, r_max, r_stddev, l_color, r_lost_percent, color.N, s_ttl, text_flags), flush=True) resolver, r_avg, r_min, r_max, r_stddev, l_color, r_lost_percent, color.N, s_ttl, text_flags),
flush=True)
if verbose and hasattr(answers, 'response'): if verbose and hasattr(answers, 'response'):
ans_index = 1 ans_index = 1
for answer in answers.response.answer: for answer in answers.response.answer:
print("Answer %d [ %s%s%s ]" % (ans_index, color.B, answer, color.N)) print("Answer %d [ %s%s%s ]" % (ans_index, color.G, answer, color.N))
ans_index += 1 ans_index += 1
print("") print("")

View File

@ -40,7 +40,7 @@ import dns.resolver
__author__ = 'Babak Farrokhi (babak@farrokhi.net)' __author__ = 'Babak Farrokhi (babak@farrokhi.net)'
__license__ = 'BSD' __license__ = 'BSD'
__version__ = "1.6.0" __version__ = "1.6.4"
__progname__ = os.path.basename(sys.argv[0]) __progname__ = os.path.basename(sys.argv[0])
shutdown = False shutdown = False
@ -60,7 +60,7 @@ usage: %s [-ehqv] [-s server] [-p port] [-P port] [-S address] [-c count] [-t ty
-S --srcip Query source IP address (default: default interface address) -S --srcip Query source IP address (default: default interface address)
-c --count Number of requests to send (default: 10) -c --count Number of requests to send (default: 10)
-w --wait Maximum wait time for a reply (default: 2 seconds) -w --wait Maximum wait time for a reply (default: 2 seconds)
-i --interval Time between each request (default: 0 seconds) -i --interval Time between each request (default: 1 seconds)
-t --type DNS request record type (default: A) -t --type DNS request record type (default: A)
-e --edns Disable EDNS0 (default: Enabled) -e --edns Disable EDNS0 (default: Enabled)
""" % (__progname__, __version__, __progname__)) """ % (__progname__, __version__, __progname__))
@ -88,7 +88,7 @@ def main():
dnsrecord = 'A' dnsrecord = 'A'
count = 10 count = 10
timeout = 2 timeout = 2
interval = 0 interval = 1
quiet = False quiet = False
verbose = False verbose = False
dnsserver = dns.resolver.get_default_resolver().nameservers[0] dnsserver = dns.resolver.get_default_resolver().nameservers[0]
@ -205,7 +205,7 @@ def main():
print("No answer") print("No answer")
pass pass
else: else:
elapsed = (etime - stime) * 1000 # convert to milliseconds elapsed = answers.response.time * 1000 # convert to milliseconds
response_time.append(elapsed) response_time.append(elapsed)
if not quiet: if not quiet:
print( print(

View File

@ -39,13 +39,20 @@ import dns.query
import dns.rdatatype import dns.rdatatype
import dns.resolver import dns.resolver
from cymruwhois import cymruwhois import cymruwhois
# Global Variables
__author__ = 'Babak Farrokhi (babak@farrokhi.net)' __author__ = 'Babak Farrokhi (babak@farrokhi.net)'
__license__ = 'BSD' __license__ = 'BSD'
__version__ = "1.6.0" __version__ = "1.6.4"
_ttl = None _ttl = None
quiet = False quiet = False
whois_cache = {}
shutdown = False
# Constants
__progname__ = os.path.basename(sys.argv[0])
WHOIS_CACHE = 'whois.cache'
class CustomSocket(socket.socket): class CustomSocket(socket.socket):
@ -64,11 +71,6 @@ def test_import():
pass pass
# Constants
__progname__ = os.path.basename(sys.argv[0])
WHOIS_CACHE = 'whois.cache'
class Colors(object): class Colors(object):
N = '\033[m' # native N = '\033[m' # native
R = '\033[31m' # red R = '\033[31m' # red
@ -85,35 +87,41 @@ class Colors(object):
self.B = '' self.B = ''
# Globarl Variables def whois_lookup(ip):
shutdown = False
def whoisrecord(ip):
try: try:
currenttime = time.perf_counter() global whois_cache
currenttime = time.time()
ts = currenttime ts = currenttime
if ip in whois: if ip in whois_cache:
asn, ts = whois[ip] asn, ts = whois_cache[ip]
else: else:
ts = 0 ts = 0
if (currenttime - ts) > 36000: if (currenttime - ts) > 36000:
c = cymruwhois.Client() c = cymruwhois.Client()
asn = c.lookup(ip) asn = c.lookup(ip)
whois[ip] = (asn, currenttime) whois_cache[ip] = (asn, currenttime)
return asn return asn
except Exception as e: except Exception as e:
return e return e
try: def load_whois_cache(cachefile):
pkl_file = open(WHOIS_CACHE, 'rb')
try: try:
whois = pickle.load(pkl_file) pkl_file = open(cachefile, 'rb')
except EOFError: try:
whois = pickle.load(pkl_file)
pkl_file.close()
except Exception:
whois = {}
except IOError:
whois = {} whois = {}
except IOError: return whois
whois = {}
def save_whois_cache(cachefile, whois_data):
pkl_file = open(cachefile, 'wb')
pickle.dump(whois_data, pkl_file)
pkl_file.close()
def usage(): def usage():
@ -125,6 +133,7 @@ def usage():
print(' -a --asn Turn on AS# lookups for each hop encountered') print(' -a --asn Turn on AS# lookups for each hop encountered')
print(' -s --server DNS server to use (default: first system resolver)') print(' -s --server DNS server to use (default: first system resolver)')
print(' -p --port DNS server port number (default: 53)') print(' -p --port DNS server port number (default: 53)')
print(' -S --srcip Query source IP address (default: default interface address)')
print(' -c --count Maximum number of hops (default: 30)') print(' -c --count Maximum number of hops (default: 30)')
print(' -w --wait Maximum wait time for a reply (default: 2)') print(' -w --wait Maximum wait time for a reply (default: 2)')
print(' -t --type DNS request record type (default: A)') print(' -t --type DNS request record type (default: A)')
@ -174,7 +183,7 @@ def expert_report(trace_path, color_mode):
print(" %s[*]%s No expert hint available for this trace" % (color.G, color.N)) print(" %s[*]%s No expert hint available for this trace" % (color.G, color.N))
def ping(resolver, hostname, dnsrecord, ttl, use_edns=False): def ping(resolver, hostname, dnsrecord, ttl, src_ip, use_edns=False):
global _ttl global _ttl
reached = False reached = False
@ -185,7 +194,7 @@ def ping(resolver, hostname, dnsrecord, ttl, use_edns=False):
resolver.use_edns(edns=0, payload=8192, ednsflags=dns.flags.edns_from_text('DO')) resolver.use_edns(edns=0, payload=8192, ednsflags=dns.flags.edns_from_text('DO'))
try: try:
resolver.query(hostname, dnsrecord, raise_on_no_answer=False) resolver.query(hostname, dnsrecord, source=src_ip, raise_on_no_answer=False)
except dns.resolver.NoNameservers as e: except dns.resolver.NoNameservers as e:
if not quiet: if not quiet:
@ -229,6 +238,7 @@ def main():
timeout = 2 timeout = 2
dnsserver = dns.resolver.get_default_resolver().nameservers[0] dnsserver = dns.resolver.get_default_resolver().nameservers[0]
dest_port = 53 dest_port = 53
src_ip = None
hops = 0 hops = 0
as_lookup = False as_lookup = False
expert_mode = False expert_mode = False
@ -237,9 +247,9 @@ def main():
color_mode = False color_mode = False
try: try:
opts, args = getopt.getopt(sys.argv[1:], "aqhc:s:t:w:p:nexC", opts, args = getopt.getopt(sys.argv[1:], "aqhc:s:S:t:w:p:nexC",
["help", "count=", "server=", "quiet", "type=", "wait=", "asn", "port", "expert", ["help", "count=", "server=", "quiet", "type=", "wait=", "asn", "port", "expert",
"color"]) "color", "srcip="])
except getopt.GetoptError as err: except getopt.GetoptError as err:
# print help information and exit: # print help information and exit:
print(err) # will print something like "option -a not recognized" print(err) # will print something like "option -a not recognized"
@ -261,6 +271,8 @@ def main():
dnsserver = a dnsserver = a
elif o in ("-q", "--quiet"): elif o in ("-q", "--quiet"):
quiet = True quiet = True
elif o in ("-S", "--srcip"):
src_ip = a
elif o in ("-w", "--wait"): elif o in ("-w", "--wait"):
timeout = int(a) timeout = int(a)
elif o in ("-t", "--type"): elif o in ("-t", "--type"):
@ -293,6 +305,7 @@ def main():
resolver = dns.resolver.Resolver() resolver = dns.resolver.Resolver()
resolver.nameservers = [dnsserver] resolver.nameservers = [dnsserver]
resolver.timeout = timeout resolver.timeout = timeout
resolver.port = dest_port
resolver.lifetime = timeout resolver.lifetime = timeout
resolver.retry_servfail = 0 resolver.retry_servfail = 0
@ -329,7 +342,7 @@ def main():
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool: # dispatch dns lookup to another thread with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool: # dispatch dns lookup to another thread
stime = time.perf_counter() stime = time.perf_counter()
thr = pool.submit(ping, resolver, hostname, dnsrecord, ttl, use_edns=use_edns) thr = pool.submit(ping, resolver, hostname, dnsrecord, ttl, src_ip=src_ip, use_edns=use_edns)
try: # expect ICMP response try: # expect ICMP response
_, curr_addr = icmp_socket.recvfrom(512) _, curr_addr = icmp_socket.recvfrom(512)
@ -345,8 +358,8 @@ def main():
if reached: if reached:
curr_addr = dnsserver curr_addr = dnsserver
stime = time.perf_counter() # need to recalculate elapsed time for last hop without waiting for an icmp error reply stime = time.perf_counter() # need to recalculate elapsed time for last hop asynchronously
ping(resolver, hostname, dnsrecord, ttl, use_edns=use_edns) ping(resolver, hostname, dnsrecord, ttl, src_ip=src_ip, use_edns=use_edns)
etime = time.perf_counter() etime = time.perf_counter()
elapsed = abs(etime - stime) * 1000 # convert to milliseconds elapsed = abs(etime - stime) * 1000 # convert to milliseconds
@ -367,11 +380,11 @@ def main():
if curr_addr: if curr_addr:
as_name = "" as_name = ""
if as_lookup: if as_lookup:
asn = whoisrecord(curr_addr) asn = whois_lookup(curr_addr)
as_name = '' as_name = ''
try: try:
if asn and asn.asn != "NA": if asn and asn.asn != "NA":
as_name = "[%s %s] " % (asn.asn, asn.owner) as_name = "[AS%s %s] " % (asn.asn, asn.owner)
except AttributeError: except AttributeError:
if shutdown: if shutdown:
sys.exit(0) sys.exit(0)
@ -379,13 +392,16 @@ def main():
c = color.N # default c = color.N # default
if curr_addr != '*': if curr_addr != '*':
IP = ipaddress.ip_address(curr_addr) try:
if IP.is_private: IP = ipaddress.ip_address(curr_addr)
c = color.R if IP.is_private:
if IP.is_reserved: c = color.R
c = color.B if IP.is_reserved:
if curr_addr == dnsserver: c = color.B
c = color.G if curr_addr == dnsserver:
c = color.G
except:
pass
print("%d\t%s (%s%s%s) %s%.3f ms" % (ttl, curr_name, c, curr_addr, color.N, as_name, elapsed), flush=True) print("%d\t%s (%s%s%s) %s%.3f ms" % (ttl, curr_name, c, curr_addr, color.N, as_name, elapsed), flush=True)
trace_path.append(curr_addr) trace_path.append(curr_addr)
@ -404,7 +420,7 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
try: try:
whois_cache = load_whois_cache(WHOIS_CACHE)
main() main()
finally: finally:
pkl_file = open(WHOIS_CACHE, 'wb') save_whois_cache(WHOIS_CACHE, whois_cache)
pickle.dump(whois, pkl_file)

View File

@ -2,6 +2,12 @@
8.8.4.4 8.8.4.4
2001:4860:4860::8888 2001:4860:4860::8888
2001:4860:4860::8844 2001:4860:4860::8844
9.9.9.9
2620:fe::fe
1.1.1.1
1.0.0.1
2606:4700:4700::1111
2606:4700:4700::1001
4.2.2.1 4.2.2.1
4.2.2.2 4.2.2.2
4.2.2.3 4.2.2.3
@ -13,3 +19,7 @@
195.46.39.40 195.46.39.40
216.146.35.35 216.146.35.35
216.146.36.36 216.146.36.36
208.67.222.222
208.67.220.220
2620:0:ccc::2
2620:0:ccd::2

18
public-v4.txt Normal file
View File

@ -0,0 +1,18 @@
8.8.8.8
8.8.4.4
9.9.9.9
1.1.1.1
1.0.0.1
4.2.2.1
4.2.2.2
4.2.2.3
4.2.2.4
4.2.2.5
209.244.0.3
209.244.0.4
195.46.39.39
195.46.39.40
216.146.35.35
216.146.36.36
208.67.222.222
208.67.220.220

View File

@ -1 +1,2 @@
dnspython==1.15.0 dnspython>=1.15.0
cymruwhois>=1.6

View File

@ -2,8 +2,11 @@ from setuptools import setup, find_packages
setup( setup(
name="dnsdiag", name="dnsdiag",
version="1.6.0", version="1.6.4",
packages=find_packages(), packages=find_packages(),
scripts=["dnseval.py", "dnsping.py", "dnstraceroute.py"],
install_requires=['dnspython>=1.15.0', 'cymruwhois>=1.6'],
classifiers=[ classifiers=[
"Topic :: System :: Networking", "Topic :: System :: Networking",
"Environment :: Console", "Environment :: Console",