DnsDynamic.org Registration under Windows

James Young · June 18, 2012

Recently I’ve been swapping over all my dynamic DNS needs across to DnsDynamic.org, which is a free and unlimited solution.  It’s fairly decent, and packs a DynDNS compatible interface so you can use ddclient under Linux.  However, I frequently want to register Windows machines, and so I wrote a simple Powershell script which can be run on a scheduled basis to register a machine.

#
# Registers a Windows machine with the DNS Dynamic service
#

Set-PSDebug -Strict

###############################################################################################

# To obfuscate (well, machine encrypt) a password, do this:
# (Get-Credential).Password | ConvertFrom-SecureString

$username = "ENTER USERNAME HERE"
$password = "ENTER OBFUSCATED PASSWORD HERE" | ConvertTo-SecureString
$hostname = "ENTER HOSTNAME HERE"
$ipsource = "iface:INTERFACE SUBSTRING:INTERFACE NUMBER"
#$ipsource = "web"

###############################################################################################

# Assemble the username/password into a credentials object
$creds = New-Object System.Net.NetworkCredential -ArgumentList $username, ([Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)))

# Determine the IP address to register
$ip = $null
write-host -NoNewLine "Determining IP address on host machine ... "
if ($ipsource -eq "web") {
try {
$wc = New-Object Net.WebClient
$ip = $wc.DownloadString("http://myip.dnsdynamic.org/")
} catch {
throw "Unable to fetch IP address from source '$ipsource': $_"
}
} elseif ($ipsource -match '^iface:(.+):([0-9]+)$') {
try {
$desc = $matches[1]
$num = $matches[2]
$ifaces = @(Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName . | Where-Object { $_.Description -like "*$desc*" })
if ($ifaces) {
$ip = $ifaces[0].IPAddress[$num]
}
} catch {
throw "Unable to fetch IP address for source '$ipsource': $_"
}
} else {
throw "Unknown IP source! Use 'web' or 'iface:interface name:number'"
}

if (! $ip) {
throw "Unable to retrieve IP address for source '$ipsource'!"
}

# IP has been retrieved. Now check if we're already registered with that IP, if so then do nothing.
write-host $ip
write-host -nonewline "Checking whether update required ... "
$dns = $null
try {
$dns = ([System.Net.Dns]::GetHostAddresses($hostname))[0].IPAddressToString
} catch {
throw "Could not complete DNS resolution for '$hostname': $_"
}

# Check if update is required, and if so, do it
if ($ip -eq $dns) {
write-host "no"
write-host "Update not required. Exiting ..."
} else {
write-host "yes"
write-host -nonewline "Committing update to dnsdynamic.org ... "
try {
# Configure request, using credentials defined above
$req = [System.Net.HttpWebRequest]::Create("https://www.dnsdynamic.org/api/?hostname=" + $hostname + "&myip=" + $ip)
$req.Credentials = $creds
$req.PreAuthenticate = $true
$req.Timeout = 30000

# Deliver the request and get the response
$resp = $req.GetResponse()
$respstream = $resp.GetResponseStream()
$sr = New-Object IO.StreamReader($respstream)
$result = $sr.ReadToEnd()
write-host $result
} catch {
throw "Unable to register: $_"
}
}

Configuration is pretty easy, just set the username field to your DnsDynamic.org username, and then generate the crypted version of your password using (Get-Credential).Password | ConvertFrom-SecureString and put that into the password field.  Hostname goes into the hostname field.

The ipsource field is more interesting.  If it’s just set to ‘web’, it will derive the external-facing IP address of your box.  Note that if you are using a proxy, this will be the address of the proxy!  This is probably the right solution for most users behind broadband routers and such.

If it’s set to ‘iface’, then the next argument is a string which should be inside the name of the network adapter you want to extract the IP address from.  Make sure you select a substring which is long enough that you won’t get multiple results (it always takes the first adapter anyway).  The second argument is the IP address index to use.  So if your adapter has more than one IP address, you can specify which IP address to use.  For most people, this index will be 0, indicating the first IP address.

The script verifies that the dynamic entry actually needs updating before trying to do so.  Note that you shouldn’t try and update your IP any more than once every 15 minutes, although as long as your IP hasn’t actually changed, the script won’t hit the DnsDynamic.org API at all if that happens.  Running it once every few hours should be enough for most purposes.

Twitter, Facebook