Archive

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 @8.8.8.8 -t axfr your.domain.com > 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 Convert_File_Format.pl > C:\DNS\Scripts\records.txt 

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

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

; <<>> DiG 9.3.2 <<>> @8.8.8.8 -t axfr your.domain.com ; (1 server found) 
;; global options: printcmd 
your.domain.com.	 86400	IN	SOA	ns1.your.domain.com. hostmaster.your.domain.com. 8308331 21600 3600 604800 600 
ns1.your.domain.com. 86400	IN	A	192.168.7.10
ns2.your.domain.com. 86400	IN	A	192.168.7.11
your.domain.com.	 86400	IN	NS	ns1.your.domain.com. 
your.domain.com.	 86400	IN	NS	ns2.your.domain.com. 
host1.your.domain.com.;192.168.10.2
host2.your.domain.com.;192.168.10.5
your.domain.com.	 86400	IN	SOA	ns1. your.domain.com. hostmaster.your.domain.com. 8308331 21600 3600 604800 600

;; Query time: 312 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; 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 (Convert_File_Format.pl):

#!C:\Perl\bin\perl.exe
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.

host1.your.domain.com.;192.168.10.2
host2.your.domain.com.;192.168.10.5

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 your.domain.com zone to C:\DNS\Scripts\Backups before update
dnscmd /ZoneExport your.domain.com 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 DC1.domain.com /RecordDelete your.domain.com %%a %%b /f
dnscmd DC1.domain.com /RecordAdd your.domain.com %%a %%b %%c) >> C:\DNS\Scripts\Logs\Add_RR_2_MSDNS_%date:~-4,4%%date:~-7,2%%date:~0,2%.log

:: Export your.domain.com zone to C:\DNS\Scripts\Backups after update
dnscmd /ZoneExport your.domain.com 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

:CHKDAY
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

:ADJUSTDAY

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

:SET31
set /A dd=31 + %dd%

goto CHKDAY

:SET30

set /A dd=30 + %dd%

goto CHKDAY

:LEAPCHK

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

:SET28

set /A dd=28 + %dd%

goto CHKDAY

:SET29

set /A dd=29 + %dd%

goto CHKDAY

:~DONE

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"
exit

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
f.Close
'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 = "dns_update@your.domain.com"
objMessage.To = "Support@your.domain.com"
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: \\dc1.your.domain.com\C$\DNS\Scripts\Backups\ " & vbCrLf & "Update logs can be found here can " _
"be found here: \\dc1.your.domain.com\C$\DNS\Scripts\Logs\ "

'==Configure remote SMTP server.

objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2

objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "smtp.your.domain.com"

objMessage.Configuration.Fields.Item _
("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25

objMessage.Configuration.Fields.Update

'==Send email
objMessage.Send

Set f = Nothing
Set fso = Nothing
Set objMessage = Nothing
Set ObtainFile = Nothing
host2.your.domain.com.	86400	IN	A	192.168.10.5