Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
DNS testing tools
Remoh
Commits
7859e494
Commit
7859e494
authored
Jun 04, 2020
by
Alexandre
Browse files
Merge branch 'master' into pipelining
parents
2f4ade58
63d193fa
Changes
3
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
7859e494
...
@@ -164,14 +164,13 @@ and [CURLINFO_PRETRANSFER_TIME](https://curl.haxx.se/libcurl/c/curl_easy_getinfo
...
@@ -164,14 +164,13 @@ and [CURLINFO_PRETRANSFER_TIME](https://curl.haxx.se/libcurl/c/curl_easy_getinfo
```
```
% ./homer.py --multistreams --file input_file --repeat 5 --no-display-results --time https://doh.powerdns.org
% ./homer.py --multistreams --file input_file --repeat 5 --no-display-results --time https://doh.powerdns.org
0
36.16
5 ms
44.773
ms
8.608
ms
0
(200) 41.99
5 ms
51.409
ms
9.414
ms
1 0.1
42
ms 8.
580
ms 8.4
38
ms
1
(200)
0.1
56
ms 8.
648
ms 8.4
92
ms
3
0.095
ms
9.223
ms
9.128
ms
2
(200) 0.121
ms
8.494
ms
8.373
ms
2
0.10
3
ms 1
0.282
ms 1
0.179
ms
3 (200)
0.1
2
0 ms 1
1.185
ms 1
1.065
ms
4 0.10
4
ms 1
0.068
ms
9.964
ms
4
(200)
0.10
3
ms 1
1.922
ms
11.819
ms
Total elapsed time: 0.07 seconds (9.26 ms/request)
Total elapsed time: 0.07 seconds (9.83 ms/request)
OK
```
```
...
...
homer.py
View file @
7859e494
...
@@ -106,7 +106,51 @@ def error(msg=None, exit=True):
...
@@ -106,7 +106,51 @@ def error(msg=None, exit=True):
def
usage
(
msg
=
None
):
def
usage
(
msg
=
None
):
if
msg
:
if
msg
:
print
(
msg
,
file
=
sys
.
stderr
)
print
(
msg
,
file
=
sys
.
stderr
)
print
(
"Usage: %s [--dot] url-or-servername domain-name [DNS type]"
%
sys
.
argv
[
0
],
file
=
sys
.
stderr
)
print
(
"Usage: %s [options] url-or-servername [domain-name [DNS type]]"
%
sys
.
argv
[
0
],
file
=
sys
.
stderr
)
print
(
"""Options
-t --dot Use DoT (by default use DoH)
-P --post --POST Use HTTP POST method for all transfers (DoH only)
-e --head --HEAD Use HTTP HEAD method for all transfers (DoH only)
-r --repeat <N> Perform N times the query. If used with -f, read up to
<N> rows of the <file>.
-d --delay <T> Time to wait in seconds between each synchronous
request (only with --repeat)
-f --file <file> Read domain names from <file>, one per row with an
optional DNS type
--check Perform a set of predefined tests.
--mandatory-level <level>
Define the <level> of test to perform (only with
--check)
Available <level> : legal, necessary, nicetohave
--multistreams Use HTTP/2 streams, needs an input file with -f
(DoH only)
--sync Process received queries synchronously (only with
--multistreams)
--no-display-results
Disable output of DNS response (only with
--multistreams)
--time Display the time elapsed for the query (only with
--multistreams)
--dnssec Request DNSSEC data (signatures)
--noedns Disable EDNS, default is to indicate EDNS support
--ecs Send ECS to authoritative servers, default is to
refuse it
--key <key> Authenticate a DoT resolver with its public <key> in
base64 (DoT only)
--nosni Do not perform SNI (DoT only)
-V --vhost <vhost> Use a specific virtual host
-k --insecure Do not check the certificate
-4 --v4only Force IPv4 resolution of url-or-servername
-6 --v6only Force IPv6 resolution of url-or-servername
-v --verbose Make the program more talkative
--debug Make the program even more talkative than -v
-h --help Print this message
url-or-servername The URL or domain name of the DoT/DoH server
domain-name The domain name to resolve, not required if -f is
provided
DNS type The DNS record type to resolve, default AAAA
"""
,
file
=
sys
.
stderr
)
print
(
"See the README.md for more details."
,
file
=
sys
.
stderr
)
print
(
"See the README.md for more details."
,
file
=
sys
.
stderr
)
def
is_valid_hostname
(
name
):
def
is_valid_hostname
(
name
):
...
@@ -244,6 +288,7 @@ class Request:
...
@@ -244,6 +288,7 @@ class Request:
use_edns
=
use_edns
,
want_dnssec
=
want_dnssec
,
options
=
options
)
use_edns
=
use_edns
,
want_dnssec
=
want_dnssec
,
options
=
options
)
self
.
message
.
flags
|=
dns
.
flags
.
AD
# Ask for validation
self
.
message
.
flags
|=
dns
.
flags
.
AD
# Ask for validation
self
.
ok
=
True
self
.
ok
=
True
self
.
i
=
0
# request's number on the connection (default to the first)
def
trunc_data
(
self
):
def
trunc_data
(
self
):
self
.
data
=
self
.
message
.
to_wire
()
self
.
data
=
self
.
message
.
to_wire
()
...
@@ -677,10 +722,11 @@ class ConnectionDoH(Connection):
...
@@ -677,10 +722,11 @@ class ConnectionDoH(Connection):
self
.
receive
(
handle
)
self
.
receive
(
handle
)
handle
.
request
.
check_response
()
handle
.
request
.
check_response
()
if
show_time
:
if
show_time
:
print
(
f
'
{
handle
.
request
.
i
:
3
d
}
'
,
end
=
' '
)
self
.
print_time
(
handle
)
print
(
f
'
{
handle
.
pretime
*
1000
:
8.3
f
}
ms'
,
end
=
' '
)
try
:
print
(
f
'
{
handle
.
time
*
1000
:
8.3
f
}
ms'
,
end
=
' '
)
self
.
finished
[
'http'
][
handle
.
request
.
rcode
]
+=
1
print
(
f
'
{
(
handle
.
time
-
handle
.
pretime
)
*
1000
:
8.3
f
}
ms'
)
except
KeyError
:
self
.
finished
[
'http'
][
handle
.
request
.
rcode
]
=
1
if
display_results
:
if
display_results
:
print
(
"Return code %s (%.2f ms):"
%
(
handle
.
request
.
rcode
,
print
(
"Return code %s (%.2f ms):"
%
(
handle
.
request
.
rcode
,
(
handle
.
time
-
handle
.
pretime
)
*
1000
))
(
handle
.
time
-
handle
.
pretime
)
*
1000
))
...
@@ -692,6 +738,13 @@ class ConnectionDoH(Connection):
...
@@ -692,6 +738,13 @@ class ConnectionDoH(Connection):
for
handle
in
self
.
all_handles
:
for
handle
in
self
.
all_handles
:
self
.
read_result_handle
(
handle
)
self
.
read_result_handle
(
handle
)
def
print_time
(
self
,
handle
):
print
(
f
'
{
handle
.
request
.
i
:
3
d
}
'
,
end
=
' '
)
print
(
f
'(
{
handle
.
request
.
rcode
}
)'
,
end
=
' '
)
print
(
f
'
{
handle
.
pretime
*
1000
:
8.3
f
}
ms'
,
end
=
' '
)
print
(
f
'
{
handle
.
time
*
1000
:
8.3
f
}
ms'
,
end
=
' '
)
print
(
f
'
{
(
handle
.
time
-
handle
.
pretime
)
*
1000
:
8.3
f
}
ms'
)
def
do_test
(
self
,
request
,
synchronous
=
True
):
def
do_test
(
self
,
request
,
synchronous
=
True
):
if
synchronous
:
if
synchronous
:
handle
=
self
.
curl_handle
handle
=
self
.
curl_handle
...
@@ -727,6 +780,8 @@ def print_result(connection, request, prefix=None, display_err=True):
...
@@ -727,6 +780,8 @@ def print_result(connection, request, prefix=None, display_err=True):
size
=
request
.
response_size
size
=
request
.
response_size
if
(
dot
and
rcode
)
or
(
not
dot
and
rcode
==
200
):
if
(
dot
and
rcode
)
or
(
not
dot
and
rcode
==
200
):
if
not
monitoring
:
if
not
monitoring
:
if
not
dot
and
show_time
:
connection
.
print_time
(
connection
.
curl_handle
)
if
display_results
and
(
not
check
or
verbose
):
if
display_results
and
(
not
check
or
verbose
):
print
(
msg
)
print
(
msg
)
else
:
else
:
...
@@ -938,9 +993,9 @@ if not monitoring:
...
@@ -938,9 +993,9 @@ if not monitoring:
try
:
try
:
optlist
,
args
=
getopt
.
getopt
(
sys
.
argv
[
1
:],
"hvPkeV:r:f:d:t46"
,
optlist
,
args
=
getopt
.
getopt
(
sys
.
argv
[
1
:],
"hvPkeV:r:f:d:t46"
,
[
"help"
,
"verbose"
,
"debug"
,
"dot"
,
[
"help"
,
"verbose"
,
"debug"
,
"dot"
,
"head"
,
"
POST"
,
"insecure"
,
"key=
"
,
"head"
,
"
HEAD"
,
"post"
,
"POST
"
,
"vhost="
,
"multistreams"
,
"insecure"
,
"vhost="
,
"multistreams"
,
"pipelining"
,
"max-in-flight="
,
"pipelining"
,
"max-in-flight="
,
"key="
,
"dnssec"
,
"noedns"
,
"ecs"
,
"nosni"
,
"dnssec"
,
"noedns"
,
"ecs"
,
"nosni"
,
"sync"
,
"no-display-results"
,
"time"
,
"sync"
,
"no-display-results"
,
"time"
,
"file="
,
"repeat="
,
"delay="
,
"file="
,
"repeat="
,
"delay="
,
...
@@ -1017,9 +1072,11 @@ if not monitoring:
...
@@ -1017,9 +1072,11 @@ if not monitoring:
mandatory_level
=
value
mandatory_level
=
value
else
:
else
:
error
(
"Unknown option %s"
%
option
)
error
(
"Unknown option %s"
%
option
)
except
getopt
.
error
as
reason
:
except
(
getopt
.
error
,
ValueError
)
as
reason
:
usage
(
reason
)
usage
(
reason
)
sys
.
exit
(
1
)
sys
.
exit
(
1
)
if
delay
is
not
None
and
multistreams
:
error
(
"--delay makes no sense with multistreams"
)
if
tests
<=
1
and
delay
is
not
None
:
if
tests
<=
1
and
delay
is
not
None
:
error
(
"--delay makes no sense if there is no repetition"
)
error
(
"--delay makes no sense if there is no repetition"
)
if
not
dot
and
pipelining
:
if
not
dot
and
pipelining
:
...
@@ -1046,8 +1103,8 @@ if not monitoring:
...
@@ -1046,8 +1103,8 @@ if not monitoring:
if
sync
and
not
multistreams
:
if
sync
and
not
multistreams
:
usage
(
"--sync cannot be used without --multistreams"
)
usage
(
"--sync cannot be used without --multistreams"
)
sys
.
exit
(
1
)
sys
.
exit
(
1
)
if
show_time
and
n
ot
multistreams
:
if
show_time
and
d
ot
:
usage
(
"--time cannot be used with
out --multistreams
"
)
usage
(
"--time cannot be used with
--dot
"
)
sys
.
exit
(
1
)
sys
.
exit
(
1
)
if
not
edns
and
not
no_ecs
:
if
not
edns
and
not
no_ecs
:
usage
(
"ECS requires EDNS"
)
usage
(
"ECS requires EDNS"
)
...
@@ -1124,9 +1181,6 @@ else: # Monitoring plugin
...
@@ -1124,9 +1181,6 @@ else: # Monitoring plugin
if
dot
and
(
post
or
head
):
if
dot
and
(
post
or
head
):
print
(
"POST or HEAD makes no sense for DoT"
)
print
(
"POST or HEAD makes no sense for DoT"
)
sys
.
exit
(
STATE_UNKNOWN
)
sys
.
exit
(
STATE_UNKNOWN
)
if
dot
and
multistreams
:
print
(
"Multi-streams makes no sense for DoT"
)
sys
.
exit
(
STATE_UNKNOWN
)
if
dot
and
path
:
if
dot
and
path
:
print
(
"URL path makes no sense for DoT"
)
print
(
"URL path makes no sense for DoT"
)
sys
.
exit
(
STATE_UNKNOWN
)
sys
.
exit
(
STATE_UNKNOWN
)
...
@@ -1208,6 +1262,8 @@ for connectTo in ip_set:
...
@@ -1208,6 +1262,8 @@ for connectTo in ip_set:
if
ifile
is
not
None
:
if
ifile
is
not
None
:
input
=
open
(
ifile
)
input
=
open
(
ifile
)
if
not
check
:
if
not
check
:
if
multistreams
:
conn
.
finished
=
{
'http'
:
{}
}
for
i
in
range
(
0
,
tests
):
for
i
in
range
(
0
,
tests
):
if
tests
>
1
and
(
verbose
or
display_results
):
if
tests
>
1
and
(
verbose
or
display_results
):
print
(
"
\n
Test %i"
%
i
)
print
(
"
\n
Test %i"
%
i
)
...
@@ -1281,18 +1337,17 @@ for connectTo in ip_set:
...
@@ -1281,18 +1337,17 @@ for connectTo in ip_set:
else
:
else
:
time_per_request
=
time_tot
/
tests
*
1000
time_per_request
=
time_tot
/
tests
*
1000
print
(
"
\n
Total elapsed time: %.2f seconds (%.2f ms/request%s)"
%
(
time_tot
,
time_per_request
,
extra
))
print
(
"
\n
Total elapsed time: %.2f seconds (%.2f ms/request%s)"
%
(
time_tot
,
time_per_request
,
extra
))
if
multistreams
and
verbose
:
for
rcode
,
n
in
conn
.
finished
[
'http'
].
items
():
print
(
'HTTP'
,
rcode
,
':'
,
n
,
f
'(
{
n
/
tests
*
100
:
0.2
f
}
%)'
)
if
ifile
is
not
None
:
if
ifile
is
not
None
:
input
.
close
()
input
.
close
()
conn
.
end
()
conn
.
end
()
if
ok
:
if
ok
:
print
(
'OK'
)
if
check
:
if
not
monitoring
:
print
(
'OK'
)
sys
.
exit
(
0
)
sys
.
exit
(
0
)
else
:
sys
.
exit
(
STATE_OK
)
else
:
else
:
print
(
'KO'
)
print
(
'KO'
)
if
not
monitoring
:
sys
.
exit
(
1
)
sys
.
exit
(
1
)
else
:
sys
.
exit
(
STATE_CRITICAL
)
tests.yaml
View file @
7859e494
...
@@ -19,14 +19,14 @@ tests:
...
@@ -19,14 +19,14 @@ tests:
args
:
args
:
-
'
-h'
-
'
-h'
retcode
:
0
retcode
:
0
partstderr
:
'
url-or-servername
domain-name
[DNS
type]'
partstderr
:
'
url-or-servername
[
domain-name
[DNS
type]
]
'
stdout
:
'
'
stdout
:
'
'
-
exe
:
'
./homer.py'
-
exe
:
'
./homer.py'
args
:
args
:
-
'
--zzz'
-
'
--zzz'
retcode
:
1
retcode
:
1
partstderr
:
'
option
--zzz
not
recognized
'
partstderr
:
'
url-or-servername
[domain-name
[DNS
type]]
'
stdout
:
'
'
stdout
:
'
'
-
exe
:
'
./homer.py'
-
exe
:
'
./homer.py'
...
@@ -132,7 +132,7 @@ tests:
...
@@ -132,7 +132,7 @@ tests:
-
'
check'
-
'
check'
-
'
fail'
-
'
fail'
-
'
slow'
-
'
slow'
timeout
:
1
0
timeout
:
1
2
args
:
args
:
-
'
--check'
-
'
--check'
-
'
https://doh.42l.fr/dns-query'
-
'
https://doh.42l.fr/dns-query'
...
@@ -991,7 +991,19 @@ tests:
...
@@ -991,7 +991,19 @@ tests:
stdout
:
'
'
stdout
:
'
'
-
exe
:
'
./homer.py'
-
exe
:
'
./homer.py'
name
:
'
[doh]
POST'
name
:
'
[doh]
POST
--post'
markers
:
-
'
doh'
args
:
-
'
--post'
-
'
https://doh.bortzmeyer.fr'
-
'
framagit.org'
retcode
:
0
stderr
:
'
'
partstdout
:
'
2a01:4f8:'
-
exe
:
'
./homer.py'
name
:
'
[doh]
POST
--POST'
markers
:
markers
:
-
'
doh'
-
'
doh'
args
:
args
:
...
@@ -1003,7 +1015,19 @@ tests:
...
@@ -1003,7 +1015,19 @@ tests:
partstdout
:
'
2a01:4f8:'
partstdout
:
'
2a01:4f8:'
-
exe
:
'
./homer.py'
-
exe
:
'
./homer.py'
name
:
'
[doh]
HEAD'
name
:
'
[doh]
POST
-P'
markers
:
-
'
doh'
args
:
-
'
-P'
-
'
https://doh.bortzmeyer.fr'
-
'
framagit.org'
retcode
:
0
stderr
:
'
'
partstdout
:
'
2a01:4f8:'
-
exe
:
'
./homer.py'
name
:
'
[doh]
HEAD
--head'
markers
:
markers
:
-
'
doh'
-
'
doh'
args
:
args
:
...
@@ -1014,6 +1038,30 @@ tests:
...
@@ -1014,6 +1038,30 @@ tests:
stderr
:
'
'
stderr
:
'
'
partstdout
:
'
HEAD'
partstdout
:
'
HEAD'
-
exe
:
'
./homer.py'
name
:
'
[doh]
HEAD
--HEAD'
markers
:
-
'
doh'
args
:
-
'
--HEAD'
-
'
https://doh.bortzmeyer.fr'
-
'
framagit.org'
retcode
:
0
stderr
:
'
'
partstdout
:
'
HEAD'
-
exe
:
'
./homer.py'
name
:
'
[doh]
HEAD
-e'
markers
:
-
'
doh'
args
:
-
'
-e'
-
'
https://doh.bortzmeyer.fr'
-
'
framagit.org'
retcode
:
0
stderr
:
'
'
partstdout
:
'
HEAD'
-
exe
:
'
./homer.py'
-
exe
:
'
./homer.py'
name
:
'
[doh]
Multistreams
with
DoT
(error)'
name
:
'
[doh]
Multistreams
with
DoT
(error)'
markers
:
markers
:
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment