Quick and Dirty Dynamic DNS Using GoDaddy


28,740

12

52

Introduction: Quick and Dirty Dynamic DNS Using GoDaddy

Need a quick and dirty answer for a (more or less) free Dynamic DNS provider? Well, if you use GoDaddy to register your domain, you have everything you need to do this.

Why would you need dynamic dns?

Imagine if you have some resources at home that you need to access when you're on vacation, but your ISP (I use Verizon FiOS) changes your IP address from time to time. Some providers, like Cable-based ISPs, change the IPs pretty frequently. Well, your choices are to go in and update your DNS record manually, use one of the free (typically restricted to their domain) or premium Dynamic DNS (DDNS) providers, or set up a simple bash script to detect the change and make the update in your own registered domain.

Plus, its free (free, if you already use GoDaddy).

Prerequisites

  1. GoDaddy-registered and managed domain. These are pretty inexpensive ($14.99/yr) and GoDaddy is the biggest registrar (at least in the US). Chances are if you have a domain name, you're probably using GoDaddy already. Plus, they throw in other features like mail forwarding and DNS zone management for free. They also have a nifty API that allows you to change you DNS records programmatically (more on that later).
  2. Some kind of server at your location that can run a bash script. The script is only a few lines and should be easily portable to php or even PowerShell, so you can make Windows-compatible versions too.

Step 1: Create Your DNS Name

First, you have to create your DNS name in GoDaddy (this assumes you have already registered a domain with GoDaddy).

GoDaddy provides several good resources on how to do this.

Add an A record in GoDaddy

I'm attaching a GIF-video from their web site that shows how easy it is.

For "Type" make sure to use "A" -- CNAME won't work.

For "Host" enter the hostname you'd like to use. I like to use "gateway" because it's how I reach the resources behind the entry point to my home network. FYI, I use ssh and rsa keys to tunnel in. I'm working on moving to a pfSense-based VPN, but that's still a work-in-progress.

For "Points to" you can enter anything you want. I use "1.1.1.1" so that it will be obvious my script is working once I run it. This is the value that will change when your ISP changes you IP address.

For "TTL" choose "Custom" then put in an arbitrarily short timeout. This tells systems that read this DNS record how long they should cache it before getting a new one. Typically, this is long (1 hour) for static DNS entries. It helps reduce DNS traffic on the general internet. For dynamic DNS, I like to use something shorter like 600 seconds (10 minutes). You don't want this to be too long because it governs the "switching" time between your old IP address and your new one. If this is an hour, it could take up to an hour to reach your dynamic resource after an IP change. NOTE: you can always flushdns at the endpoint, but sometimes intermediate DNS servers will cache the reply (again, to save on traffic).

The most important thing is to make sure it's an "A" record.

Step 2: Create a GoDaddy API Key

In order to make programmatic changes to the DNS records, you'll need a GoDaddy API key. Here is some background on the process first:

GoDaddy Developer "Get Started" Guide

The short version is, go to this link GoDaddy API Keys and click "Create New API key"

You'll want to give it a new name (I use "Dynamic DNS") and select an environment. GoDaddy recommends you test with the OTE environment first, then move to Production. You're using my code, so you can probably just create a production key.

Next, you'll see your API key and your key secret. Make sure you copy these down. The API key will still be visible when you come back to this screen, but the secret will never be displayed again and cannot be recovered!! If you lose the secret, you'll have to create a new key. HINT: Don't lose the secret.

Step 3: Create a Script to Update DNS

Here is a quick and dirty script you can use to determine your current IP, compare it to your DNS zone file, and update if needed. It's written for BASH (Un*x):

#!/bin/bash

mydomain="sos-obx.us"
myhostname="gateway"
gdapikey="api_key:key_secret"
logdest="local7.info"

myip=`curl -s "https://api.ipify.org"`
dnsdata=`curl -s -X GET -H "Authorization: sso-key ${gdapikey}" "https://api.godaddy.com/v1/domains/${mydomain}/records/A/${myhostname}"`
gdip=`echo $dnsdata | cut -d ',' -f 1 | tr -d '"' | cut -d ":" -f 2`
echo "`date '+%Y-%m-%d %H:%M:%S'` - Current External IP is $myip, GoDaddy DNS IP is $gdip"

if [ "$gdip" != "$myip" -a "$myip" != "" ]; then
  echo "IP has changed!! Updating on GoDaddy"
  curl -s -X PUT "https://api.godaddy.com/v1/domains/${mydomain}/records/A/${myhostname}" -H "Authorization: sso-key ${gdapikey}" -H "Content-Type: application/json" -d "[{\"data\": \"${myip}\"}]"
  logger -p $logdest "Changed IP on ${hostname}.${mydomain} from ${gdip} to ${myip}"
fi

Replace "mydomain" variable with the domain you registered. For example, if you registered "fredshouse.com" then the line should read:

mydomain="fredshouse.com"

Also replace "myhostname" with your hostname, "api_key" with you api key and "key_secret" with your key secret. It's important to note that the actual contents of "gdapikey" will be your api key followed by a colon (":") followed by the secret as one single string. If you get this wrong, the script will not work. Let's say your api key is "abcdefghijklm" and your key secret is "zyx987rst456" then your "gdapikey" will be "abcdefghijklm:zyx987rst456" -- one string with a colon separating the two parts. Again, this is IMPORTANT.

I saved this as /usr/local/sbin/gd-dyndns. Make sure your chmod 700 to both make it executable and to protect it from prying eyes. My script is owned by root (quick and dirty -- I warned you!!).

This script uses ipify.org to determine your current IP address (they return results in a code-friendly way) then compares to the current IP setting in GoDaddy. If they do not match, it uses the API to change the IP address.

I installed this as a cron job (crontab -e) and it runs every 10 minutes:

*/10 * * * *    /usr/local/sbin/gd-dyndns > /dev/null

You should go back to the GoDaddy DNS manager to verify that it updated properly.

That's it!! Quick and dirty but free if you already use GoDaddy as your registrar.

Step 4: Porting to Other Languages

I've given you the bash version. Porting to php should be super simple (use phpcurl). PowerShell might be a bit more of a challenge, but you should look at Invoke-WebRequest.

If the community likes this instructable but needs a php and/or PowerShell version, I might be inclined to write it and come back to update this article.

UPDATE:

Here is a version that works in PowerShell. You can add to the Task Scheduler.

$mydomain = "sos-obx.us"
$myhostname = "gateway" $gdapikey = "api_key:key_secret" $myip = Invoke-RestMethod -Uri "https://api.ipify.org" $dnsdata = Invoke-RestMethod "https://api.godaddy.com/v1/domains/$($mydomain)/records/A/$($myhostname)" -Headers @{ Authorization = "sso-key $($gdapikey)" } $gdip = $dnsdata.data Write-Output "$(Get-Date -Format 'u') - Current External IP is $($myip), GoDaddy DNS IP is $($gdip)" If ( $gpid -ne $myip) { Write-Output "IP has changed!! Updating on GoDaddy" Invoke-RestMethod -Method PUT -Uri "https://api.godaddy.com/v1/domains/$($mydomain)/records/A/$($myhostname)" -Headers @{ Authorization = "sso-key $($gdapikey)" } -ContentType "application/json" -Body "[{`"data`": `"$($myip)`"}]"; }

1 Person Made This Project!

Recommendations

  • Explore Science Challenge

    Explore Science Challenge
  • Furniture Contest

    Furniture Contest
  • Make it Real Student Design Challenge #3

    Make it Real Student Design Challenge #3

52 Comments

1
sumo1rev
sumo1rev

11 months ago

here my fix for powershell: https://pastebin.com/BrU36q1z
added a logfile.txt and fixed the match
also if you want to add to task (hidden and at startup) check my task (xml) or import it and change it
https://pastebin.com/TExt4nwu

run powershell with this arguments and with start in directory (the same of the script)
<Command>C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe</Command>
<Arguments>-noprofile -executionpolicy unrestricted -noninteractive -File C:\myScriptRUN\my_dns\mydns.ps1</Arguments>
<WorkingDirectory>C:\myScriptRUN\my_dns</WorkingDirectory>

and also choose any users to run it, so the script will be hidden (no blue screen for 3-4 sec)


0
paragonuk
paragonuk

Reply 22 hours ago

Log file is a great idea, but I personally thing working locally is a better approach, so that you can compare the WAN IP with the last IP in the log file only reaching GD DNS when is necessary, that is, for an update. Then, it doesnt matter how often you check, there wont be any risk of problems with GD due to too many request queries.

1
1_21gigawatts
1_21gigawatts

7 weeks ago

Thank you. Just what I needed.

0
roadrunner1024
roadrunner1024

3 months ago

just a quick one, powershell uses tls1.0 by default,
so you get this error:
Invoke-RestMethod : The request was aborted: Could not create SSL/TLS secure channel.

put this this line in at the beginning:
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

0
Web Sharp Studios
Web Sharp Studios

Tip 5 months ago on Step 3

DO NOT set your CronTab job to run every ten minutes. GoDaddy will shut you down faster than you know what happened. DHCP expirations are much longer than that typically

0
Web Sharp Studios
Web Sharp Studios

Tip 5 months ago on Step 4

Great article! I love GoDaddy I recommend them to all my clients. Here is an updated script that works with IPv6. Make sure your CronTab job runs at a lesser than or equal to interval for your DHCP expiration. If you use Comcast that expiration interval is every 6000 minutes. Here's the CronTab script as well...

***************

#!/bin/bash

mydomain="websharpstudios.com"
myhostname="@"
gdapikey=""

myip=`curl -s "https://api.ipify.org"`
dnsdata=`curl -s -X GET -H "Authorization: sso-key ${gdapikey}" "https://api.godaddy.com/v1/domains/${mydomain}/records/A/${myhostname}"`
gdip=`echo $dnsdata | cut -d ',' -f 1 | tr -d '"' | cut -d ":" -f 2`
echo "`date '+%Y-%m-%d %H:%M:%S'` - Current External IP is $myip, GoDaddy DNS IP is $gdip"

if [ "$gdip" != "$myip" -a "$myip" != "" ]; then
echo "IP has changed!! Updating on GoDaddy"
curl -s -X PUT "https://api.godaddy.com/v1/domains/${mydomain}/records/A/${myhostname}" -H "Authorization: sso-key ${gdapikey}" -H "Content-Type: application/json" -d "[{\"data\": \"${myip}\"}]"
fi

## IP 6 AAAA Records

myip=`wget -6 "https://ifconfig.co"`
dnsdata=`curl -s -X GET -H "Authorization: sso-key ${gdapikey}" "https://api.godaddy.com/v1/domains/${mydomain}/records/AAAA/${myhostname}"`
gdip=`echo $dnsdata | cut -d ',' -f 1 | tr -d '"' | cut -d ":" -f 2`
echo "`date '+%Y-%m-%d %H:%M:%S'` - Current External IP6 is $myip, GoDaddy DNS IP6 is $gdip"

if [ "$gdip" != "$myip" -a "$myip" != "" ]; then
echo "IP6 has changed!! Updating on GoDaddy"
curl -s -X PUT "https://api.godaddy.com/v1/domains/${mydomain}/records/AAAA/${myhostname}" -H "Authorization: sso-key ${gdapikey}" -H "Content-Type: application/json" -d "[{\"data\": \"${myip}\"}]"
fi

1
bootcamp20
bootcamp20

6 months ago

This was a big help. Thank you very much!

0
daveritchie
daveritchie

7 months ago

Great work Tod, I have been looking for something like this for a long time.

I am using the powershell script and noticed it runs fine on Windows 10, however when I move it on Windows Server 2016 Datacenter, I get the following error when connecting to https://api.godaddy.com.

"Invoke-RestMethod : The request was aborted: Could not create SSL/TLS secure channel"

To fix this included the following line before the "$myip = ....."

[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls"

And now it works as it should.

Dave

0
MikeysLab
MikeysLab

9 months ago

Here is a cleaner shell script:

#!/bin/bash
domain=$1
host=$2
APIKey=$3
APISecret=$4

WanIP=`curl -s "https://api.ipify.org"`

GDIP=`curl -s -X GET -H "Authorization: sso-key ${APIKey}:${APISecret}" "https://api.godaddy.com/v1/domains/${domain}/records/A/${host}" | cut -d'[' -f 2 | cut -d']' -f 1 | jq -r '.data'`

if [ "$WanIP" != "$GDIP" -a "$WanIP" != "" ]; then
curl -s -X PUT "https://api.godaddy.com/v1/domains/${domain}/records/A/${host}" -H "Authorization: sso-key ${APIKey}:${APISecret}" -H "Content-Type: application/json" -d " [{\"data\": \"${WanIP}\"}]"
fi

1
FedderSkovgaard
FedderSkovgaard

10 months ago on Step 4

There's a typo in the Powershell script at line 10:
"If ( $gpid -ne $myip) {"
should read:
If ( $gdip -ne $myip) {

Otherwise you are comparing $myip with an empty (non-initialized) variable
0
CristianC22
CristianC22

11 months ago

A good formulated query on Google pointed me to this brilliant article.
KUDOS to the writer, this is exactly what I was after for one of my clients using an unreliable ISP.
Respect and many thanks!

0
floydaroo
floydaroo

Question 11 months ago

Would you be able to update it with detailed instructions on making it run on startup and then once every 10 mins? I need help.

0
jesusdavidvaldivia
jesusdavidvaldivia

Reply 11 months ago

Omg!. i have to try it!, sounds great

0
Tod-SoS
Tod-SoS

Reply 1 year ago

Awesome!!!
I've thought about expanding this to cover the APIs for other DNS providers (cloudflare, rackspace, etc) and I'm glad to see it ported to other languages!!

0
jesusdavidvaldivia
jesusdavidvaldivia

11 months ago

Excelent!, if you are trying to make your record with a IPV6 Ip, remember thath your record type have to be AAAA

https://api.godaddy.com/v1/domains/${mydomain}/rec...

and Api IPV6 is https://api6.ipify.org with 6 after api

0
storageguy
storageguy

12 months ago

Tod - this is great!! Exactly what I was looking for to test some things out. Thank you!

0
KallumD
KallumD

1 year ago

I use subdomains so i tried using the script by "segihovav" but it was not working due to the GoDaddy IP (gdip) variable not being set. i have rewritten it slightly so that it updates all "A" records with your new IP. i have added the ability to set TTL as i noticed that using it without would set all "A" records to default to 600 seconds. only have to change line 2 ("Domain") , line 3 (API key) and line 5 (TTL).

https://pastebin.com/siqXYPTd

Hope this helps people using subdomains!

0
Tod-SoS
Tod-SoS

Reply 1 year ago

Awesome work! thnx

0
analystguy
analystguy

Question 1 year ago on Step 3

What am I doing wrong? I followed steps one through three but GoDaddy still shows my ip address as parked? CRON seems to be running but where is the file local7.info found?

May 4 16:20:01 eserver CRON[1083]: (root) CMD (/usr/local/sbin/gd-dyndns > /dev/null)
May 4 16:20:01 eserver CRON[1079]: (CRON) info (No MTA installed, discarding output)
May 4 16:30:01 eserver CRON[1096]: (root) CMD (/usr/local/sbin/gd-dyndns > /dev/null)
May 4 16:30:01 eserver CRON[1092]: (CRON) info (No MTA installed, discarding output)