Managing Windows server DNS records from Linux commandline

I've been in the process of automating the creation of Apache VirtualHosts from the command line for some time now. What always annoyed me, was that after the vHost was generated, I had to manually add the DNS entry on our Windows server. Well…. No more!

After some talking with our IT guys, they told me of the (windows) command line tool for managing DNS entries ( dnscmd ), which lead me on a search for an equivalent Linux tool. I was happy enough to dig up the nsupdate tool, and after even more digging up, to find how to properly use it. The thing that amazed me the most was that it was MUCH simpler than expected!

The following command do not take into account authentication, because (for some reason unknown to me) our domain uses an unsecure policy -- in the zone properties, "Dynamic updates" is set to Nonsecure and secure, and thus was not a problem for me. I believe that if the server has joined the domain though, it won't make a difference, but cannot validate that claim.

Managing DNS records interactively

First, let's go through the interactive process - fire up a terminal ( in my case, via SSH ), and then on to the meat of things:


$ nsupdate
> update add my.domain.local 86400 A 10.11.12.13
> send
> answer
Answer:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:   2158
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 1, ADDITIONAL: 0
;; ZONE SECTION:
;domain.local.                 IN      SOA

;; UPDATE SECTION:
my.domain.local. 86400 IN     A       10.11.12.13

Let's see what just happened:

  • We ran the nsupdate command, and got a prompt ( > )
  • We asked to create an update message, which adds the record "my.domain.local", with TTL 86400, is of type A, and has the content 10.11.12.13
  • We then sent the message to the current DNS server
  • We asked to see the answer to our message.
    • The interesting bit here is status: NOERROR meaning that what we asked for was performed.

The operations that I've found supported (which are fine enough for me) are add and delete. Thus, to update a record you first delete and then re-create it.

A sample deletion message would be:


$ nsupdate
> update delete my.domain.local
> send
> answer
Answer:
;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id:  53365
;; flags: qr; ZONE: 1, PREREQ: 0, UPDATE: 1, ADDITIONAL: 0
;; ZONE SECTION:
;domain.local.                 IN      SOA
;; UPDATE SECTION:
my.domain.local. 0 ANY     ANY

And that's that. In my tests, I didn't have to authenticate at all ( Win 2003 R2 acting as Domain controller and DNS server ) - but I may have been in a trusted IP range, if you encounter issues let me know!

Managing DNS records via script

Though I would much prefer it, there is no direct way to send everything at once. But we do get the option to run a script that contains commands, so it amounts to the same thing.

What you basically do, is create a file that has the above commands (one per line, no blank lines), and pump that into nsupdate. That simple.

A small and mostly static example in PHP for doing so :


<?php

$file = "/tmp/dnsup";

$dns_commands <<< HERE
update delete my.domain.local 
update add my.domain.local   86400 A     10.11.12.13
update add your.domain.local 86400 CNAME my.domain.local
send 
answer
HERE;

file_put_contents($file, $dns_commands);

$answer = array();
exec('nsupdate /tmp/dnsup', $answer);

unlink('/tmp/dnsup');

As you can see, the above script does little in the way of being cautious, or checking for errors - but you should have the output of the command in the $answer array to check that everything was ok.

I've tested the above in both CentOS6 and CentOS7 (the latter having joined the domain as described in a previous article), and it seems to work just fine with our Windows 2003 R2 Active directory domain controller being the DNS server.

If you encounter any issues let me know in the comments below, and I'll try to give you a hand!

Best of luck!