Scripting a DNS Backup

DNS, Powershell

Scripting a DNS Backup

The client I am currently working at wanted me to look at their DNS configuration. A while ago one of their admins had enabled DNS scavenging without really know what they were doing and before too long a large portion of their valid DNS records had been scavenged.

Before I took a look at their scavenging they wanted me to implement a regular backup of their DNS zones. At the core of the script is the one line ‘dnscmd /ZoneExport’, all the other components are designed to provide a repeatable, robust script that cleans up after itself.

This first section grabs some parameters from the command line and stores them.

1
2
3
4
5
6
7
8
9
10
11
PARAM(
[Parameter(Mandatory=$true)][STRING[]]$server,
[Parameter(Mandatory=$true)][STRING]$dnsZone,
[STRING]$preface = "DNSZoneBackup",
[STRING]$extension = ".dns",
[Parameter(Mandatory=$true)][STRING[]]$finalLocation = "C:\Admin\DNSBackup\Backups"
)
$logFile = "logs\$(Get-date -format yyyyMM)dnsBackupLogs.log"
If(!(test-path -Path $logFile)) {
	New-Item $logFile -type file
}

Next a function is created to build a log file as the script is run

1
2
3
4
5
function LogWrite {
	PARAM ([STRING]$logstring)
	$logTimeStamp = Get-Date -Format yyyyMMdd_hhmmss
	Add-Content $logFile -Value "$logtimestamp $logstring"
}

Now the script starts. Firstly with a section for the log file to make it easier to read the log file. It then moves on to create a foreach loop to check each server entered at the command line (the $server variable can take an array).

There are number of components created in the loop mostly parts that are used in the creation of the backup file name or the script that is used to run the backup (dnscmd /ZoneExport). The backup file is always put in %windir%\System32\dns, and this can’t be changed.

1
2
3
4
5
6
7
8
9
10
11
12
13
LogWrite "--------------------------"
LogWrite "DNS backup job has started"
LogWrite "--------------------------"
foreach ($entry in $server) {
#set the timestamp
$timeStamp = Get-Date -Format yyyyMMdd_hhmmss
LogWrite "DNS Backup on $entry has started"
#build the file name
$fileName = "$entry$preface$timeStamp$extension"
#Create backup script
$dnsCMD = "dnscmd $entry /ZoneExport $dnsZone $fileName"
$dnsBackup = invoke-expression "CMD /C $dnsCMD"
LogWrite "The zone $dnsZone has been backed up to %windir%\system32\dns on $entry in a file called $filename"

The next section moves the backup file to a final location so that it doesn’t file up the system drive. To allow this to run against multiple machines I created share access on the machines it was running against. I locked the share down so that on the user that was running the script could access the share (\\servername\DNS\). If you are running the script locally the share is not required.

This foreach loop will also remove backup files from the final destination that are older than 7 days. The client was happy with this as they do weekly full and daily incremental backups of the final location.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
foreach ($path in $finalLocation){
IF (Test-Path -Path $path) {
	Copy-Item "\\$entry\DNS\$fileName" "$path"
	LogWrite "$filename has been copied to $path"
	#Clean up files older than 7 days
	$oldFiles = Get-Item "$path\*" | sort -Property lastwritetime -Descending | where {$_.lastWriteTime -lt (get-date).adddays(-7)} | foreach {
	Remove-Item $_.fullname
	LogWrite "$_.Fullname has been deleted"
	}
}
Else {
	logWrite "The Backup destination, $path, does not exist"
}
}

The final section removes the orginal backup file and writes some final entries to the log file.

1
2
3
4
5
6
7
Remove-Item "\\$entry\DNS$\$fileName"
LogWrite "The original backup file has been removed from %windir\system32\dns on $entry"
LogWrite "backup of $dnsZone on $entry has been finished"
}
LogWrite "---------------------------"
LogWrite "DNS backup job has finished"
LogWrite "---------------------------"

The full script can be downloaded from here: backup-dns.ps1

Leave a Reply

Your email address will not be published. Required fields are marked *