2014-04-18 00:17:45 +00:00
#!/usr/bin/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
import sys , subprocess , re , difflib
if len ( sys . argv ) < 3 :
print ( " Usage: tests/dns.py ipaddress hostname " )
sys . exit ( 1 )
ipaddr , hostname = sys . argv [ 1 : ]
2014-04-20 16:26:35 +00:00
# construct the expected output
subs = { " ipaddr " : ipaddr , " hostname " : hostname }
expected = """
{ hostname } . ##### IN A {ipaddr}
{ hostname } . ##### IN NS ns1.{hostname}.
{ hostname } . ##### IN NS ns2.{hostname}.
ns1 . { hostname } . ##### IN A {ipaddr}
ns2 . { hostname } . ##### IN A {ipaddr}
www . { hostname } . ##### IN A {ipaddr}
{ hostname } . ##### IN MX 10 {hostname}.
{ hostname } . ##### IN TXT "v=spf1 mx -all"
mail . _domainkey . { hostname } . ##### IN TXT "v=DKIM1\; k=rsa\; s=email\; " "p=__KEY__"
""" .format(**subs).strip() + " \n "
def dig ( server , digargs ) :
2014-04-18 00:17:45 +00:00
# run dig and clean the output
2014-04-20 16:26:35 +00:00
response = subprocess . check_output ( [ ' dig ' , ' @ ' + server , " +noadditional " , " +noauthority " ] + digargs ) . decode ( ' utf8 ' )
2014-04-18 00:17:45 +00:00
response = re . sub ( ' [ \r \n ]+ ' , ' \n ' , response ) # remove blank lines
response = re . sub ( ' \n ;.* ' , ' ' , response ) # remove comments
2014-04-20 16:26:35 +00:00
response = re . sub ( ' ( \n \ S+ \ s+)( \ d+) ' , r ' \ 1##### ' , response ) # normalize TTLs
response = re . sub ( r " ( \" p=).*( \" ) " , r " \ 1__KEY__ \ 2 " , response ) # normalize DKIM key
2014-04-18 00:17:45 +00:00
response = response . strip ( ) + " \n "
return response
2014-04-20 16:26:35 +00:00
def test ( server , description ) :
digoutput = \
dig ( server , [ hostname ] ) \
+ dig ( server , [ " ns " , hostname ] ) \
+ dig ( server , [ " ns1. " + hostname ] ) \
+ dig ( server , [ " ns2. " + hostname ] ) \
+ dig ( server , [ " www. " + hostname ] ) \
+ dig ( server , [ " mx " , hostname ] ) \
+ dig ( server , [ " txt " , hostname ] ) \
+ dig ( server , [ " txt " , " mail._domainkey. " + hostname ] )
2014-04-23 18:10:04 +00:00
return test2 ( digoutput , server , description , expected )
2014-04-18 00:17:45 +00:00
2014-04-23 18:10:04 +00:00
def test_ptr ( server , description ) :
ipaddr_reversed = " . " . join ( reversed ( ipaddr . split ( " . " ) ) )
expected = " %s .in-addr.arpa. ##### IN PTR %s . \n " % ( ipaddr_reversed , hostname )
digoutput = dig ( server , [ " -x " , ipaddr ] )
return test2 ( digoutput , server , description , expected )
def test2 ( digoutput , server , description , expected ) :
2014-04-20 16:26:35 +00:00
# Show a diff if there are any changes
has_diff = False
def split ( s ) : return [ line + " \n " for line in s . split ( " \n " ) ]
for line in difflib . unified_diff ( split ( expected ) , split ( digoutput ) , fromfile = ' expected DNS settings ' , tofile = description ) :
if not has_diff :
print ( " The response from %s ( %s ) is not correct: " % ( description , server ) )
print ( )
has_diff = True
2014-04-23 18:10:04 +00:00
sys . stdout . write ( line )
2014-04-20 16:26:35 +00:00
return not has_diff
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-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 :
# 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 :
print ( " DNS is OK. " )