2014-06-08 21:22:52 +00:00
#!/usr/bin/env python3
2014-04-20 16:26:35 +00:00
#
# Tests the DNS configuration of a Mail-in-a-Box.
2014-04-18 00:17:45 +00:00
#
# tests/dns.py ipaddr hostname
2014-04-20 16:26:35 +00:00
#
# where ipaddr is the IP address of your Mail-in-a-Box
# and hostname is the domain name to check the DNS for.
2014-04-18 00:17:45 +00:00
2014-04-23 22:27:50 +00:00
import sys , re , difflib
import dns . reversename , dns . resolver
2014-04-18 00:17:45 +00:00
if len ( sys . argv ) < 3 :
2014-05-10 11:15:31 +00:00
print ( " Usage: tests/dns.py ipaddress hostname [primary hostname] " )
2014-04-18 00:17:45 +00:00
sys . exit ( 1 )
2014-05-10 11:15:31 +00:00
ipaddr , hostname = sys . argv [ 1 : 3 ]
primary_hostname = hostname
if len ( sys . argv ) == 4 :
primary_hostname = sys . argv [ 3 ]
2014-04-18 00:17:45 +00:00
2014-04-20 16:26:35 +00:00
def test ( server , description ) :
2014-04-23 22:27:50 +00:00
tests = [
( hostname , " A " , ipaddr ) ,
2014-06-19 22:47:41 +00:00
#(hostname, "NS", "ns1.%s.;ns2.%s." % (primary_hostname, primary_hostname)),
2014-05-10 11:15:31 +00:00
( " ns1. " + primary_hostname , " A " , ipaddr ) ,
( " ns2. " + primary_hostname , " A " , ipaddr ) ,
2014-04-23 22:27:50 +00:00
( " www. " + hostname , " A " , ipaddr ) ,
2014-05-10 11:15:31 +00:00
( hostname , " MX " , " 10 " + primary_hostname + " . " ) ,
2014-04-23 22:27:50 +00:00
( hostname , " TXT " , " \" v=spf1 mx -all \" " ) ,
( " mail._domainkey. " + hostname , " TXT " , " \" v=DKIM1; k=rsa; s=email; \" \" p=__KEY__ \" " ) ,
2014-06-19 22:47:41 +00:00
#("_adsp._domainkey." + hostname, "TXT", "\"dkim=all\""),
2022-08-19 17:23:42 +00:00
( " _dmarc. " + hostname , " TXT " , " \" v=DMARC1; p=quarantine; \" " ) ,
2014-04-23 22:27:50 +00:00
]
return test2 ( tests , server , description )
2014-04-18 00:17:45 +00:00
2014-04-23 18:10:04 +00:00
def test_ptr ( server , description ) :
2014-04-23 22:27:50 +00:00
ipaddr_rev = dns . reversename . from_address ( ipaddr )
tests = [
( ipaddr_rev , " PTR " , hostname + ' . ' ) ,
]
return test2 ( tests , server , description )
def test2 ( tests , server , description ) :
first = True
resolver = dns . resolver . get_default_resolver ( )
resolver . nameservers = [ server ]
for qname , rtype , expected_answer in tests :
# do the query and format the result as a string
2014-05-10 11:11:26 +00:00
try :
response = dns . resolver . query ( qname , rtype )
2014-06-04 23:31:55 +00:00
except dns . resolver . NoNameservers :
2014-05-10 11:11:26 +00:00
# host did not have an answer for this query
2014-06-04 23:31:55 +00:00
print ( " Could not connect to %s for DNS query. " % server )
sys . exit ( 1 )
except ( 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
2014-06-04 21:01:49 +00:00
response = [ " [no value] " ]
2014-04-23 22:27:50 +00:00
response = " ; " . join ( str ( r ) for r in response )
response = re . sub ( r " ( \" p=).*( \" ) " , r " \ 1__KEY__ \ 2 " , response ) # normalize DKIM key
2014-06-17 21:34:26 +00:00
response = response . replace ( " \" \" " , " " ) # normalize TXT records (DNSSEC signing inserts empty text string components)
2014-04-23 18:10:04 +00:00
2014-04-23 22:27:50 +00:00
# is it right?
if response == expected_answer :
#print(server, ":", qname, rtype, "?", response)
continue
# show prolem
if first :
print ( " Incorrect DNS Response from " , description )
2014-04-20 16:26:35 +00:00
print ( )
2014-06-04 21:01:49 +00:00
print ( " QUERY " , " RESPONSE " , " CORRECT VALUE " , sep = ' \t ' )
2014-04-23 22:27:50 +00:00
first = False
2014-06-04 21:01:49 +00:00
print ( ( qname + " / " + rtype ) . ljust ( 20 ) , response . ljust ( 12 ) , expected_answer , sep = ' \t ' )
2014-04-23 22:27:50 +00:00
return first # success
2014-04-18 00:17:45 +00:00
2014-04-20 16:26:35 +00:00
# Test the response from the machine itself.
2014-04-23 18:10:04 +00:00
if not test ( ipaddr , " Mail-in-a-Box " ) :
print ( )
print ( " Please run the Mail-in-a-Box setup script on %s again. " % hostname )
sys . exit ( 1 )
else :
2014-06-04 21:01:49 +00:00
print ( " The Mail-in-a-Box provided correct DNS answers. " )
print ( )
2014-04-20 16:26:35 +00:00
# If those settings are OK, also test Google's Public DNS
# to see if the machine is hooked up to recursive DNS properly.
2014-04-23 18:10:04 +00:00
if not test ( " 8.8.8.8 " , " Google Public DNS " ) :
2014-04-20 16:26:35 +00:00
print ( )
2014-04-23 18:10:04 +00:00
print ( " Check that the nameserver settings for %s are correct at your domain registrar. It may take a few hours for Google Public DNS to update after changes on your Mail-in-a-Box. " % hostname )
sys . exit ( 1 )
else :
2014-06-04 21:01:49 +00:00
print ( " Your domain registrar or DNS host appears to be configured correctly as well. Public DNS provides the same answers. " )
print ( )
2014-04-23 18:10:04 +00:00
# And if that's OK, also check reverse DNS (the PTR record).
if not test_ptr ( " 8.8.8.8 " , " Google Public DNS (Reverse DNS) " ) :
print ( )
print ( " The reverse DNS for %s is not correct. Consult your ISP for how to set the reverse DNS (also called the PTR record) for %s to %s . " % ( hostname , hostname , ipaddr ) )
sys . exit ( 1 )
else :
2014-06-04 21:01:49 +00:00
print ( " And the reverse DNS for the domain is correct. " )
print ( )
2014-04-23 18:10:04 +00:00
print ( " DNS is OK. " )