2010-11-14

A BASH SCRIPT TO MANAGE DYNAMIC DNS

Have you ever wanted to host a site on your home linux box or simply reach your home PC from outside? If yes, you have come to the right place.

For this you will need an account and a DNS from one of the many services that offer dynamic DNS update. The most popular is DynDNS where you can get a free sub-domain on one of their registered domains. If you instead want to have a more professional solution I normally recommend eNom, where you will have to register your own domain.
In this article I will cover both the above mentioned services (and others) but nothing stops you from using the same technique on virtually every dynamic DNS service.

Before we start make sure that you have "curl" installed on your linux box; if not:

apt-get install curl (for all debian based linux distributions)
yum install curl (for all redhat based linux distributions)

For all other distributions you can find it at http://curl.haxx.se/download/curl-7.21.2.tar.gz

Let's prepare all files we will need. As root create a directory called /etc/dynip_scripts, move into it and create the following files:
touch cur_addr (it will be used to store our current address)
touch update_dns (our bash script)
touch log_new_dns (a log for all new addresses)
touch log_unchanged_dns (a log for all unchanged DNS)

Now we get to the scripting side of our solution.
Updating your DNS takes 2 steps: finding your current address and pushing it to a dynamic DNS service.

Step 1) we need to find out our IP address. we have several ways to accomplish this task but I will focus on two most generic cases: linux handles your DSL connection or you have a router to connect to the Internet.
If linux is handling the connection, there should be an interface created to access the Internet (something like ppp0).
In this case "ifconfig" command will return your current address. Unfortunately ifconfig returns a plethora of useful information, totally unnecessary though for us at present.
We need to filter the output in order to get the current ip address.
Bash has all the instruments need:

ifconfig ppp0 | grep -i "addr:" | cut -f2 -d: | cut -f1 -d " "

The above command returns your IP address stripped of all other information

If instead a router is handling your connection you need to rely on external services to get the IP address. DynDNS hosts a basic public page to identify your address.

curl --silent http://checkip.dyndns.org | cut -f6 -d " " | cut -f1 -d "<"

If that doesn't work you can use a service I am hosting on my web server.
curl --silent http://www.intellisan.eu/get_ip.php?auth=210873 | grep IPAddress | cut -f2 -d:


Step 2) communicating your address to a DynDNS or eNom. Both services support updating your address through the querystring.
Once obtained a valid account and a DNS, whether a subdomain from DynDNS or your own registered domain from eNom, here are examples of working querystrings.

- DynDNS (I registered a subdomain of their homelinux.org domain called "qatqat", but you obviously will register your own). I will be therefore updating qatqat.homelinux.org, which you will replace with yours:

curl -u your_username:your_password "http://members.dyndns.org/nic/update?hostname=qatqat.homelinux.org&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG&myip=your_ip_address"

If you are using eNom instead here is the querystring:
curl "https://reseller.enom.com/interface.asp?command=setdnshost&hostname=your_hostname&zone=your_domain&domainpassword=your_password&address=your_ip_address"


Now let's put all of this in our bash script update_dns. Edit it with your favorite text editor and copy the text below in it. In the script I have also included some more nifty features such as obtaining your address from a NETGEAR router, updating a no-ip or everyDNS dynamic domain address, or sending an alert email after the DNS is updated.


#!/bin/bash

#get the address stored in the cur_addr file
export CUR_IPADDR=$(cat /home/antonio/cur_addr)

#obtain IP address, uncomment all options that you will be using
export DYNIP_ADDR=$(curl --silent http://checkip.dyndns.org | cut -f6 -d " " | cut -f1 -d "<") #intellisan.eu server
#export DYNIP_ADDR=$(curl --silent http://www.intellisan.eu/get_ip.php?auth=210873 | grep IPAddress | cut -f2 -d:)

#GET ADDRESS FROM NETGEAR ROUTERS (tested with DG834 or other similar firmware)
#export DYNIP_ADDR=$(curl --silent -u admin:your_router_password http://192.168.1.1/setup.cgi?next_file=s_status.htm | grep -A1 -m1 "IP Address" | grep -v "IP Address" | cut -d ">" -f2 | cut -d "<" -f1) #obtain your IP address from ifconfig command - it only works if linux is handling your internet connection directly
#export DYNIP_ADDR=$(ifconfig ppp0 | grep -i "addr:" | cut -f2 -d: | cut -f1 -d " ")


#now we compare the current address with the one stored in the cur_addr file
if [ "$CUR_IPADDR" = "$DYNIP_ADDR" ]; then

#if the address has not changed we simply log it
echo "$(date) - unchanged address " >> /home/antonio/log_unchanged_dns

else

#if the address has changed instead we log it and carry on with the rest

we update the cur_addr file
echo "$DYNIP_ADDR" > /home/antonio/cur_addr

#we log an entry in the log_new_dns file
echo "$(date) - New IP $DYNIP_ADDR" >> /home/antonio/log_new_dns


#now we update our dynamic address on DynDNS
curl -u your_username:your_password "http://members.dyndns.org/nic/update?hostname=your_subdomain.homelinux.org&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG&myip="$DYNIP_ADDR

#uncomment the line below if instead you are using eNom
#curl "https://reseller.enom.com/interface.asp?command=setdnshost&hostname=your_hostname&zone=your_domain&domainpassword=your_password&address="$DYNIP_ADDR


#here are strings for more services
#everydns.net

#curl --silent -u your_username:your_password "http://dyn.everydns.net?ver=0.1&domain=your_domain&ip="$DYNIP_ADDR

#no-ip
#curl --silent "http://your_username:your_password@dynupdate.no-ip.com/nic/update?hostname=yourhostname.domain&myip="$DYNIP_ADDR


#now our final touch. we send an email to inform you of the new address
echo "YOUR PUBLIC IP ADDRESS HAS CHANGED TO $DYNIP_ADDR ON $(date)" | mail -s "a service message from my server" your@yourdomain.com





Now, all is left to do is to make the update_dns script executable and hidden to normal users and then create an entry in /etc/crontavb that will execute it every 20 minutes.

Always as root execute the commands below:

chmod 700 /etc/dynip_scripts/update_dns

echo "10,30,50 * * * * root /etc/dynip_scripts/update_dns > /dev/null 2>&1" >> /etc/crontab


This is it really.


Feel free to use and modify this script as you please, comments and suggestions are anyway appreciated.
This script can be adjusted to work with basically all dynamic DNS services by simply adding lines with the curl command for the appropriate querystring.
I just did not have the time to discover many other services' querystrings so if you happen to find them out kindly post a comment here.

Cheers,

QatQat

Nessun commento:

Posta un commento