Linux部署阿里云解析ddns

1、安装依赖

yum install -y bind-dig curl openssl-util

 

2、获取DomainRecordId

修改main函数,在里面调用describe_record,如:

main()
    {
        describe_record
        #update_record
    }

然后执行这个脚本。如果没问题的话,就能获取到域名的所有解析记录的列表了:

{"PageNumber":1,"TotalCount":1,"PageSize":1,"RequestId":"0000","DomainRecords":{"Record":[{"RR":"www","Status":"ENABLE","Value":"8.8.8.8","RecordId":"21332133","Type":"A","DomainName":"example.com","Locked":false,"Line":"default","TTL":"600"},]}}HttpCode:200

上面的结果中,RecordId为21332133。得到结果后再修改DomainRecordId为正确的值。

修改main函数:

main()
    {
        #describe_record
        update_record
    }

 

3、定时执行如下脚本

修改如下参数

AccessKeyId="MyID"
AccessKeySec="MySecret"
DomainRecordId="00000"
DomainRR="www"
DomainName="example.com"
DomainType="A"
DNSServer="dns9.hichina.com"

完整脚本

#!/bin/bash

#Dependences: bind-dig, curl, openssl-util, tr, sort

## ----- Setting -----
AccessKeyId="xxx"
AccessKeySec="xxx"
DomainRecordId="xxx"
# DomainRR, use "@" to set top level domain
DomainRR="www"
DomainName="example.com"
DomainType="A"
# DNS Server for check current IP of the record
# Perferred setting is your domain name service provider
# Leave it blank if using the default DNS Server
DNSServer="dns9.hichina.com"

# The server address of ALi API
ALiServerAddr="alidns.aliyuncs.com"
# A url provided by a third-party to echo the public IP of host
#MyIPEchoUrl=""
MyIPEchoUrl="http://whatismyip.akamai.com"

# the generatation a random number can be modified here
#((rand_num=${RANDOM} * ${RANDOM} * ${RANDOM}))
rand_num=$(openssl rand 16 -hex)

## ----- Log level -----
_DEBUG_=true
_LOG_=true
_ERR_=true


## ===== private =====

## ----- global var -----
# g_pkey_$i    # param keys
# g_pval_$key  # param values
g_pn=0         # number of params
_func_ret=""


## ----- Base Util -----
_debug()	{ ${_DEBUG_} && echo "> $*"; }
_log() 		{ ${_LOG_}   && echo "* $*"; }
_err() 		{ ${_ERR_}   && echo "! $*"; }
reset_func_ret()
{
	_func_ret=""
}

## ----- params -----
# @Param1: Key
# @Param2: Value
put_param()
{
	eval g_pkey_${g_pn}=$1
	eval g_pval_$1=$2
	g_pn=$((g_pn + 1))
}

# This function will init all public params EXCLUDE "Signature"
put_params_public()
{
	put_param "Format" "JSON"
	put_param "Version" "2015-01-09"
	put_param "AccessKeyId" "${AccessKeyId}"
	put_param "SignatureMethod" "HMAC-SHA1"
	put_param "SignatureVersion" "1.0"

	# time stamp
	local time_utc=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
	_debug time_stamp: ${time_utc}
	put_param "Timestamp" "${time_utc}"

	# random number
	_debug rand_num: ${rand_num}
	put_param "SignatureNonce" "${rand_num}"
}

# @Param1: New IP address
put_params_UpdateDomainRecord()
{
	put_param "Action" "UpdateDomainRecord"
	put_param "RR" "${DomainRR}"
	put_param "RecordId" "${DomainRecordId}"
	put_param "Type" "${DomainType}"
	put_param "Value" "${1}"
}

put_params_DescribeDomainRecords()
{
	put_param "Action" "DescribeDomainRecords"
	put_param "DomainName" ${DomainName}
}

pack_params()
{
	reset_func_ret
	local ret=""
	local key key_enc val val_enc

	local i=0
	while [ $i -lt ${g_pn} ]
	do
		eval key="\$g_pkey_${i}"
		eval val="\$g_pval_${key}"
		rawurl_encode "${key}"
		key_enc=${_func_ret}
		rawurl_encode "${val}"
		val_enc=${_func_ret}

		ret="${ret}${key_enc}=${val_enc}&"
		i=$((++i))
	done

	#delete last "&"
	_func_ret=${ret%"&"}
}


# ----- Other utils -----
get_my_ip()
{
	reset_func_ret
	local my_ip=$(curl ${MyIPEchoUrl} --silent --connect-timeout 10)

	_func_ret=${my_ip}
}

get_domain_ip()
{
	reset_func_ret
	local full_domain=""
	if [ -z "${DomainRR}" ] || [ "${DomainRR}" == "@" ] ; then
		full_domain=${DomainName}
	else
		full_domain=${DomainRR}.${DomainName}
	fi

	local ns_param=""
	if [ -z "${DNSServer}" ] ; then
		ns_param=""
	else
		ns_param="@${DNSServer}"
	fi
	_func_ret=$(dig "$ns_param" "${full_domain}" +short)
}

# @Param1: Raw url to be encoded
rawurl_encode() 
{
	reset_func_ret

	local string="${1}"
	local strlen=${#string}
	local encoded=""
	local pos c o

	pos=0
	while [ ${pos} -lt ${strlen} ]
	do
		c=${string:$pos:1}
		case "$c" in
			[-_.~a-zA-Z0-9] ) o="${c}" ;;
			* )               o=$(printf "%%%02X" "'$c")
		esac
		encoded="${encoded}${o}"
		pos=$(($pos + 1))
	done
	_func_ret="${encoded}" 
}

calc_signature()
{
	reset_func_ret
	local sorted_key=$(
		i=0
		while [ $i -lt ${g_pn} ]
		do
			eval key="\$g_pkey_$i"
			echo "${key}"
			i=$((++i))
		done | LC_ALL=C sort
	)
	echo ${sorted_key}
	local query_str=""
	for key in ${sorted_key}
	do
		eval val="\$g_pval_${key}"

		rawurl_encode "${key}"
		key_enc=${_func_ret}
		rawurl_encode "${val}"
		val_enc=${_func_ret}

		query_str="${query_str}${key_enc}=${val_enc}&"
	done
	query_str=${query_str%'&'}

	_debug Query String: ${query_str}
	# encode
	rawurl_encode "${query_str}"
	local encoded_str=${_func_ret}
	local str_to_signed="GET&%2F&"${encoded_str}
	_debug String to Signed: ${str_to_signed}

	local key_sign="${AccessKeySec}&"
	_func_ret=$(echo -n ${str_to_signed} | openssl dgst -binary -sha1 -hmac ${key_sign} | openssl enc -base64)
}

send_request()
{
	# put signature
	calc_signature
	local signature=${_func_ret}
	put_param "Signature" "${signature}"
	echo ${signature}
	# pack all params
	pack_params
	local packed_params=${_func_ret}

	local req_url="${ALiServerAddr}/?${packed_params}"
	_debug Request addr: ${req_url}

	local respond=$(curl -3 ${req_url} --silent --connect-timeout 10 -w "HttpCode:%{http_code}")
	echo ${respond}
}

describe_record()
{
	put_params_public
	put_params_DescribeDomainRecords

	send_request
}

update_record()
{
	# get ip
	get_my_ip
	local my_ip=${_func_ret}

	# Check if need update
	_debug My IP: ${my_ip}
	if [ -z "${my_ip}" ]; then
		_err Could not get my ip, exitting...
		exit
	fi

	get_domain_ip
	local domain_ip=${_func_ret}
	_debug Current Domain IP: ${domain_ip}

	if [ "${my_ip}" == "${domain_ip}" ] ; then
		_log Need not to update, current IP: ${my_ip}
		exit
	fi

	# init params
	put_params_public
	put_params_UpdateDomainRecord ${my_ip}

	send_request
}

main()
{
	#describe_record
	update_record
}

main