diff --git a/update_mikrotik_dns.py b/update_mikrotik_dns.py new file mode 100644 index 0000000..dcdaa2f --- /dev/null +++ b/update_mikrotik_dns.py @@ -0,0 +1,138 @@ +#! /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) \ No newline at end of file