Commit 4491ef39 authored by Alexandre's avatar Alexandre
Browse files

Loop on all IPs. Addresses #9, #21 and #24

parent d33fd3b4
......@@ -309,7 +309,11 @@ class ConnectionDoT(Connection):
Connection.__init__(self, server, servername=servername, connect=connect,
forceIPv4=forceIPv4, forceIPv6=forceIPv6, dot=True,
verbose=verbose, insecure=insecure)
self.check_ip_address(self.server)
if connect is not None:
addr = connect
else:
addr = self.server
self.check_ip_address(addr)
addrinfo_list = socket.getaddrinfo(self.server, 853, self.family)
addrinfo_set = { (addrinfo[4], addrinfo[0]) for addrinfo in addrinfo_list }
signal.signal(signal.SIGALRM, timeout_connection)
......@@ -688,6 +692,14 @@ def run_check(connection):
return False
return True
def resolved_ips(host, port, family, dot=dot):
try:
addr_list = socket.getaddrinfo(host, port, family)
except socket.gaierror:
error(f'Could not resolve "{url}"')
ip_set = { addr[4][0] for addr in addr_list }
return ip_set
# Main program
me = os.path.basename(sys.argv[0])
monitoring = (me == "check_doh" or me == "check_dot")
......@@ -836,63 +848,91 @@ else: # Monitoring plugin
path = path[1:]
url += path
# retrieve all ips when using --check
# not necessary if connectTo is already defined
# as it is the case with --monitoring
if not check or connectTo is not None:
ip_set = {connectTo, }
else:
if dot:
port = 853
if not is_valid_hostname(url):
error("DoT requires a host name or IP address, not \"%s\"" % url)
netloc = url
else:
port = 443
if not is_valid_url(url):
error("DoH requires a valid HTTPS URL, not \"%s\"" % url)
url_parts = urllib.parse.urlparse(url)
netloc = url_parts.netloc
if forceIPv4:
family = socket.AF_INET
elif forceIPv6:
family = socket.AF_INET6
else:
family = 0
ip_set = resolved_ips(netloc, port, family, dot)
ok = True
start = time.time()
try:
for connectTo in ip_set:
start = time.time()
if dot and vhostname is not None:
extracheck = vhostname
else:
extracheck = None
if dot:
conn = ConnectionDoT(url, servername=extracheck, connect=connectTo, verbose=verbose,
forceIPv4=forceIPv4, forceIPv6=forceIPv6,
insecure=insecure)
if verbose and check and connectTo:
print(f'Checking "{url}" on {connectTo} ...')
try:
if dot:
conn = ConnectionDoT(url, servername=extracheck, connect=connectTo, verbose=verbose,
forceIPv4=forceIPv4, forceIPv6=forceIPv6,
insecure=insecure)
else:
conn = ConnectionDoH(url, servername=extracheck, connect=connectTo, verbose=verbose,
forceIPv4=forceIPv4, forceIPv6=forceIPv6,
insecure=insecure)
except TimeoutError:
error("timeout")
except ConnectionRefusedError:
error("Connection to server refused")
except ValueError:
error(f'"{url}" not a name or an IP address')
except socket.gaierror:
error(f'Could not resolve "{url}"')
except CustomException as e:
error(e)
if ifile is not None:
input = open(ifile)
if not check:
for i in range (0, tests):
if tests > 1:
print("\nTest %i" % i)
if ifile is not None:
name, rtype = get_next_domain(input)
try:
request = conn.do_test(name, rtype)
except (OpenSSL.SSL.Error, CustomException) as e:
ok = False
error(e)
break
if not print_result(conn, request):
ok = False
if tests > 1 and i == 0:
start2 = time.time()
if delay is not None:
time.sleep(delay)
else:
conn = ConnectionDoH(url, servername=extracheck, connect=connectTo, verbose=verbose,
forceIPv4=forceIPv4, forceIPv6=forceIPv6,
insecure=insecure)
except TimeoutError:
error("timeout")
except ConnectionRefusedError:
error("Connection to server refused")
except ValueError:
error(f'"{url}" not a name or an IP address')
except socket.gaierror:
error(f'Could not resolve "{url}"')
except CustomException as e:
error(e)
if ifile is not None:
input = open(ifile)
if not check:
for i in range (0, tests):
if tests > 1:
print("\nTest %i" % i)
if ifile is not None:
name, rtype = get_next_domain(input)
try:
request = conn.do_test(name, rtype)
except (OpenSSL.SSL.Error, CustomException) as e:
ok = False
error(e)
break
if not print_result(conn, request):
ok = False
if tests > 1 and i == 0:
start2 = time.time()
if delay is not None:
time.sleep(delay)
else:
ok = run_check(conn)
stop = time.time()
if tests > 1:
extra = ", %.2f ms/request if we ignore the first one" % ((stop-start2)*1000/(tests-1))
else:
extra = ""
if not monitoring and (not check or verbose):
print("\nTotal elapsed time: %.2f seconds (%.2f ms/request %s)" % (stop-start, (stop-start)*1000/tests, extra))
if ifile is not None:
input.close()
conn.end()
ok = run_check(conn)
stop = time.time()
if tests > 1:
extra = ", %.2f ms/request if we ignore the first one" % ((stop-start2)*1000/(tests-1))
else:
extra = ""
if not monitoring and (not check or verbose):
print("\nTotal elapsed time: %.2f seconds (%.2f ms/request %s)" % (stop-start, (stop-start)*1000/tests, extra))
if ifile is not None:
input.close()
conn.end()
if ok:
print('OK')
if not monitoring:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment