Quick and Dirty Dynamic DNS Using GoDaddy

13,239

9

41

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)`"}]"; }

Be the First to Share

    Recommendations

    • Pocket-Sized Speed Challenge

      Pocket-Sized Speed Challenge
    • Super-Size Speed Challenge

      Super-Size Speed Challenge
    • Audio Challenge 2020

      Audio Challenge 2020

    41 Discussions

    0
    floydaroo
    floydaroo

    Question 7 days 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 days ago

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

    0
    Tod-SoS
    Tod-SoS

    Reply 6 weeks 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 days 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

    18 days ago

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

    0
    KallumD
    KallumD

    24 days 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 22 days ago

    Awesome work! thnx

    0
    analystguy
    analystguy

    Question 8 weeks 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)

    0
    Tod-SoS
    Tod-SoS

    Answer 8 weeks ago

    local7.info isn't a file, it's a facility in syslog. Try running the script from the command line and paste your output here (obfuscate any details you don't want published).

    0
    analystguy
    analystguy

    Reply 8 weeks ago

    Hi Todd
    My issue yesterday was that I was using an OTE key. I made the necessary target ote adjustment in GoDaddy api address shown in the script but could not get the DNS to update.

    Here is the bash script I am using this morning after having created production keys. CRON runs every 10 mins but again fails to update DNS. Odd given that when I ran the powershell script, the DNS changed. So it remains for me to figure out why the bash script fails.

    Dave

    #!/bin/bash
    mydomain="edomainname.com"
    myhostname="gateway"
    gdapikey="myproductionkey:mysecretkey"
    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

    0
    Tod-SoS
    Tod-SoS

    Reply 8 weeks ago

    Can you run the script from the bash command line and post the output? I'm figuring that your curl command is failing. Also, whats is your OS version and curl version?

    0
    analystguy
    analystguy

    Reply 8 weeks ago

    So the script works if I run bash from the command line but not when I run it from crontab!
    I am running buster lite (Debian) on a raspberry pi 3 B+. Do I need to append .sh to the gd-dyndns (gd-dyndns.sh)? Maybe it's a permissions issue?

    0
    Tod-SoS
    Tod-SoS

    Reply 8 weeks ago

    You might want to fully path curl in the script. In raspbian, I think it's /usr/bin/curl -- make sure you modify all instances. Also, redirect the cron output to a file instead of /dev/null to get some useful info. Try:

    */10 * * * * /usr/local/sbin/gd-dyndns >> /tmp/gdout.txt 2>&1

    This should redirect stdout and stderr to a temp file at /tmp/gdout.txt. Examine that file after a run to see what it's complaining about.

    0
    analystguy
    analystguy

    Reply 7 weeks ago

    HI Todd
    Everything is working as it should. The issue was the script privileges . After chmod 700 everything is bliss. Thanks nks for your help.
    dave

    0
    Tod-SoS
    Tod-SoS

    Reply 7 weeks ago

    Very cool. Thanks for using my instructable!

    0
    analystguy
    analystguy

    Reply 8 weeks ago

    from the command line
    pi@server1:/usr/local/sbin $ bash gd-dyndns
    2020-05-05 15:42:03 - Current External IP is 24.89.x.x, GoDaddy DNS IP is 1.1.1.1 Updating on GoDaddy
    pi@server1:/usr/local/sbin $

    0
    Tod-SoS
    Tod-SoS

    Reply 8 weeks ago

    OK. I see you're running on a Raspberry pi. Bash is doing something with the exclamation marks in the echo statement. Remove them and replace with a period, as in:

    echo "IP has changed. Updating on GoDaddy."

    When I just run the command: echo "Hello!!" in bash on a pi, the shell expands the "!" and fills with an "exit" which seems to be making your script end prematurely. Let me know if this helps. If it fails, run from command line again and send me the new output.

    0
    analystguy
    analystguy

    Reply 8 weeks ago

    It is now working. My issue was that the file was not executable. While I thought I did a chmod 700 on it, I apparently didn't as it showed only rw privilege. Another chmod 700 fixed it and it is now working. Thanks for all your help.