forked from luoye-fe/aliyun-ddns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
166 lines (150 loc) · 4.05 KB
/
index.js
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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*
* 借助阿里云 DNS 服务实现 DDNS(动态域名解析)
*/
const DNS = require('dns');
const crypto = require('crypto');
const axios = require('axios');
const uuidv1 = require('uuid/v1');
const schedule = require('node-schedule');
const { AccessKey, AccessKeySecret, Domain } = require('./config.json');
const HttpInstance = axios.create({
baseURL: 'https://alidns.aliyuncs.com/',
});
main();
// 每分钟更新一次
schedule.scheduleJob('*/1 * * * *', function() {
main();
});
async function main() {
const now = new Date();
const localTime = now.getTime();
const localOffset = now.getTimezoneOffset() * 60000;
const utc = localTime + localOffset;
const offset = 8;
const calctime = utc + (3600000 * offset);
const calcDate = new Date(calctime);
console.log(calcDate.toLocaleString(), '正在更新DNS记录 ...');
const ip = await getExternalIP();
console.log(calcDate.toLocaleString(), '当前外网 ip:', ip);
const records = await getDomainInfo();
if (!records.length) {
console.log(calcDate.toLocaleString(), '记录不存在,新增中 ...');
await addRecord(ip);
return console.log(calcDate.toLocaleString(), '成功, 当前 dns 指向: ', ip);
}
const recordID = records[0].RecordId;
const recordValue = records[0].Value;
if (recordValue === ip) return console.log(calcDate.toLocaleString(), '记录一致, 无修改');
await updateRecord(recordID, ip)
console.log(calcDate.toLocaleString(), '成功, 当前 dns 指向: ', ip);
}
// 新增记录
function addRecord(ip) {
return new Promise((resolve, reject) => {
const requestParams = sortJSON(Object.assign({
Action: 'AddDomainRecord',
DomainName: Domain.match(/\.(.*)/)[1],
RR: Domain.match(/(.*?)\./)[1],
Type: 'A',
Value: ip
}, commonParams()));
const Signature = sign(requestParams);
HttpInstance.get('/', {
params: Object.assign({
Signature
}, requestParams)
})
.then(res => {
resolve(res.data);
})
.catch(e => {
reject(e);
})
});
}
// 更新记录
function updateRecord(id, ip) {
return new Promise((resolve, reject) => {
const requestParams = sortJSON(Object.assign({
Action: 'UpdateDomainRecord',
RecordId: id,
RR: Domain.match(/(.*?)\./)[1],
Type: 'A',
Value: ip
}, commonParams()));
const Signature = sign(requestParams);
HttpInstance.get('/', {
params: Object.assign({
Signature
}, requestParams)
})
.then(res => {
resolve(res.data);
})
.catch(e => {
reject(e);
})
});
}
// 获取本机外网 ip 地址
// 作者此前的接口已失效,更换了个国外的接口
async function getExternalIP() {
const res = await axios.get('https://api.ip.sb/ip', {
});
return res.data.replace('\n', '');
}
// 获取当前解析记录
function getDomainInfo() {
return new Promise((resolve, reject) => {
const requestParams = sortJSON(Object.assign({
Action: 'DescribeSubDomainRecords',
SubDomain: Domain,
PageSize: 100
}, commonParams()));
const Signature = sign(requestParams);
HttpInstance.get('/', {
params: Object.assign({
Signature
}, requestParams)
})
.then(res => {
resolve(res.data.DomainRecords.Record);
})
.catch(e => {
reject(e);
})
});
}
// json 字典顺序排序
function sortJSON(object) {
const result = {};
const keys = Object.keys(object);
keys.sort();
keys.forEach(item => {
result[item] = object[item];
})
return result;
}
// 阿里云签名
function sign(object) {
const hmac = crypto.createHmac('sha1', AccessKeySecret + '&');
const temp = [];
Object.keys(object).forEach(item => {
temp.push(`${encodeURIComponent(item)}=${encodeURIComponent(object[item])}`);
})
const sourceStr = 'GET&%2F&' + encodeURIComponent(temp.join('&'));
const result = hmac.update(sourceStr).digest('base64');
return result;
}
// 阿里云公共请求参数
function commonParams() {
return {
Format: 'JSON',
Version: '2015-01-09',
AccessKeyId: AccessKey,
SignatureMethod: 'HMAC-SHA1',
Timestamp: (new Date()).toISOString(),
SignatureVersion: '1.0',
SignatureNonce: uuidv1()
}
}