环境
nodejs版本不低于10.16
系统window,centos 均可
package.json
{"name": "aliyun-ddns","version": "2.1.0","main": "ddns.js","scripts": {"start": "node ddns.js"},"author": "luoyefe","license": "MIT","dependencies": {"@alicloud/pop-core": "^1.7.13","axios": "^0.20.0"},"description": "借助阿里云解析API实现DDNS"
}
nodejs代码
const config={accessKeyId: "666666", // 你的阿里云AccessKey IDaccessKeySecret: "888888",// 你的阿里云AccessKey SecretDomainName: 'google.com', //你的域名RRKeyWord: 'ddns', // 子域名
}const Core = require('@alicloud/pop-core');
const axios = require('axios');const client = new Core({accessKeyId: config.accessKeyId,accessKeySecret: config.accessKeySecret,endpoint: 'https://alidns.aliyuncs.com',apiVersion: '2015-01-09'
});// 获取当前公网IP地址,用多个API ,防止一个失效后,有另外的进行替代
async function getPublicIP() {const ipApis = ['https://api.ipify.org?format=json','https://ipinfo.io/json','https://icanhazip.com','http://ip-api.com/json'];for (const api of ipApis) {try {const response = await axios.get(api);const ip = response.data.ip || response.data; // 处理不同API的返回结构console.log(`成功从 ${api} 获取公网IP: ${ip}`);return ip;} catch (error) {console.error(`从 ${api} 获取公网IP失败:`, error);}}throw new Error('所有IP查询API均不可用');
}// 获取指定域名和子域名的DNS记录ID及其值
async function getRecordIdAndValue(domainName, rr) {return new Promise((resolve, reject) => {client.request('DescribeDomainRecords', {DomainName: domainName,RRKeyWord: rr}, { method: 'POST' }).then((result) => {const record = result.DomainRecords.Record.find(r => r.RR === rr);if (record) {resolve({ recordId: record.RecordId, value: record.Value });} else {reject(new Error('没有找到对应的记录'));}}, (ex) => {reject(ex);});});
}// 更新DNS记录
async function updateDNSRecord(recordId, ip,rr) {return new Promise((resolve, reject) => {client.request('UpdateDomainRecord', {RecordId: recordId,RR: rr,Type: 'A',Value: ip}, { method: 'POST' }).then((result) => {resolve(result);}, (ex) => {console.log("client.request失败",ex)reject(ex);});});
}// 主程序
(async () => {try {let domainName=config.DomainName;let rr=config.RRKeyWord;const ip = await getPublicIP();console.log('当前公网IP地址:', ip);const { recordId, value } = await getRecordIdAndValue(domainName, rr);console.log('DNS记录ID:', recordId);console.log('当前DNS记录值:', value);if (value !== ip) {const result = await updateDNSRecord(recordId, ip,rr);console.log('DNS记录更新成功:', result);} else {console.log('DNS记录值未变化,无需更新');}} catch (error) {console.error('操作失败:', error);}
})();