#!/bin/sh
#################################################
AnripDdns v5.08
Dynamic DNS using DNSPod API
Edited by ProfFan
#################################################
Openwrt
#################################################
#https://www.cnblogs.com/jackadam/p/8192843.html
#https://github.com/anrip/ArDNSPod
#1:必须安装CURL
#opkg --force-depends --force-overwrite install /tmp/libmbedtls_2.14.1-1_arm_cortex-a9.ipk
#opkg --force-depends --force-overwrite install /tmp/ca-bundle_20180409_all.ipk
#opkg --force-depends --force-overwrite install /tmp/libcurl_7.60.0-3_arm_cortex-a9.ipk
#opkg --force-depends --force-overwrite install /tmp/curl_7.60.0-3_arm_cortex-a9.ipk
#或者安装支持HTTPS的完整WGET
#2:拷贝ddnspod.sh和ddnspod.conf到相应的目录,并设置权限为777
#3:在/etc/ppp/ip-up.d目录新建一个文件autoddns.sh,权限0755,内容如下:
#/bin/sh
sh /etc/config/ddnspod.sh >> /tmp/log/dnspod.log 2>&1 &
#只要wan口发生变化,就会执行脚本去DNSpod更新A记录的IP。
#简单测试一下:/etc/init.d/network restart
#################################################
case $(uname) in
'Linux')
echo "Linux"
A() {
local extip
extip=$(ip -o -4 addr list | grep -Ev '\s(docker|lo)' | awk '{print $4}' | cut -d/ -f1 | grep -Ev '(^127.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$)|(^10.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}$)|(^172.1[6-9]{1}[0-9]{0,1}.[0-9]{1,3}.[0-9]{1,3}$)|(^172.2[0-9]{1}[0-9]{0,1}.[0-9]{1,3}.[0-9]{1,3}$)|(^172.3[0-1]{1}[0-9]{0,1}.[0-9]{1,3}.[0-9]{1,3}$)|(^192.168.[0-9]{1,3}.[0-9]{1,3}$)')
if [ "x${extip}" = "x" ]; then
extip=$(ip -o -4 addr list | grep -Ev '\s(docker|lo)' | awk '{print $4}' | cut -d/ -f1 )
fi
echo $extip
}
getIPv6() {
local extip
extip=ip addr show ${ipv6ethName} | grep inet6 | awk '{print $2}' |grep ^${ipv6prefix} | grep '/64$' | sed 's/\/.*//g'
echo $extip
#ip addr show dev ${ipv6ethName} | sed -e's/^.inet6 ([^ ])/.*$/\1/;t;d'
#如果没有nvram,使用这条,注意将eth0改为本机上的网口设备(通过 ifconfig 查看网络接口)
}
# 获得外网ipv6地址
AAAA() {
local hostIP_v6=$(getIPv6)
while [[ -z $hostIP_v6 ]]
do
sleep 60
hostIP_v6=$(getIPv6)
done
echo $hostIP_v6
}
;;
*) ;;
esac
Get script dir
rreadlink() ( # Execute the function in a subshell to localize variables and the effect of cd
.
target=$1 fname= targetDir= CDPATH=
Try to make the execution environment as predictable as possible:
All commands below are invoked via command
, so we must make sure that command
itself is not redefined as an alias or shell function.
(Note that command is too inconsistent across shells, so we don't use it.)
command
is a builtin in bash, dash, ksh, zsh, and some platforms do not even have
an external utility version of it (e.g, Ubuntu).
command
bypasses aliases and shell functions and also finds builtins
in bash, dash, and ksh. In zsh, option POSIX_BUILTINS must be turned on for that
to happen.
{ \unalias command; \unset -f command; } >/dev/null 2>&1
[ -n "$ZSH_VERSION" ] && options[POSIX_BUILTINS]=on # make zsh find builtins with command
too.
while :; do # Resolve potential symlinks until the ultimate target is found.
[ -L "$target" ] || [ -e "$target" ] || { command printf '%s\n' "ERROR: '$target' does not exist." >&2; return 1; }
command cd "$(command dirname -- "$target")" # Change to target dir; necessary for correct resolution of target path.
fname=$(command basename -- "$target") # Extract filename.
[ "$fname" = '/' ] && fname='' # !! curiously, basename /
returns '/'
if [ -L "$fname" ]; then
# Extract [next] target path, which may be defined
# relative to the symlink's own directory.
# Note: We parse ls -l
output to find the symlink target
# which is the only POSIX-compliant, albeit somewhat fragile, way.
target=$(command ls -l "$fname")
target=${target#* -> }
continue # Resolve [next] symlink target.
fi
break # Ultimate target reached.
done
targetDir=$(command pwd -P) # Get canonical dir. path
Output the ultimate target's canonical path.
Note that we manually resolve paths ending in /. and /.. to make sure we have a normalized path.
if [ "$fname" = '.' ]; then
command printf '%s\n' "${targetDir%/}"
elif [ "$fname" = '..' ]; then
# Caveat: something like /var/.. will resolve to /private (assuming /var@ -> /private/var), i.e. the '..' is applied
# AFTER canonicalization.
command printf '%s\n' "$(command dirname -- "${targetDir}")"
else
command printf '%s\n' "${targetDir%/}/$fname"
fi
)
DIR=$(dirname -- "$(rreadlink "$0")")
Global Variables:
Token-based Authentication
arToken=""
Account-based Authentication
arMail=""
arPass=""
ipv6ethName=""
ipv6prefix=""
Load config
#. $DIR/ddnspod.conf
Get Domain IP
arg: domain
arDdnsInfo() {
recordType=$3
# Get domain ID
domainID=$(arApiPost "Domain.Info" "domain=${1}")
domainID=$(echo $domainID | sed 's/.{"id":"([0-9])".*/\1/')
# Get Record ID
recordID=$(arApiPost "Record.List" "domain_id=${domainID}&sub_domain=${2}&record_type=${recordType}")
recordID=$(echo $recordID | sed 's/.*\[{"id":"\([0-9]*\)".*/\1/')
# Last IP
recordIP=$(arApiPost "Record.Info" "domain_id=${domainID}&record_id=${recordID}&record_type=${recordType}")
recordIP=$(echo $recordIP | sed 's/.*,"value":"\([0-9a-z\.:]*\)".*/\1/')
# Output IP
case "$recordIP" in
[0-9a-z]*)
echo $recordIP
return 0
;;
*)
echo "Get Record Info Failed,Please Install wget/curl or check your network or check domain/sub domain."
return 1
;;
esac
}
Get data
arg: type data
arApiPost() {
local agent="AnripDdns/5.07([email protected])"
local inter="https://dnsapi.cn/${1:?'Info.Version'}"
if [ "x${arToken}" = "x" ]; then # undefine token
local param="login_email=${arMail}&login_password=${arPass}&format=json&${2}"
else
local param="login_token=${arToken}&format=json&${2}"
fi
if [ -n "`opkg list-installed | grep curl | sed 's/[[:space:]]//g'`" ];then #if install curl
curl -k -X POST $inter -d "$param"
elif [ -n "`opkg list-installed | grep wget | sed 's/[[:space:]]//g'`" ];then #if install wget
wget --quiet --no-check-certificate --output-document=- --user-agent=$agent --post-data $param $inter
else
echo "Please run 'opkg install wget' or 'opkg install curl'!"
fi
}
Update
arg: main domain sub domain
arDdnsUpdate() {
local domainID recordID recordRS recordCD recordIP myIP recordType
recordType=$4
# Get domain ID
domainID=$(arApiPost "Domain.Info" "domain=${1}")
domainID=$(echo $domainID | sed 's/.*{"id":"\([0-9]*\)".*/\1/')
# Get Record ID
recordID=$(arApiPost "Record.List" "domain_id=${domainID}&sub_domain=${2}&record_type=${recordType}")
recordID=$(echo $recordID | sed 's/.*\[{"id":"\([0-9]*\)".*/\1/')
# Update IP
myIP=$3
recordRS=$(arApiPost "Record.Modify" "domain_id=${domainID}&sub_domain=${2}&record_type=${recordType}&record_id=${recordID}&record_line=%e9%bb%98%e8%ae%a4&value=${myIP}")
recordCD=$(echo $recordRS | sed 's/.*{"code":"\([0-9]*\)".*/\1/')
recordIP=$(echo $recordRS | sed 's/.*,"value":"\([0-9a-z\.:]*\)".*/\1/')
# Output IP
if [ "$recordIP" = "$myIP" ]; then
if [ "$recordCD" = "1" ]; then
echo $recordIP
return 0
fi
# Echo error message
echo $recordRS | sed 's/.*,"message":"\([^"]*\)".*/\1/'
return 1
else
echo "Update Failed! Please check your network."
return 1
fi
}
DDNS Check
Arg: Main Sub
arDdnsCheck() {
if [ "x${3}" = "x" ]; then
recordType='A'
else
recordType=$3
fi
hostIP=$(${recordType})
echo "----------------------------------------"
echo "$(date "+%Y-%m-%d %H:%M:%S") Updating Domain: ${2}.${1} to ${hostIP}(${recordType})"
lastIP=$(arDdnsInfo $1 $2 $recordType)
if [ $? -eq 0 ]; then
echo "$(date "+%Y-%m-%d %H:%M:%S") lastIP: ${lastIP}"
if [ "$lastIP" != "$hostIP" ]; then
postRS=$(arDdnsUpdate $1 $2 $hostIP $recordType)
if [ $? -eq 0 ]; then
echo "$(date "+%Y-%m-%d %H:%M:%S") postRS: ${postRS}"
return 0
else
echo ${postRS}
return 1
fi
fi
echo "Last IP is the same as current IP!"
return 1
fi
echo ${lastIP}
return 1
}
DDNS
#echo ${#domains[@]}
#for index in ${!domains[@]}; do
echo "${domains[index]} ${subdomains[index]}"
arDdnsCheck "${domains[index]}" "${subdomains[index]}"
#done
. $DIR/ddnspod.conf
-----------ddnspod.conf-------------------
arToken="XXXXX,XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
ipv6ethName="pppoe-wan"
ipv6prefix="2409" #**移动IPV6前辍
arDdnsCheck "xxxxx.cn" "ipv4" #IPV4
arDdnsCheck "xxxxx.cn" "ipv6" "AAAA" #IPV6