Managing DNS using PowerShell

One of the things I have found sorely lacking in PowerShell 2.0 is a good way to manage DNS.  I’m hoping there is a fix for this in Windows Server 2012 and PowerShell 3.0, but for now I’ve had to search for alternatives.  Now, the Scripting Guys have published an excellent article on how to manage DNS through a combination of PowerShell and WMI.  You can find it here.   As I said, this is an interesting approach, and certainly works, but I personally found it to be overly complicated.  Instead, I found that leveraging PowerShell’s ability to incorporate pre-existing tools into my scripts presented me with a more viable solution. Specifically, I’ve combined DNSCMD with PowerShell.  Here’s how it works. 

DNSCMD is a well documented and very powerful tool for managing your windows DNS server from the command line.  It can be called directly from within PowerShell. So lets say I want a script that will set up new primary DNS zones for me based on a standard that we’ve developed.  We could set up AD integrated zones this way as well, but in my situation I was dealing with primary and so that’s what I’m sticking with now.  If you want to use AD integrated zones instead then the syntax is pretty easy to modify.  So, lets say I want to set up a new zone for sweeneyops.com.  I could simply run my script like this:

./create-primarydnszone.ps1 sweeneyops.com

… and voila! The zone would be created as per my predefined standards. What are my standards?  I guess we should probably define those now:

  • I want to create a primary dns zone
  • I want to use the default windows dns zone naming convention. (e.g. if my zone is sweeneyops.lab then my zone file would be sweeneyops.lab.dns)
  • My server host name is Server1, but it is recognized publicly as ns1.sweeneyops.lab.  This server only hosts primary zones. 
  • I have a second server called Server2.  It is publicly recognized as ns2.sweeneyops.lab.  It will host only seecondary copies of the zone, and I want it listed as a name server.
  • The host name will be added automatically to the name servers list. I want to remove it.
  • I want the zone contact to be me@sweeneyops.lab.  In DNS zone syntax that equates to me.sweeneyops.lab.
  • I want to use the windows default settings for the start of authority.
  • I want to allow zone transfers, but only for servers listed in the name servers tab of the DNS zone properties.
  • I want to create an A record for WWW and an empty A record (DNSCMD thinks of this as an @ record) and have both point to 192.168.1.1
    Here’s what the code looks like (I apologize if the line breaks are confusing, but I think it reads easily enough):

PARAM($domain)

# get the local host name
$localhost = $env:computername

# create the dns zone
dnscmd $localhost /zoneadd $domain /primary /file "$domain.dns"
   
# update Start of Authority (note: need to use single quotes around @ or will error out)
dnscmd $localhost /recordadd $domain ‘@’ SOA ns1.sweeneyops.lab me.sweeneyops.lab 1\ 3600 600 86400 3600

# add authoritative name servers
dnscmd $localhost /recordadd $domain ‘@’ NS ns1.sweeneyops.lab
dnscmd $localhost /recordadd $domain ‘@’ NS ns2.sweeneyops.lab
   
# Remove the host name from the name servers list
dnscmd $localhost /recorddelete $domain ‘@’ NS $localhost /f

# make sure zone transfers are allowed, but only for servers in the name server tab, and configure to notify
dnscmd $localhost /zoneresetsecondaries $domain /securens /notify

# create default records for cooperindustries.com
dnscmd $localhost /recordadd $domain ‘@’ A 192.168.1.1
dnscmd $localhost /recordadd $domain www A 192.168.1.1

Now one thing worth noting here is the entry for creating the Start of Authority record (SOA).  I said I wanted to use the windows defaults for setting up the SOA, but the DNSCMD syntax requires that you provide the values for the various SOA components.  In our script, that looks like this:

dnscmd $localhost /recordadd $domain ‘@’ SOA ns1.sweeneyops.lab me.sweeneyops.lab 1\ 3600 600 86400 3600

If we were to manually enter this on Server1 to create a zone called sweeneyops.com then it would look like this:

dnscmd Server1 /recordadd sweeneyops.com ‘@’ SOA ns1.sweeneyops.lab me.sweeneyops.lab 1\ 3600 600 86400 3600

So what’s up with that bit at the end where all the numbers start?  Well, if you pull up NSLOOKUP and set your query type to SOA then look up a zone after creating it through the DNS GUI you will see the following returned in the entry:

refresh = 3600 (1 hour)
retry   = 600 (10 mins)
expire  = 86400 (1 day)
default TTL = 3600 (1 hour)

These are the default Refresh, Retry, Expire, and MinTTL values defined by Windows, which I said I wanted to use.  That’s what the “3600 600 86400 3600” part is about.  The “1\” is a serial number value required in the DNS syntax. Normally, when using the GUI, Windows would define this value automatically.  We still want it to do so, and I found that using the “1\” causes it to do just that.  Trial an error for me, benefit for you.  I haven’t tried defining a specify serial number, but I suppose you could do that and possibly pass it in as another parameter.  For now, however, lets move on.  

I run this script on Server1 (ns1.sweeneyops.lab), pass in my domain name, and it creates my primary zone.  But what about my secondary zones on Server2 (ns2.sweeneyops.lab)?  For those, I will need a slightly different script.  Our new script is going to need the IP address of ns1.sweeneyops.lab, so for the sake of argument we’ll say that it’s 192.168.1.2.  Our code is much simpler.  It takes the domain name and the IP address of the first name server. It then uses that information to create the secondary zone.  All of the records were defined on the primary server, so there’s really not much left to do.  The code, which would be run on Server2, looks like this:

PARAM([string]$domain, [string]$IP)

# get the local host name
$localhost = $env:computername

dnscmd $localhost /zoneadd $domain /Secondary $IP /file "$domain.dns"

I could probably shorten it down to a single line, but I felt that it read more easily this way.  Feel free to modify it however you see fit.  So, there you have it. Simplified scripting of DNS through PowerShell. Enjoy!

Advertisements
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: