场景

需要使用域名指向自己的NAS的场景,达到域名动态的指定自己的IP的目的,但是家庭宽带IP不固定,每次重启路由IP会变,所以写一个脚本来自动查询IP,并更新到阿里云的域名上。

脚本

NAS 中配置定时任务是可以执行脚本的,本身也是Linux,如查开ssh的话,直接就能上去操作,不过不安全就是,全身如果IP对外暴露,就会有被人恶意连接上的危险。
很多文章放脚本需要开ssh之后,通过FTP工具上传脚本,不要这么做,轻易不要开启ssh登陆,除非你已经很熟悉了。

shell 脚本

建一个目录,创建一个文件aliyun.sh,然后右键--属性查看文件路径:

查看文件路径

脚本内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#!/bin/sh

set -e

if [ $1 ]; then
ApiId=$1
fi

if [ $2 ]; then
ApiKey=$2
fi

if [ $3 ]; then
Domain=$3
fi

if [ -z "$ApiId" -o -z "$ApiKey" -o -z "$Domain" ]; then
echo "参数缺失"
exit 1
fi

if [ $4 ]; then
SubDomain=$4
fi

if [ -z "$SubDomain" ]; then
SubDomain="@"
fi

Nonce=$(date -u "+%N") # 有bug?
Timestamp=$(date -u "+%Y-%m-%dT%H%%3A%M%%3A%SZ") # SB 阿里云, 什么鬼时间格式
Nonce=$Timestamp

urlencode() {
local raw="$1";
local len="${#raw}"
local encoded=""

for i in `seq 1 $len`; do
local j=$((i+1))
local c=$(echo $raw | cut -c$i-$i)

case $c in [a-zA-Z0-9.~_-]) ;;
*)
c=$(printf '%%%02X' "'$c") ;;
esac

encoded="$encoded$c"
done

echo $encoded
}

# $1 = query string
getSignature() {
local encodedQuery=$(urlencode $1)
local message="GET&%2F&$encodedQuery"
local sig=$(echo -n "$message" | openssl dgst -sha1 -hmac "$ApiKey&" -binary | openssl base64)
echo $(urlencode $sig)
}

sendRequest() {
local sig=$(getSignature $1)
local result=$(wget -qO- --no-check-certificate --content-on-error "https://alidns.aliyuncs.com?$1&Signature=$sig")
echo $result
}

getRecordId() {
echo "获取 $SubDomain.$Domain 的 IP..." >&2
local queryString="AccessKeyId=$ApiId&Action=DescribeSubDomainRecords&Format=JSON&SignatureMethod=HMAC-SHA1&SignatureNonce=$Nonce&SignatureVersion=1.0&SubDomain=$SubDomain.$Domain&Timestamp=$Timestamp&Type=A&Version=2015-01-09"
local result=$(sendRequest "$queryString")
local code=$(echo $result | sed 's/.*,"Code":"\([A-z]*\)",.*/\1/')
local recordId=$(echo $result | sed 's/.*,"RecordId":"\([0-9]*\)",.*/\1/')

if [ "$code" = "$result" ] && [ ! "$recordId" = "$result" ]; then
local ip=$(echo $result | sed 's/.*,"Value":"\([0-9\.]*\)",.*/\1/')

if [ "$ip" == "$NewIP" ]; then
echo "IP 无变化, 退出脚本..." >&2
echo "quit"
else
echo $recordId
fi
else
echo "null"
fi
}

# $1 = record ID, $2 = new IP
updateRecord() {
local queryString="AccessKeyId=$ApiId&Action=UpdateDomainRecord&DomainName=$Domain&Format=JSON&RR=$SubDomain&RecordId=$1&SignatureMethod=HMAC-SHA1&SignatureNonce=$Nonce&SignatureVersion=1.0&Timestamp=$Timestamp&Type=A&Value=$2&Version=2015-01-09"
local result=$(sendRequest $queryString)
local code=$(echo $result | sed 's/.*,"Code":"\([A-z]*\)",.*/\1/')

if [ "$code" = "$result" ]; then
echo "$SubDomain.$Domain 已指向 $NewIP." >&2
else
echo "更新失败." >&2
echo $result >&2
fi
}

# $1 = new IP
addRecord() {
local queryString="AccessKeyId=$ApiId&Action=AddDomainRecord&DomainName=$Domain&Format=JSON&RR=$SubDomain&SignatureMethod=HMAC-SHA1&SignatureNonce=$Nonce&SignatureVersion=1.0&Timestamp=$Timestamp&Type=A&Value=$1&Version=2015-01-09"
local result=$(sendRequest $queryString)
local code=$(echo $result | sed 's/.*,"Code":"\([A-z]*\)",.*/\1/')

if [ "$code" = "$result" ]; then
echo "$SubDomain.$Domain 已指向 $NewIP." >&2
else
echo "添加失败." >&2
echo $result >&2
fi
}

# Get new IP address
echo "获取当前 IP..."
NewIP=$(wget -qO- --no-check-certificate "http://members.3322.org/dyndns/getip")
echo "当前 IP 为 $NewIP."

# Get record ID of sub domain
recordId=$(getRecordId)

if [ ! "$recordId" = "quit" ]; then
if [ "$recordId" = "null" ]; then
echo "域名记录不存在, 添加 $SubDomain.$Domain 至 $NewIP..."
addRecord $NewIP
else
echo "域名记录已存在, 更新 $SubDomain.$Domain 至 $NewIP..."
updateRecord $recordId $NewIP
fi
fi

命令格式

bash /volume1/workspaces/shell/nas/aliyun.sh AccessKey_ID AccessKey_Secret test.com www

参数说明

阿里云后台获取,这个直接进入阿里云控制台就可以操作了,懂的都懂

AccessKey_ID
AccessKey_Secret

域名
test.com: 这个test.com不是我的域名,但晚写文章都用test
www: 如果有子域名比较nas这样,也可以写成子域名

创建任务

从控制面板中,添加任务,我这里添加的是定时任务,定时执行,也可以添加开机执行任务。
一般情况下只有路由器或光猫重启才会更新IP,NAS重启也会更新,所以还是定时的去更新比较靠谱。

计划任务

添加任务

添加执行.jpg

总结

到上面就配置完了,可以先设成一分钟,看看效果。