Commit 0f2c36c1 authored by Alexandre's avatar Alexandre
Browse files

[monitoring] Fix error if the host is an IP + code clean-up

parent 3f75d576
......@@ -31,8 +31,24 @@ except ImportError as e:
import homer
# Values that can be changed from the command line
# "H:n:p:V:t:e:Pih46k:x"
# Options
# -H <host> IP address or domain name of the server (necessary). If using
# DoH, the url will be built as https://<host>/<path>
# -n <name> The domain name to resolve (necessary)
# -V <vhost> The virtual hostname to use
# -t <rtype> The DNS record type to resolve, default AAAA
# -e <value> expect (looks for expected string in output)
# -p <path> [DoH] URL path of the DoH service
# -P [DoH] Use HTTP POST method
# -h [DoH] Use HTTP HEAD method
# -i Do not check the certificate
# -x Do not perform SNI
# -4 Force IPv4 resolution of url-or-servername
# -6 Force IPv6 resolution of url-or-servername
# -k <key> [DoT] Authenticate a DoT resolver with its public <key> in
# base64
class opts:
#"H:n:p:V:t:e:Pih46k:x"
dot = False # DoH by default
dnssec = False
edns = True
......@@ -74,31 +90,20 @@ def print_result(connection, request, prefix=None, display_err=True):
size = request.response_size
if (dot and rcode) or (not dot and rcode == 200):
if opts.expect is not None and opts.expect not in str(request.response):
ok = False
print("%s Cannot find \"%s\" in response" % (server, opts.expect))
sys.exit(STATE_CRITICAL)
ok = False
if ok and size is not None and size > 0:
print("%s OK - %s" % (server, "No error for %s/%s, %i bytes received" % (name, opts.rtype, size)))
else:
elif ok:
print("%s OK - %s" % (server, "No error"))
sys.exit(STATE_OK)
else:
if not dot:
print("%s HTTP error - %i: %s" % (server, rcode, msg))
else:
print("%s Error - %i: %s" % (server, rcode, msg))
sys.exit(STATE_CRITICAL)
ok = False
return ok
def resolved_ips(host, port, family, dot=False):
try:
addr_list = socket.getaddrinfo(host, port, family)
except socket.gaierror as e:
error("Could not resolve \"%s\" (%s)" % (host, e))
ip_set = { addr[4][0] for addr in addr_list }
return ip_set
def parse_opts_monitoring(me, opts):
name = None
opts.dot = (me == "check_dot")
......@@ -190,73 +195,43 @@ me = os.path.basename(sys.argv[0])
url, name = parse_opts_monitoring(me, opts)
# The provided host is indeed a valid IP
# TODO catch ValueError exception if the host is an url as in :
# ./check_doh -H https://doh.bortzmeyer.fr -n afnic.fr
if homer.is_valid_ip_address(opts.host)[0]:
opts.connectTo = opts.host
# retrieve all ips when using --check
# not necessary if connectTo is already defined
# as it is the case with --monitoring
if opts.connectTo is not None:
ip_set = {opts.connectTo, }
ok = True
if opts.dot and opts.vhostname is not None:
extracheck = opts.vhostname
else:
extracheck = None
try:
if opts.dot:
port = homer.PORT_DOT
if not homer.is_valid_hostname(url):
error("DoT requires a host name or IP address, not \"%s\"" % url)
netloc = url
else:
port = homer.PORT_DOH
if not homer.is_valid_url(url):
error("DoH requires a valid HTTPS URL, not \"%s\"" % url)
try:
url_parts = urllib.parse.urlparse(url) # A very poor validation, many
# errors (for instance whitespaces, IPv6 address litterals without
# brackets...) are ignored.
except ValueError:
error("The provided url \"%s\" could not be parsed" % url)
netloc = url_parts.netloc
if opts.forceIPv4:
family = socket.AF_INET
elif opts.forceIPv6:
family = socket.AF_INET6
conn = homer.ConnectionDOT(url, servername=extracheck, connect_to=opts.connectTo,
forceIPv4=opts.forceIPv4, forceIPv6=opts.forceIPv6,
insecure=opts.insecure,
sni=opts.sni, key=opts.key)
else:
family = 0
ip_set = resolved_ips(netloc, port, family, opts.dot)
ok = True
# todo no loop needed here when using monitoring plugin,
# we know where to connect to, we monitor one machine therefore the IP is known
for ip in ip_set:
if opts.dot and opts.vhostname is not None:
extracheck = opts.vhostname
else:
extracheck = None
try:
if opts.dot:
conn = homer.ConnectionDOT(url, servername=extracheck, connect_to=opts.connectTo,
forceIPv4=opts.forceIPv4, forceIPv6=opts.forceIPv6,
insecure=opts.insecure,
sni=opts.sni, key=opts.key)
else:
conn = homer.ConnectionDOH(url, servername=extracheck, connect_to=opts.connectTo,
forceIPv4=opts.forceIPv4, forceIPv6=opts.forceIPv6,
insecure=opts.insecure)
except TimeoutError:
error("timeout")
except ConnectionRefusedError:
error("Connection to server refused")
except ValueError:
error("\"%s\" not a name or an IP address" % url)
except socket.gaierror:
error("Could not resolve \"%s\"" % url)
except (homer.ConnectionException, homer.DOHException) as e:
error(e)
if conn.dot and not conn.success:
ok = False
continue
conn = homer.ConnectionDOH(url, servername=extracheck, connect_to=opts.connectTo,
forceIPv4=opts.forceIPv4, forceIPv6=opts.forceIPv6,
insecure=opts.insecure)
except TimeoutError:
error("timeout")
except ConnectionRefusedError:
error("Connection to server refused")
except ValueError:
error("\"%s\" not a name or an IP address" % url)
except socket.gaierror:
error("Could not resolve \"%s\"" % url)
except (homer.ConnectionException, homer.DOHException) as e:
error(e)
if conn.dot and not conn.success:
ok = False
else:
ok = run_default(name, conn, opts)
conn.end()
conn.end()
if ok:
sys.exit(STATE_OK)
......
Markdown is supported
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