Archive for the ‘DNS’ Category

Disparate DNS Platform Woes

January 16, 2011 Leave a comment

I hope this never happens to you as a DNS administrator, but in the event that you find yourself in the woeful position of having identical discretely maintained legacy DNS zones, this slightly convoluted process may assist you in synchronising the two zones across platforms until such times as you’re able to migrate to one unified solution.  I will create a better solution in the future, but I was exploring different scripting technologies for this one (I now love Perl by the way, it’s ugly, but it works!).

Bear in mind that while I’m primarily a Windows bod, I have a great affinity for Linux/UNIX utilities. Also, I’ve used Googles public DNS IP address, so you won’t be able to get a zone transfer from it.

Firstly a batch file (AXFR.bat) to pull a zone transfer from one DNS platform and copy it to a Windows server that will run on a Windows box with dig, grep & perl installed:

@echo off

:: Get domain AXFR & output to file:
dig @ -t axfr > C:\DNS\Scripts\AXFR.txt 

:: Harvest records and exclude anything with a dash:
grep "host.*" C:\DNS\Scripts\AXFR.txt | grep -v "-" > C:\DNS\Scripts\Filtered_AXFR.txt

:: Convert the file into a format usable by the batch file that will add them to MS DNS:
perl > C:\DNS\Scripts\records.txt 

:: Copy the prepared file to an MS DNS server:
xcopy C:\DNS\Scripts\records.txt \\\C$\DNS\Scripts\ /y

As this will output the following format in the AXFR.txt text file:

; <<>> DiG 9.3.2 <<>> @ -t axfr ; (1 server found) 
;; global options: printcmd	 86400	IN	SOA 8308331 21600 3600 604800 600 86400	IN	A 86400	IN	A	 86400	IN	NS	 86400	IN	NS;;	 86400	IN	SOA	ns1. 8308331 21600 3600 604800 600

;; Query time: 312 msec
;; WHEN: Sat Jan 15 08:30:01 2011
;; XFR size: 7 records (messages 5)

I used grep to filter the results into the Filtered_AXFR.txt file and called the following Perl script (

open(DATA, "Filtered_AXFR.txt");
while (<DATA>) {
@linefields = split(/\s+/);
if (@linefields) { print "$linefields[0];$linefields[@linefields-2];$linefields[@linefields-1]\n"; }

This will output the records.txt file in the following format that a batch file on the Windows server can use to insert records into MS DNS.;;

The next step moves to your Windows DNS server.  This batch file (DNS_Insert.bat) backs up the zone, creates or deletes and adds records from the records.txt file copied to the Windows DNS server by the previous batch file, logs the transactions, emails the support team by calling a CDO VBScript (email.vbs) and deletes logs older than one year:

:: Export zone to C:\DNS\Scripts\Backups before update
dnscmd /ZoneExport MS_DNS_Pre_Update_Zone_%date:~-4,4%%date:~-7,2%%date:~0,2%.txt
echo %date% %time% >> C:\DNS\Scripts\Logs\Export-Move.log
move /Y C:\WINDOWS\system32\dns\MS_DNS_Pre_Update_Zone_*.txt C:\DNS\Scripts\Backups\ >> C:\DNS\Scripts\Logs\Export-Move.log

:: Bulk delete and insert A records matching the contents of C:\DNS\Scripts\records.txt on DC1
for /f "tokens=1-3 delims=;" %%a in (records.txt) do (dnscmd /RecordDelete %%a %%b /f
dnscmd /RecordAdd %%a %%b %%c) >> C:\DNS\Scripts\Logs\Add_RR_2_MSDNS_%date:~-4,4%%date:~-7,2%%date:~0,2%.log

:: Export zone to C:\DNS\Scripts\Backups after update
dnscmd /ZoneExport MS_DNS_Post_Update_Zone_%date:~-4,4%%date:~-7,2%%date:~0,2%.txt
echo %date% %time% >> C:\DNS\Scripts\Logs\Export-Move.log
move /Y C:\WINDOWS\system32\dns\MS_DNS_Post_Update_Zone_*.txt C:\DNS\Scripts\Backups\ >> C:\DNS\Scripts\Logs\Export-Move.log

:: Email Support team to advise which records have been created
cscript C:\DNS\Scripts\Scripts\email.vbs

cd Logs\
:: Delete logs on a rolling yearly basis
:: Ascertain date 364 days ago
set yyyy=

set $tok=1-3
for /f "tokens=1 delims=.:/-, " %%u in ('date /t') do set $d1=%%u
if "%$d1:~0,1%" GTR "9" set $tok=2-4
for /f "tokens=%$tok% delims=.:/-, " %%u in ('date /t') do (
for /f "skip=1 tokens=2-4 delims=/-,()." %%x in ('echo.^|date') do (
    set %%x=%%u
    set %%y=%%v
    set %%z=%%w
    set $d1=
    set $tok=))

if "%yyyy%"=="" set yyyy=%yy%
if /I %yyyy% LSS 100 set /A yyyy=2000 + 1%yyyy% - 100

set CurDate=%mm%/%dd%/%yyyy%

set dayCnt=%1

if "%dayCnt%"=="" set dayCnt=364

set /A dd=1%dd% - 100 - %dayCnt%
set /A mm=1%mm% - 100

if /I %dd% GTR 0 goto DONE
set /A mm=%mm% - 1
if /I %mm% GTR 0 goto ADJUSTDAY
set /A mm=12
set /A yyyy=%yyyy% - 1


if %mm%==1 goto SET31
if %mm%==2 goto LEAPCHK
if %mm%==3 goto SET31
if %mm%==4 goto SET30
if %mm%==5 goto SET31
if %mm%==6 goto SET30
if %mm%==7 goto SET31
if %mm%==8 goto SET31
if %mm%==9 goto SET30
if %mm%==10 goto SET31
if %mm%==11 goto SET30
REM ** Month 12 falls through

set /A dd=31 + %dd%



set /A dd=30 + %dd%



set /A tt=%yyyy% %% 4

if not %tt%==0 goto SET28

set /A tt=%yyyy% %% 100

if not %tt%==0 goto SET29

set /A tt=%yyyy% %% 400

if %tt%==0 goto SET29


set /A dd=28 + %dd%



set /A dd=29 + %dd%



if /I %mm% LSS 10 set mm=0%mm%
if /I %dd% LSS 10 set dd=0%dd%

:: Copy logs less than 364 days ago into a text file to exclude and delete the rest

echo >> Logs_less_than_a_year_old.txt
for /f "tokens=*" %%a IN ('xcopy C:\DNS\Scripts\Logs\*.log /d:%mm%-%dd%-%yyyy% /L /I null') do if exist %%~nxa echo %%~nxa >> C:\DNS\Scripts\Logs\Logs_less_than_a_year_old.txt
for /f "tokens=*" %%a IN ('xcopy C:\DNS\Scripts\Logs\*.log /L /I /EXCLUDE:C:\DNS\Scripts\Logs\Logs_less_than_a_year_old.txt null') do if exist "%%~nxa" del "%%~nxa"

:: Copy exported zone files less than 364 days ago into a text file to exclude and delete the rest
echo >> Files_less_than_a_year_old.txt
for /f "tokens=*" %%a IN ('xcopy C:\DNS\Scripts\Backups\*.txt /d:%mm%-%dd%-%yyyy% /L /I null') do if exist %%~nxa echo %%~nxa >> C:\DNS\Scripts\Logs\Files_less_than_a_year_old.txt
for /f "tokens=*" %%a IN ('xcopy C:\DNS\Scripts\Backups\*.txt /L /I /EXCLUDE:C:\DNS\Scripts\Logs\Files_less_than_a_year_old.txt null') do if exist "%%~nxa" del "%%~nxa"

The CDO VBScript called by the previous batch file reads the last modified date of the records.txt file and copies it and the contents into an email to your support team:

'These constants are defined to make the code more readable
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Dim fso, f, BodyText, arrLines, LineCount, ObtainFile, CreateDate
Set fso = CreateObject("Scripting.FileSystemObject")
'Open the file for reading
Set f = fso.OpenTextFile("C:\DNS\Scripts\Filtered_AXFR.txt", ForReading)
'The ReadAll method reads the entire file into the variable BodyText
BodyText = f.ReadAll
'Split by lines, put into an array
arrLines = Split(BodyText,vbCrLf)
'Use UBound to count the lines
LineCount = UBound(arrLines) + 1
'Close the file
'Get file creation date
Set ObtainFile = fso.GetFile("C:\DNS\Scripts\Filtered_AXFR.txt")
CreateDate = ObtainFile.DateLastModified

Set objMessage = CreateObject("CDO.Message")
objMessage.Subject = "MS DNS Updated with A records from Other DNS Platform"
objMessage.From = ""
objMessage.To = ""
objMessage.TextBody = "The following " & LineCount & " hosts were exported from your other DNS platform on/at: " _
" & CreateDate & " (If this date is more than 24 hours ago, there is a problem with the scheduled task) " _
"and added to MS DNS over the past 10 minutes: " & vbCrLf & vbCrLf & BodyText & vbCrLf & "Exported zone files " _
"can be found here: \\\C$\DNS\Scripts\Backups\ " & vbCrLf & "Update logs can be found here can " _
"be found here: \\\C$\DNS\Scripts\Logs\ "

'==Configure remote SMTP server.

objMessage.Configuration.Fields.Item _
("") = 2

objMessage.Configuration.Fields.Item _
("") = ""

objMessage.Configuration.Fields.Item _
("") = 25


'==Send email

Set f = Nothing
Set fso = Nothing
Set objMessage = Nothing
Set ObtainFile = Nothing	86400	IN	A