-
-
Save letenkov/4753314 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# -*- coding: utf-8 -*- | |
""" | |
Written on 2013-02-04 by Philipp Klaus <philipp.l.klaus →AT→ web.de>. | |
Check <https://gist.github.com/4707775> for newer versions. | |
A script to update the A and AAAA RRs of HOSTNAME on a DNS server | |
according to your actual ones using nsupdate / TSIG. | |
This script is ready to run on Mac OS X (10.8) but you should be able | |
to get it up and running in almost no time on other Unix or Linux systems. | |
Uses dnspython: install using `pip3 install dnspython3` | |
""" | |
import argparse, sys | |
global Verbose | |
Verbose = False | |
def get_external_IP(get_ipv6=False): | |
import urllib.request | |
import ipaddress | |
ADDR = "http://v6.ipv6-test.com/api/myip.php" if get_ipv6 else "http://v4.ipv6-test.com/api/myip.php" | |
retval = urllib.request.urlopen(ADDR).read().decode('ascii') | |
try: | |
ip = ipaddress.ip_address('192.168.0.1') | |
return retval | |
except: | |
return None | |
def get_RR_value(FQDN, kind="A"): | |
import dns.resolver | |
try: | |
answer = dns.resolver.query(FQDN, kind) | |
if len(answer) == 0: | |
return None | |
return answer[0].to_text() | |
except dns.resolver.NXDOMAIN: | |
return None | |
def IPs_match_current_RRs(FQDN): | |
my_IPv4 = get_external_IP(get_ipv6=False) | |
my_IPv6 = get_external_IP(get_ipv6=True) | |
if Verbose: print("Current IPv4 and IPv6 addresses: %s and %s." % (my_IPv4, my_IPv6)) | |
cur_RR_v4 = get_RR_value(FQDN, 'A') | |
cur_RR_v6 = get_RR_value('sb.dyn.klaus.bz.', 'AAAA') | |
if Verbose: print("Current IPv4 and IPv6 RRs in DNS: %s and %s." % (cur_RR_v4, cur_RR_v6)) | |
return (my_IPv4 == cur_RR_v4 and my_IPv6 == cur_RR_v6) | |
def update_dns(server, zone, keyfile, domain, IPv4_addr=None, IPv6_addr=None, TTL=30): | |
import subprocess | |
command = "server %s\n" % server | |
command += "zone %s\n" % zone | |
command += "update delete %s A\n" % domain | |
command += "update delete %s AAAA\n" % domain | |
if IPv4_addr: | |
command += "update add %s %s A %s\n" % (domain, TTL, IPv4_addr) | |
if IPv6_addr: | |
command += "update add %s %s AAAA %s\n" % (domain, TTL, IPv6_addr) | |
command += "show\nsend\n" | |
command = "nsupdate -k {0} -v << EOF\n{1}\nEOF\n".format(keyfile, command) | |
subprocess.call(command, shell=True) | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser(description='Update the RRs of HOSTNAME on a DNS server according to your actual ones.') | |
parser.add_argument('-v', '--verbose', action='store_true', | |
help='Create more detailed output.') | |
parser.add_argument('-z', '--zone', metavar='ZONE', | |
help='The zone of the host to update.', required=True) | |
parser.add_argument('-k', '--keyfile', metavar='DNSSEC-file.key', | |
help='The key file for TSIG.', required=True) | |
parser.add_argument('-n', '--nameserver', metavar='NS', | |
help='The name server to update.', required=True) | |
parser.add_argument('host', metavar='HOSTNAME', | |
help='The hostname you want updated.') | |
args = parser.parse_args() | |
if args.verbose: Verbose = True | |
if not IPs_match_current_RRs(args.host): | |
if Verbose: print("The current IPs and the RRs do not match. Updating the DNS server...") | |
update_dns(args.nameserver, args.zone, args.keyfile, args.host, get_external_IP(), get_external_IP(True)) | |
else: | |
if Verbose: print("The current IPs and the RRs are matching. Everyting OK.") | |
sys.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment