Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change DNS lookup timeout handling #2192

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 19 additions & 7 deletions management/dns_update.py
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -1029,17 +1029,29 @@ def set_secondary_dns(hostnames, env):
resolver = dns.resolver.get_default_resolver()
resolver.timeout = 5
resolver.lifetime = 5

for item in hostnames:
if not item.startswith("xfr:"):
# Resolve hostname.
try:
resolver.resolve(item, "A")
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.resolver.Timeout):
tries = 2

while tries > 0:
tries = tries - 1
try:
resolver.resolve(item, "AAAA")
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, dns.resolver.Timeout):
raise ValueError("Could not resolve the IP address of %s." % item)
response = resolver.resolve(item, "A")
tries = 0
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
try:
response = resolver.resolve(item, "AAAA")
tries = 0
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
raise ValueError("Could not resolve the IP address of %s." % item)
except (dns.resolver.Timeout):
if tries < 1:
raise ValueError("Could not resolve the IP address of %s due to timeout." % item)
except (dns.resolver.Timeout):
if tries < 1:
raise ValueError("Could not resolve the IP address of %s due to timeout." % item)
else:
# Validate IP address.
try:
Expand Down
33 changes: 21 additions & 12 deletions management/status_checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def run_network_checks(env, output):
# See https://www.spamhaus.org/news/article/807/using-our-public-mirrors-check-your-return-codes-now. for
# information on spamhaus return codes
rev_ip4 = ".".join(reversed(env['PUBLIC_IP'].split('.')))
zen = query_dns(rev_ip4+'.zen.spamhaus.org', 'A', nxdomain=None)
zen = query_dns(rev_ip4+'.zen.spamhaus.org', 'A', nxdomain=None, retry = False)
if zen is None:
output.print_ok("IP address is not blacklisted by zen.spamhaus.org.")
elif zen == "[timeout]":
Expand Down Expand Up @@ -721,10 +721,9 @@ def check_mail_domain(domain, env, output):
# Stop if the domain is listed in the Spamhaus Domain Block List.
# The user might have chosen a domain that was previously in use by a spammer
# and will not be able to reliably send mail.

# See https://www.spamhaus.org/news/article/807/using-our-public-mirrors-check-your-return-codes-now. for
# information on spamhaus return codes
dbl = query_dns(domain+'.dbl.spamhaus.org', "A", nxdomain=None)
dbl = query_dns(domain+'.dbl.spamhaus.org', "A", nxdomain=None, retry=False)
if dbl is None:
output.print_ok("Domain is not blacklisted by dbl.spamhaus.org.")
elif dbl == "[timeout]":
Expand Down Expand Up @@ -768,7 +767,7 @@ def check_web_domain(domain, rounded_time, ssl_certificates, env, output):
# website for also needs a signed certificate.
check_ssl_cert(domain, rounded_time, ssl_certificates, env, output)

def query_dns(qname, rtype, nxdomain='[Not Set]', at=None, as_list=False):
def query_dns(qname, rtype, nxdomain='[Not Set]', at=None, as_list=False, retry=True):
# Make the qname absolute by appending a period. Without this, dns.resolver.query
# will fall back a failed lookup to a second query with this machine's hostname
# appended. This has been causing some false-positive Spamhaus reports. The
Expand All @@ -793,15 +792,25 @@ def query_dns(qname, rtype, nxdomain='[Not Set]', at=None, as_list=False):
# lifetime expires a dns.exception.Timeout exception will be raised.
resolver.lifetime = 5

if retry:
tries = 2
else:
tries = 1

# Do the query.
try:
response = resolver.resolve(qname, rtype)
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
# Host did not have an answer for this query; not sure what the
# difference is between the two exceptions.
return nxdomain
except dns.exception.Timeout:
return "[timeout]"
while tries > 0:
tries = tries - 1
try:
response = resolver.resolve(qname, rtype, search=True)
tries = 0
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
# Host did not have an answer for this query; not sure what the
# difference is between the two exceptions.
if tries < 1:
return nxdomain
except dns.exception.Timeout:
if tries < 1:
return "[timeout]"

# Normalize IP addresses. IP address --- especially IPv6 addresses --- can
# be expressed in equivalent string forms. Canonicalize the form before
Expand Down