GoDaddy DynDNS for the poor

Recently, I bought a fresh new domain from godaddy.com for my personal homepage that hosted on a server at home. Admittedly, I didn’t really spend any time on customer satisfaction or the stuff they support, they just had the cheapest offer for a .me domain :-) So after getting used to their cluttered web interface, I discovered they don’t support dynamic DNS in any way. In such a case, you have several options:

1. Transfer the domain to a registrar that offers dynamic DNS service

The obvious though costly solution if you just bought the domain. It can also take months to complete so that usually a non-option.

2. Use a CNAME and point it do a your DynDNS provider-supplied domain

However, this means only a subdomain (usually www) would point to your dynamic DNS domain. As an example, this is how it would look in my case:

www.peilicke.me -> duff.i324.me

There’s a simple guide in the GoDaddy forum to achieve that with their web interface. But that means wasting the actual domain, not nice.

3. Use the name servers of your DynDNS provider

GoDaddy (and other registrars) allow to replace the name servers and you could use those from your DynDNS provider given they allow it. This is how you could do it with dyndns.org. However, they started charging for that a while ago, to bad.

4. Do it yourself

You only need a script that discovers the public IP assigned to you by your ISP and write a little screen-scraper that logs into go GoDaddy’s ZoneFile Editor ™ fills and submit the A record form. Turns out that other people already had (and solved) those issues, so this is how it could look like:

#!/usr/bin/env python

import logging
import pif
import pygodaddy

logging.basicConfig(filename='godaddy.log', format='%(asctime)s %(message)s', level=logging.INFO)
GODADDY_USERNAME="@USERNAME@"
GODADDY_PASSWORD="@PASSWORD@"
client = pygodaddy.GoDaddyClient()
client.login(GODADDY_USERNAME, GODADDY_PASSWORD)

for domain in client.find_domains():
    dns_records = client.find_dns_records(domain)
    public_ip = pif.get_public_ip()
    logging.debug("Domain '{0}' DNS records: {1}".format(domain, dns_records))
    if public_ip != dns_records[0].value:
        client.update_dns_record(domain, public_ip)
        logging.info("Domain '{0}' public IP set to '{1}'".format(domain, public_ip))

Depending on where you want to run the script, you may need to fetch the dependencies. In my case it’s running on a Synology DiskStation 213. Underneath it’s amazing software stack is an embedded Linux with Busybox. Luckily, it already has a Python interpreter, so for me a wrapper script looks like:

#!/bin/sh
OLD_PWD=$PWD
ROOT_DIR=$(dirname $0)
cd $ROOT_DIR
if [ ! -d .venv27 ] ; then
  curl -O https://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.9.tar.gz
  tar xvfz virtualenv-1.9.tar.gz
  python virtualenv-1.9/virtualenv.py .venv27
fi
source .venv27/bin/activate
pip install -q --upgrade pif pygodaddy
./godaddy.py
deactivate
cd $OLD_PWD

Since your ISP will cut your connection every 24 hours (usually during the night), you would want to continuously run this script by putting it into /etc/crontab. On the DiskStation, you have to use tabs, not spaces and you have to restart crond after editing (It’s explained in the German wiki):

<br />*/5 * * * * root /path/to/godaddy.sh<br />

That’s it.

About these ads

34 thoughts on “GoDaddy DynDNS for the poor

  1. Would you be able to expand on your DYI option and provide other examples. I don’t have programming background and I would like to use this following subdomain vpn.xyz.com and update above script. What info would I have change and what script would I run on Suse server? Thx

  2. It heavily depends. Some services provide an API which one can use. Godaddy does not so I use a screenscraper. The virtualenv approach for Python software should work out of the box but openSUSE provides very comprehendive Python packages which one could use. Currently the script is rather godaddy-specific. For extending it to other domain registrars, I likely need some credentials and a test domain. Some donation wouldnt hurt either :-)

  3. In my case I have my own domain on Godaddy and I would like to do exactly what you did for my subdomain (ex. vpn.xyz.com). If I were to run this on SuSe box (which I have) what script should I use and what modification should I made in order for this script to obtain my ISP IP and log in to my GoDaddy account to update A record? Looking at at script wrapper I don’t see any info related to GoDaddy credentials.

  4. Ah, now i understand. Just put replace @USERNAME@ and @PASSWORD@ with your credentials. The script updates all domains. To update only a specific one replace client.find_domains() with ["my.sub.domain"].

  5. When I execute script I am getting following output. I have replaced client.find_domains() with vpn.xyz.com (my subdomain).

    linux-5swp:/etc/cron.hourly # sh godaddy
    godaddy: line 2: $’\r': command not found
    godaddy: line 3: import: command not found
    godaddy: line 4: import: command not found
    godaddy: line 5: import: command not found
    godaddy: line 6: $’\r': command not found
    godaddy: line 7: syntax error near unexpected token `filename=’godaddy.log’,’
    ‘odaddy: line 7: `logging.basicConfig(filename=’godaddy.log’, format=’%(asctime)s %(message)s’, level=logging.INFO)

  6. it seems you tried to invoke the Python script with Bash. Use “# python godaddy” instead or simply “# ./godaddy” (assuming executable bits set accordingly). Sorry for the late reply, been traveling for a while.

  7. 19 lines for the first and 14 for the second ..

    thought may not have been browser problem, so also tried ie, but simply cannot get whole listing ..

  8. ok .. sorry .. thought there would be an end to the for loop .. and if statement ..

    many thanks ..

    will experiment ..

  9. Hello, thanks for this post, this would be very useful for me too, however, for some reasons, it does not work for me. I’m also trying to get it work with only one specific domain (a subdomain to be precise) like Rafal. I replaced client.find_domains() with my domain like:
    for domain in ["mysub.mydomain.com"]:

    But I get the following error:

    Traceback (most recent call last):
    File “./godaddy.py”, line 17, in
    if public_ip != dns_records[0].value:
    IndexError: list index out of range

    I haven’t learned python, but I guess the dns_records[0] is empty/null? Maybe client.find_dns_records(domain) couldn’t fetch it? Do you have any idea what could be the cause of this? (Now I tried, and when giving a main domain – not a subdomain of it-, it works!)

    Thanks in advance!

  10. Ok, I figured out that I need to use the main domain, and the dns_records[n] will point to the needed A entry (like my subdomains). But when I use the “client.update_dns_record(domain, public_ip)” it will update every dns_records[] element I guess. So modifying only one specific dsn record is not possible? :(

  11. Well, I could finally manage it. I needed to use my main domain in the for statement. Then check on godaddy dns zone file, which A line is for my subdomain (this is only needed for the comparison with the actual IP). It was the 3rd line, stored in “dns_records[2]“. In the “client.upgrade_dns_record()” you can use a subdomain only in “client.find_dns_record()” you can’t. So this is how it worked:

    for domain in ["mydomain.com"]:
    dns_records = client.find_dns_records(domain)
    public_ip = pif.get_public_ip()
    logging.debug(“Domain ‘{0}’ DNS records: {1}”.format(domain, dns_records))
    if public_ip != dns_records[2].value:
    client.update_dns_record(“sub.mydomain.com”, public_ip)
    logging.info(“Domain ‘{0}’ public IP set from ‘{1}’ to ‘{2}'”.format(domain, dns_records[2].value, public_ip))

    I hope it’s understandable :)

  12. hi there,
    anywhere that i could find a detailed instruction to install ur DIY option on my DSM plz.
    sorry I am not neither linux or programming expert

  13. Can you be more specific about the issues you are facing? This script is supposed to work only with GoDaddy DynDNS. In general you have to put both scripts into any directory, replace the dummy credentials with yours and run the wrapper script. That should update your public IP in GoDaddy’s web interface. For that to happen regularly, you need to set up a cron job.

  14. Thanks this is exactly what I was looking for!
    I’ve written a version based on what you and agocska have done that will loop through multiple domains and host names to change whichever ones you choose. I’m not a programmer and have never played with Python before. Can you check this over and offer corrections? (fully commented)
    ————— CODE ————————
    #!/usr/bin/env python
    import logging # creates a log file
    import pif # public address checker
    import pygodaddy # “… a 3rd-party client library … to make GoDaddy suck less.”
    logging.basicConfig(filename=’godaddy.log’, format=’%(asctime)s %(message)s’, level=logging.INFO) #setup the log file
    GODADDY_USERNAME=”@USERNAME@” # replace @USERNAME@ with godadday login id
    GODADDY_PASSWORD=”@PASSWORD@” # ditto for password
    client = pygodaddy.GoDaddyClient() # set client as pygodaddy
    client.login(GODADDY_USERNAME, GODADDY_PASSWORD) # login
    domains_list = ["@DOMAIN_NAME@", "@DOMAIN_NAME@", "@DOMAIN_NAME@"] # replace @DOMAIN_NAME@ with domain names i.e. “linux.com”
    hosts_list = ["@HOST_NAME@", "@HOST_NAME@", "@HOST_NAME@" ] # replace @HOST_NAME@ with just the host names i.e. “www” use “@” for bare domain name
    public_ip = pif.get_public_ip() # set public_ip to the internet routeable address
    for target_domain in domain_list: # loop through the list of domain names
    for target_host in hosts_list: # loop through the list of host names that may be under the current domain
    for subdomain in client.find_dns_records(target_domain): # loop through all the A-Records for current domain
    if subdomain.hostname == target_host: # if the current hostname matches our target then
    fq_subdomain = (“{0}.{1}”.format(subdomain.hostname,domain)) #concatinate the host name with the domain
    loggin.info(“Found subdomain ‘{0}’ as ‘{1}’”.format(fq_subdomain,subdomain.value) # log the current IP
    if public_ip != subdomain.value: # if the current ip value is not the same as the public IP then
    client.update_dns_record(fq_subdomain, public_ip) # change it
    loggin.info(“Changed subdomain ‘{0}’ to ‘{1}’”.format(fq_subdomain,public_ip) # log the new IP
    else: # no change needed
    logging.info(“No change to subdomain ‘{0}’ address needed”.(fq_subdomain) # log no change made
    # end of if-then – Python does not use conditional end
    # end of if-then
    # end of subdomain for-loop – Python does not use a loop end
    #end of target_host for-loop
    #end of target_domain for-loop
    # end of script – Python does not like to talk about endings.
    —————— End Code ————-

  15. Hi,

    What would you name these scripts, and which folders to place them in linux like Ubuntu. And how would you run it like any default index.php a simple instruction on configuring the files on the server would greatly appreciated… Very interesting code cheers…

  16. Do you have a bitcoin wallet address? I was hoping to make a small donation for the “Do It Yourself DynDNS” python script that I am now using. Works great!

  17. Hi,

    I have a domain and subdomain in Godaddy. I’m using a remote desktop application to access my clients PC’s named ScreenConnect that works like TeamViewer but it is installed on a server at home. To access the application I go to my subdomain. My problem is that every time my ISP changes my IP, I have to access the server via TeamViewer, check the public IP, go to Godaddy and change the subdomain “POINTS TO” section.

    Long story short… I HAVE NO CLUE how to run your Script or where to run it. Could you please help me? I’m not an expert on PHP nor other programming language.

  18. Since the script updates to the public IP (assigned by your ISP) of the machine it’s running on, you have to run it on the server you want to expose to the internet. On that server, you need at least a Python interpreter and bash (for the wrapper script). That means something Unix-like (Linux, Mac OS, you name it). If you’re running a Windows server, you would need to change the bash script into a Windows batch script. Either way, the Python skript needs to be invoked regularly. That’s easiest on Linux with cron. But if you’re in a (para)virtualized LAMP-Stack environment, a pure-PHP solution is probably an easier choice.

  19. The server is running Windows and the Screenconnect app is installed in there. What do a I have to install in there?

  20. Brilliant script, thank you. I was in the middle of writing one in Java, this is a a lot more elegant :)

  21. I have a DDWRT router with cron window in the setup area would this just work as a copy paste and run from that environment or what would need be changed to make this work under the DDWRT environment? Figure this device would be the first appliance on the network so the best place to run this from not from a linux box.

  22. I have a DDWRT router with cron window in the setup area would this just work as a copy paste and run from that environment or what would need be changed to make this work under the DDWRT environment? Figure this device would be the first appliance on the network so the best place to run this from not from a linux box. Opps forgot the notify options boxes

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