Linux shell 阿里云IPV6 DNS解析
记录一下本地服务器自动更新IPV6 DNS解析的过程
需求
由于移动不提供动态公网IPV4(联通,电信有动态公网IP),需要在外访问家中的网络设备。
只要有IPV6网络,就可以访问家中的设备,无需购买有公网IP的服务器,可以做域名解析,速度还是很快的,跟局域网访问差不多,速度差别根据你的带宽而定,主要有以下用途:。
- 搭建IPV6网站
- Webdav文件服务
- 远程SMB服务
- 远程RDP桌面连接
- 远程管理家中智能设备
- 只要能用IPV6地址的地方
本教程以OPENWRT为例
// 安装必要依赖
opkg update
opkg install openssl-util bash curl jq
配置阿里DNS的登录ID和秘钥并设置你需要自动更新的域名,记录,解析类型
# -----------------------------------------------------------------------------
api_domain='alidns.aliyuncs.com'
# https://ram.console.aliyun.com/manage/ak
ak_id="yourid"
ak_secret="yoursecret"
# Fixed, only one
signature_method='HMAC-SHA1'
# Alidns Domain properties
# -----------------------------------------------------------------------------
domain="yourdomain"
records=('yourrecord')
records_type="AAAA"
获取本机IPV6地址,RE正则匹配
语法 ipconfig [interface] | egrep -o [re] | head -n 1
移动IPV6 2409开头
电信IPV6 240e开头
联通IPV6 2408开头
get_public_ip() {
public_ip= ifconfig pppoe-wan | egrep -o "2409:.*:[a-z0-9]{3,4}:[a-z0-9]{3,4}" | head -n 1
echo $public_ip
return $public_ip
}
完整代码
#!/bin/bash
# Alidns properties
# -----------------------------------------------------------------------------
api_domain='alidns.aliyuncs.com'
# https://ram.console.aliyun.com/manage/ak
ak_id="yourid"
ak_secret="yoursecret"
# Fixed, only one
signature_method='HMAC-SHA1'
# Alidns Domain properties
# -----------------------------------------------------------------------------
domain="yourdomain"
records=('yourrecord')
records_type="AAAA"
# get public ip
# -----------------------------------------------------------------------------
get_public_ip() {
public_ip= ifconfig pppoe-wan | egrep -o "2409:.*:[a-z0-9]{3,4}:[a-z0-9]{3,4}" | head -n 1
echo $public_ip
return $public_ip
}
# build param & signed
# -----------------------------------------------------------------------------
param_encode() {
params=$1
str=""
for (( i=0; i<${#params}; i++ )); do
char="${params:$i:1}"
if [[ $char == [a-zA-Z0-9.~_-] ]]; then
str="$str$char"
else
hex=`printf '%%%02X' "'$char"`
str="$str$hex"
fi
done
echo $str | sed -e 's/+/%20/g' -e 's/*/%21/g' -e 's/%7E/~/g'
}
# TODO: ':' hex is '%3A', but, alidns api return '%253A'
# I didn't find the reason, so I made a replacement first, there may be other problems.
param_tosign() {
echo -n "GET&$(param_encode "/")&$(param_encode $1)" \
| sed -e "s/\%3A/\%253A/g" \
| openssl sha1 -binary -hmac "$ak_secret&" \
| openssl base64
}
# dns actions
# -----------------------------------------------------------------------------
request() {
timestamp=`date -u +%Y-%m-%dT%TZ`
signature_nonce=`date +%d-%m-%Y_%H-%M-%S`
params="AccessKeyId=$ak_id&DomainName=$1&Format=json&SignatureMethod=$signature_method&SignatureNonce=$signature_nonce&SignatureVersion=1.0&Timestamp=$timestamp&Version=2015-01-09&Action=$2"
if [ ! -z "$3" ]; then
params=$params"&"$3
fi
# dictionary sorting
params=`awk 'BEGIN{split('"\"$params\""',arr,"&"); for(i in arr) {v=arr[i]"&"; print v}}' | sort | xargs echo | sed 's/ //g;s/&$//g'`
sign=$(param_encode $(param_tosign $params))
echo `curl -k -s "https://$api_domain/?$params&Signature=$sign"`
}
fetch_domain_records() {
echo $(request $1 "DescribeDomainRecords")
}
update_domain_record() {
request $1 "UpdateDomainRecord" "RR=$2&RecordId=$3&Type=$records_type&Value=$4"
}
add_domain_record() {
request $1 "AddDomainRecord" "RR=$2&Type=$records_type&Value=$3"
}
batch_update() {
ip=`get_public_ip`
if [ "$?" != "0" ]; then
echo "cannot get public ip"
exit 1
fi
echo ""
echo "Public IP: $ip"
echo "-----------------------------------------------------------------------"
echo ""
#bellow set your domain
existed_records=`fetch_domain_records "$domain" | jq .DomainRecords.Record`
for i in "${records[@]}"; do
echo $i
if [ "$existed_records" = "null" ]; then
add_domain_record $domain $i $ip
else
record=`echo $existed_records | jq -c '.[] | select( .RR | contains("'$i'"))'`
if [ -z $record ]; then
add_domain_record $domain $i $ip
else
record_id=`echo $record | jq .RecordId | sed -e "s/\"//g"`
old_value=`echo $record | jq .Value | sed -e "s/\"//g"`
if [ "$old_value" != "$ip" ]; then
if [ "$record_id" = "null" ]; then
add_domain_record $domain $i $ip
echo "add records"
else
update_domain_record $domain $i $record_id $ip
echo "update records"
fi
fi
fi
fi
echo ""
sleep 1
done
}
batch_update
定时任务执行脚本,每隔十分钟执行一次
*/10 * * * * bash /root/aliddns.sh