#! /usr/bin/python # # update_dns.py - Update DNS static entries on your Mikrotik Router(s) using this python script. # Copyright (C) 2021 WILDERNETS LLC, Distributed under GPL-3.0, GNU General Public License v3.0 only # # How it works: # - Grab a copy of the master host table off the host table server. # - Get existing DNS static entries from a list of Mikrotik routers. # - Compare entries to the master host table # - Issue add/set/remove commands as needed to update the Mikrotik DNS entries. # # Setup Notes: # - Setup DNS server on your mikrotik router(s) # - Run this on a trusted secure system so you don't have to trust the host master with access to your router(s). # - OR just Comment out Step0 and run from the machine that has the host master file. # - Setup password-less ssh to the host master machine. # - Setup password-less ssh to your router(s). # - Adv Topic: consider setting up a portable subnet/IP for your router so you can implement DNS server redundancy. # (I use 10.10.10.10 on two routers and 10.10.10.1 on two routers and inject these as /32 into OSPF) # # Requirements: # - Setup password-less SSH using keys to the machine that hosts the master copy of the host table # - Setup password-less SSH using keys to the router that act as DNS servers # - Change the Script vars listed below # - Test on a non-production router # # Coding Notes: # - Hosts file parsed into two master dictionaries. # - For each router updated a working copy is made of these two masters. # - As hosts are processed they are deleted from the dictionary copy. # - Next router updated gets a brand new copy from the master. # import re # strip comments import sys # system stuff import subprocess # Popen command import os # Execute scp command # Script vars #HOSTMASTER = "nismaster:etc/hosts" #HOSTMASTER = "/etc/hosts" HOSTSFILE = "/root/hosts.txt" SSHCMD = "/ip dns static export" routerlist = ['10.87.2.1'] routeruser = "dnsupdate" debug = 1 # Step0 Go Grab latest hosts file #print "# Getting hosts file: scp "+HOSTMASTER+" "+HOSTSFILE #os.system("scp "+HOSTMASTER+" "+HOSTSFILE) #os.system("cp "+HOSTMASTER+" "+HOSTSFILE) # Step1 Open hosts file, parse and check for duplicates if debug: print("# Verifying hostsfile: "+HOSTSFILE) error = 0 masteriphosts = {} masterhostip = {} hosts = open(HOSTSFILE,'r',encoding='utf-8') for line in hosts: if not line.startswith('#') and line.strip(): line=re.sub(r'#.*$', '', line).rstrip() data = line.split() i = data.pop(0) if debug > 1: print("checking ip "+i) if (i in masteriphosts): print("ERROR: Duplicate ipaddress "+i+" for "+str(data)+" and "+str(masteriphosts[i])) error += 1 else: masteriphosts[i] = data for h in data: if debug > 1: print("checking host "+h) if (h in masterhostip): print("ERROR: Duplicate hostname "+h+" in hosts file for "+i+" and "+masterhostip[h]) error += 1 else: masterhostip[h] = i if error: exit(1) for router in routerlist: USERHOST = routeruser+"@"+router iphosts = masteriphosts.copy() hostip = masterhostip.copy() addrname = {} nameaddr = {} # Step2 SSH to EACH DNS Router and Export the DNS static table and Parse print("# Getting router DNS entries: ssh",USERHOST, SSHCMD) ssh = subprocess.Popen(["ssh", "%s" % USERHOST, SSHCMD], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = ssh.stdout.readlines() if result == []: error = ssh.stderr.readlines() # print >>sys.stderr, "ERROR: %s" % error else: if debug: print("# Parsing DNS Static Export") for line in result: if line.startswith(b'\n') : line=re.sub(r'add address=', '', line).rstrip() line=re.sub(r'name=', '', line) a,n = line.split() # Check name is a Host if (n in hostip): i = hostip[n] # Check for duplicate DNS names if (n in nameaddr): command = "ssh "+USERHOST+" /ip dns static remove [find name="+n+" address="+a+"]; # Delete Duplicate" print(command) os.system(command) # Changed address for name elif (a != i): command = "ssh "+USERHOST+" /ip dns static set address="+i+" [find name="+n+" address="+a+"]; # Changed Address" print(command) os.system(command) addrname[i] = n nameaddr[n] = i # Delete key from hostip after used so they are gone before step3 del hostip[n] else: # Delete it if not Host command = "ssh "+USERHOST+" /ip dns static remove [find name="+n+" address="+a+"]; # Delete Entry" print(command) os.system(command) # Step3 Remaining keys in hostip need to be added. if debug: print("# Generate Add Commands") for h in hostip: i = hostip[h] command = "ssh "+USERHOST+" /ip dns static add address="+i+" name="+h+"; # Add Entry" print(command) os.system(command) if debug: print("# Finished") exit(0)