Best DDNS alternatives to DYNDNS(LINUX CLIENT FOR DNSPOD

If you own a top-level domain and want to point it to a server in your home or office, you don't have to use paid services offered by dyn.com orother DDNS service providers. There exist better free solutions. DNSPOD is one of these free DDNS services. DNSPOD is free DNS service from China and it provides very fast DNS update. Once you update your domains to new IP in your account, you can see the change almost instantly. Best of all, they have an API which allows you to write your own script to update your account automatically.

Based on this API, i have written a shell script to sync up my dynamic home IP to my domain and it works seamlessly. This script should work on any LINUX distribution including Openwrt, DDWRT, ubuntu, centos, debian. first, you need to point your custom
nameservers to DNSPOD's DNS server in your domain registrar account. Then you create an free DNSPOD account from https://www.dnspod.com. Then, you save the following script to file named lino-dnspod and add execution permission to it. After that , you can follow the steps outlined below to begin using the service

Create Your Domain in DNSPOD account

lino-dnspod -C example.com

Create Your Record in DNSPOD account

lino-dnspod -u example.com

After you run the command to update record, the script will go into background and update your record automatically as ip changes

#!/bin/sh
#written by benson huang
#admin@gizfun.com
curl_status=`which curl 2>/dev/null`
[ -n "$curl_status" ] || { echo "curl is not installed";exit 3; }
#dnspod account
email='admin@gizfun.com
#dnspod password
password='xxxxxxx'
sub_domains='www ftp @'
API_url="https://dnsapi.cn"
pub_ip_addr=$(curl -s http://checkip.dyndns.com | sed -n 's/.*: \([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p')
format='json'
lang='en'
record_type='A'
offset="2"
length=""
os=$(uname -a | egrep -io 'openwrt' | tr [A-Z] [a-z])
shared_data="login_email=$email&login_password=$password&format=$format&lang=$lang&"
PROGRAM=$(basename $0)
#check for changed ip every 300 seconds
wait=300

getJsonValue(){
      params="$1"
 echo $json_data | sed 's/\\\\\//\//g' | sed 's/[{}]//g;s/\(\[\|\]\)//g' |\
 awk -F ',' '{ for (i=1;i<=NF;i++) { print $i }}' |\
 sed 's/":/\|/g;s/"//g' |\
 awk -v k="$params" -F'|' '{ if ($(NF - 1) == k )  print $NF }'
}

getDomainId() {
     local json_data=`curl -k -A 'xddns' $API_url/Domain.info -d ${shared_data}domain=$domainname`
          getJsonValue id
 }
 
getRecordId() {

  for sub_domain in $sub_domains;do

      local json_data
      json_data=$(curl -k -A 'xddns' $API_url/Record.List -d\ "${shared_data}record_type=$record_type&domain_id=$domain_id&sub_domain=${sub_domain}&offset=${offset}&length=${length}")
	  
	   #check if record type is NS
	   IS_NS=$(getJsonValue type | grep -o 'NS' | head -n1)
	   
      #if there are 3 @ subdomains, get the non-NS record id only
     if [ "$IS_NS" = "NS" ];then
	     
		 numofline=$(getJsonValue id | sed '/^[0-9]\{7\}$/d' | wc -l)
		 
		[ $numofline -eq 3 ] && tmp_result_id="$(getJsonValue id | sed '/^[0-9]\{7\}$/d' | head -n1 )" || continue

     else  
	       tmp_result_id="$(getJsonValue id | sed '/^[0-9]\{7\}$/d')"
	 fi	
	        #if result_id is not empty or unset, append a space to split record id
		   result_id="${result_id:+${result_id} }${tmp_result_id}"
		
  done
	  
      echo $result_id
      exit
}

createDomain() {
      curl -k -A 'xddns' $API_url/Domain.Create -d ${shared_data}domain=$domainname
       exit
}

createRecord() {
             for sub_domain in $sub_domains;do

             local extra_data="&domain_id=$domain_id&sub_domain=$sub_domain&record_type=$record_type&record_line=默认&value=${pub_ip_addr}"
             curl -k -A 'xddns' $API_url/Record.Create -d $shared_data"$extra_data"			 
            done
}

updateRecord() {

         local record_id_list=`getRecordId`
         tmp_sub_domains=${sub_domains}

         for record_id in $record_id_list;do

                 sub_domain=$(echo $tmp_sub_domains | awk '{ print $1 }')
                 tmp_sub_domains=${tmp_sub_domains#* }

      local extra_data="&domain_id=$domain_id&sub_domain=${sub_domain}\
          &record_type=${record_type}&record_line=默认&value=${pub_ip_addr}&record_id=$record_id"

      curl -k -A 'xddns' $API_url/Record.Modify -d $shared_data"$extra_data"

          done
}

		
removeRecord(){

             read -p "list the subdomains to be deleted " subdomain

                 sub_domains="$subdomain"
				 
				 for sub_domain in $sub_domains;do

                   record_id=`getRecordId`
				   
                  local extra_data="&domain_id=$domain_id&record_id=$record_id"
                  curl -k -A 'xddns' $API_url/Record.Remove -d $shared_data"$extra_data"
			    done

                 exit
				
 }



checkip() {
          oldip=$pub_ip_addr
          newip=$(curl -s http://checkip.dyndns.com | sed -n 's/.*: \([0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\).*/\1/p')

                  if [ "$newip" != "$oldip" ];then
                        oldip="$newip"
                        return 8
                  else
                        return 3
                  fi
}

 if [ $# -ne 2 ];then
      echo "usage:$PROGRAM |-c create record|-r remove records|-C create new domain|-m modify record | -bc create a batch of records DOMAIN [eg.example.com]"
          exit 3
 fi

 [ -n "$2" ] && domainname=$2

domain_id=`getDomainId $domainname`


  case $1 in
          -c)createRecord $domainname;;
          -r)removeRecord $domainname;;
          -u)updateRecord $domainname;;
          -C)createDomain $domainname;;
          -i)getRecordId $domainname;;
          *) echo "no such option";
             exit 3;;
  esac


 while [ 1 ];do

          checkip
		  
       if [ $? -eq 8 ];then
               pub_ip_addr="$newip"
               updateRecord
       fi
	   
       sleep $wait


done

NOTE:if you paste this script into vi editor or other text editors, you need to make sure that Chinese characters can be displayed and saved properly.Otherwise, the record line value will be invalid.

basic usage

Create a new domain
lino-dnspod -C example.com

Create a new record
lino-dnspod -c example.com

Remove a record
lino-dnspod -r example.com

Update a record
lino-dnspod -u example.com