1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2025-06-08 19:00:55 +00:00
This commit is contained in:
Michael Kroes 2020-05-18 19:31:16 -04:00 committed by GitHub
commit 8da77925a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -4,7 +4,7 @@
# TLS certificates have been signed, etc., and if not tells the user # TLS certificates have been signed, etc., and if not tells the user
# what to do next. # what to do next.
import sys, os, os.path, re, subprocess, datetime, multiprocessing.pool import sys, os, os.path, re, subprocess, datetime, multiprocessing.pool, time
import dns.reversename, dns.resolver import dns.reversename, dns.resolver
import dateutil.parser, dateutil.tz import dateutil.parser, dateutil.tz
@ -400,19 +400,9 @@ def check_primary_hostname_dns(domain, env, output, dns_domains, dns_zonefiles):
issues listed above.""" issues listed above."""
% (my_ips, ip + ((" / " + ipv6) if ipv6 is not None else ""))) % (my_ips, ip + ((" / " + ipv6) if ipv6 is not None else "")))
# Check reverse DNS matches the PRIMARY_HOSTNAME. Note that it might not be # Check reverse DNS matches the PRIMARY_HOSTNAME. Note that it might not be
# a DNS zone if it is a subdomain of another domain we have a zone for. # a DNS zone if it is a subdomain of another domain we have a zone for.
existing_rdns_v4 = query_dns(dns.reversename.from_address(env['PUBLIC_IP']), "PTR") check_reverse_dns(domain, my_ips, output, env)
existing_rdns_v6 = query_dns(dns.reversename.from_address(env['PUBLIC_IPV6']), "PTR") if env.get("PUBLIC_IPV6") else None
if existing_rdns_v4 == domain and existing_rdns_v6 in (None, domain):
output.print_ok("Reverse DNS is set correctly at ISP. [%s%s]" % (my_ips, env['PRIMARY_HOSTNAME']))
elif existing_rdns_v4 == existing_rdns_v6 or existing_rdns_v6 is None:
output.print_error("""Your box's reverse DNS is currently %s, but it should be %s. Your ISP or cloud provider will have instructions
on setting up reverse DNS for your box.""" % (existing_rdns_v4, domain) )
else:
output.print_error("""Your box's reverse DNS is currently %s (IPv4) and %s (IPv6), but it should be %s. Your ISP or cloud provider will have instructions
on setting up reverse DNS for your box.""" % (existing_rdns_v4, existing_rdns_v6, domain) )
# Check the TLSA record. # Check the TLSA record.
tlsa_qname = "_25._tcp." + domain tlsa_qname = "_25._tcp." + domain
@ -433,6 +423,42 @@ def check_primary_hostname_dns(domain, env, output, dns_domains, dns_zonefiles):
# Check that the hostmaster@ email address exists. # Check that the hostmaster@ email address exists.
check_alias_exists("Hostmaster contact address", "hostmaster@" + domain, env, output) check_alias_exists("Hostmaster contact address", "hostmaster@" + domain, env, output)
def check_reverse_dns(domain, my_ips, output, env):
existing_rdns_v4 = query_dns_ptr(dns.reversename.from_address(env['PUBLIC_IP']))
existing_rdns_v6 = query_dns_ptr(dns.reversename.from_address(env['PUBLIC_IPV6'])) if env.get(
"PUBLIC_IPV6") else None
if existing_rdns_v4 == domain and existing_rdns_v6 in (None, domain):
output.print_ok("Reverse DNS is set correctly at ISP. [%s%s]" % (my_ips, env['PRIMARY_HOSTNAME']))
elif existing_rdns_v4 == existing_rdns_v6 or existing_rdns_v6 is None:
output.print_error("""Your box's reverse DNS is currently %s, but it should be %s. Your ISP or cloud provider will have instructions
on setting up reverse DNS for your box.""" % (existing_rdns_v4, domain))
else:
output.print_error("""Your box's reverse DNS is currently %s (IPv4) and %s (IPv6), but it should be %s. Your ISP or cloud provider will have instructions
on setting up reverse DNS for your box.""" % (existing_rdns_v4, existing_rdns_v6, domain))
def query_dns_ptr(qname):
# When looking up PTR records bind will contact the authoritative servers for a response.
# Sometimes these servers don't respond properly, we will give these servers 3 chances
# with a 2 second pause in between. These servers don't take a long time to fail, so it
# shouldn't slow the checks down to much.
for attempt in range(3):
result=query_dns(qname, "PTR")
# Check if the authoritative servers respond properly
if result == "[nonameservers]":
time.sleep(2)
else:
# There might still be an error, like a timeout, but we will continue
# chances of recovering from those are slim.
break
# Display a slighty more meaningful message to the end users
if result == "[nonameservers]":
return "[bad response from authoritative nameservers]"
return result
def check_alias_exists(alias_name, alias, env, output): def check_alias_exists(alias_name, alias, env, output):
mail_aliases = dict([(address, receivers) for address, receivers, *_ in get_mail_aliases(env)]) mail_aliases = dict([(address, receivers) for address, receivers, *_ in get_mail_aliases(env)])
if alias in mail_aliases: if alias in mail_aliases:
@ -681,10 +707,12 @@ def query_dns(qname, rtype, nxdomain='[Not Set]', at=None):
# Do the query. # Do the query.
try: try:
response = resolver.query(qname, rtype) response = resolver.query(qname, rtype)
except (dns.resolver.NoNameservers, dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer):
# Host did not have an answer for this query; not sure what the # No response was received
# difference is between the two exceptions.
return nxdomain return nxdomain
except dns.resolver.NoNameservers:
# No non-broken nameservers were available to respond to the request
return "[nonameservers]"
except dns.exception.Timeout: except dns.exception.Timeout:
return "[timeout]" return "[timeout]"
@ -978,6 +1006,13 @@ if __name__ == "__main__":
elif sys.argv[1] == "--show-changes": elif sys.argv[1] == "--show-changes":
run_and_output_changes(env, pool) run_and_output_changes(env, pool)
elif sys.argv[1] == "--check-ptr":
# See if the reverse dns of the box is configured properly
shell('check_call', ["/usr/sbin/rndc", "flush"], trap=True)
output = ConsoleOutput()
my_ips = env['PUBLIC_IP'] + ((" / "+env['PUBLIC_IPV6']) if env.get("PUBLIC_IPV6") else "")
check_reverse_dns(env["PRIMARY_HOSTNAME"], my_ips, output, env)
elif sys.argv[1] == "--check-primary-hostname": elif sys.argv[1] == "--check-primary-hostname":
# See if the primary hostname appears resolvable and has a signed certificate. # See if the primary hostname appears resolvable and has a signed certificate.
domain = env['PRIMARY_HOSTNAME'] domain = env['PRIMARY_HOSTNAME']