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.
This commit is contained in:
parent
8283f4dbc2
commit
8a9acd9100
81
dnseval.py
81
dnseval.py
@ -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
|
||||||
@ -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,12 +165,25 @@ 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:
|
||||||
answers = resolver.query(host, dnsrecord, tcp=use_tcp,
|
if force_miss:
|
||||||
|
fqdn = "_dnseval_%s_.%s" % (random_string(), host)
|
||||||
|
print(fqdn)
|
||||||
|
else:
|
||||||
|
fqdn = host
|
||||||
|
|
||||||
|
stime = time.perf_counter()
|
||||||
|
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
|
||||||
|
|
||||||
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 = answers.response.time * 1000 # convert to milliseconds
|
elapsed = answers.response.time * 1000 # convert to milliseconds
|
||||||
response_times.append(elapsed)
|
response_times.append(elapsed)
|
||||||
@ -210,13 +232,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()
|
||||||
@ -236,6 +260,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"):
|
||||||
@ -282,25 +308,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
|
||||||
@ -308,7 +338,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)
|
||||||
@ -320,7 +350,8 @@ 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:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user