家庭NAS最大的一個問題之一就是公網(wǎng)IP不固定,這個問題的解決方法很多蛆挫,如:
1.路由器刷固件赃承;
2.群暉:白群暉自帶內(nèi)網(wǎng)穿透,黑群暉就放棄這個方案吧悴侵;
3.花生殼/花生棒:支持各類操作系統(tǒng)平臺(路由器/Windows/Linux/群暉)瞧剖,缺點是需要花錢;
4.阿里云DDNS:強(qiáng)烈推薦可免;
5.騰訊云DDNS:推薦抓于,證書驗證不如阿里云方便。
6.ngrok等內(nèi)網(wǎng)傳統(tǒng)方案
我買了黑群暉巴元,家用路由器是小米的毡咏,所以對于我來說通過阿里云DDNS和騰訊云DDNS是最好的方案,我的域名是在阿里云上注冊的逮刨,所以呕缭,我直接采用了阿里云DDNS方案。
思路是:每隔一定時間獲取當(dāng)前的公網(wǎng)ip修己,把阿里云的域名解析地址更改為獲取到的公網(wǎng)ip
獲取公網(wǎng)IP
最直觀的獲取ip的方法是
后續(xù)我們獲取到ip后可以跟此ip對比恢总,驗證是否正確
node 獲取ip方式有好多,我嘗試了public-ip睬愤、http 請求等方法
// npm install --save public-ip
const publicIp = require('public-ip');
publicIp.v4().then(ip => {
console.log(ip);
//=> '46.5.21.123'
});
很有意思的是我利用public-ip這個庫請求到的ip地址跟我百度的ip地址并不一樣片仿,這個問題我后續(xù)探究下
所以我直接使用http請求,獲取到用戶公網(wǎng)ip尤辱,代碼如下
const http = require('http')
// 獲取用戶公網(wǎng)ip
const url = 'http://txt.go.sohu.com/ip/soip'
http.get(url, res => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => {
let m = data.match(/\d+\.\d+\.\d+\.\d+/g)
if (m.length > 0) {
console.log('myIP', m[0])
}
})
}).on('error', e => console.log(`error messsage: ${e.message}`))
這樣獲取到的ip地址跟百度出來的ip地址是一樣的
修改阿里云域名解析
首先登錄阿里云獲取accessKeyId和accessKeySecret
獲取accessKeyId和accessKeySecret
域名解析文檔
使用阿里云npm庫@alicloud/pop-core進(jìn)行調(diào)用
// npm install @alicloud/pop-core --save
const Core = require('@alicloud/pop-core');
var client = new Core({
accessKeyId: 'xxxxxxxx',
accessKeySecret: 'xxxxxxxx',
endpoint: 'https://alidns.aliyuncs.com',
apiVersion: '2015-01-09'
});
通過文檔我們可以發(fā)現(xiàn)砂豌,如果需要修改解析地址,我們需要用到被修改解析記錄的RecordId光督,
所以我們先獲取到RecordId
var params = {
// 參數(shù)可根據(jù)自己需求去增加
"RegionId": "cn-hangzhou",
"DomainName": "baidu.com",
"KeyWord": "A"
}
var requestOption = {
method: 'POST'
};
client.request('DescribeDomainRecords', params, requestOption).then((res) => {
console.log(JSON.stringify(res));
if(res.DomainRecords.Record) {
// 我修改的是根域名阳距,所以篩選了下
let recordList = res.DomainRecords.Record.filter(item => {
return item.Type === 'A'
})
let recordID = recordList[0].RecordId
// 此處獲取到的就是RecordId,可根據(jù)自己需求修改邏輯
} else {
console.log('DomainRecords record is null')
}
}, (ex) => {
console.log(ex);
})
根據(jù)獲取到的RecordId將獲取到的公網(wǎng)ip賦值
var params = {
"RegionId": "cn-hangzhou",
"RecordId": recordID,
"RR": "@",
"Type": "A",
"Value": myIP
}
var requestOption = {
method: 'POST'
};
this.client.request('UpdateDomainRecord', params, requestOption).then((result) => {
// console.log(JSON.stringify(result));
console.log('修改成功结借,公網(wǎng)IP為', myIP)
}, (ex) => {
console.log(ex);
})
以上就是修改ip的全過程筐摘,后續(xù)我們再利用node-schedule做個定時任務(wù)就可以了,整體代碼如下
const http = require('http')
const Core = require('@alicloud/pop-core');
const schedule = require('node-schedule');
class AliDDNS {
constructor() {
this.myIP = ''
this.accessKeyId = ''
this.accessKeySecret = ''
this.domainName = ''
this.KeyWord = '@'
}
init () {
this.getIP()
this.initCore()
this.getDomainNameID()
}
getIP () {
// 獲取用戶公網(wǎng)ip
const url = 'http://txt.go.sohu.com/ip/soip'
http.get(url, res => {
let data = ''
res.on('data', chunk => data += chunk)
res.on('end', () => {
let m = data.match(/\d+\.\d+\.\d+\.\d+/g)
if (m.length > 0) {
this.myIP = m[0]
console.log('myIP', this.myIP)
}
})
}).on('error', e => console.log(`error messsage: ${e.message}`))
}
initCore() {
// 初始化 阿里云Core
this.client = new Core({
accessKeyId: this.accessKeyId,
accessKeySecret: this.accessKeySecret,
endpoint: 'https://alidns.aliyuncs.com',
apiVersion: '2015-01-09'
});
}
getDomainNameID() {
if(!this.client) {
console.error('client no init')
return false
}
var params = {
"RegionId": "cn-hangzhou",
"DomainName": this.domainName,
"KeyWord": this.KeyWord,
}
var requestOption = {
method: 'POST'
};
this.client.request('DescribeDomainRecords', params, requestOption).then((res) => {
console.log(JSON.stringify(res));
if(res.DomainRecords.Record) {
let recordList = res.DomainRecords.Record.filter(item => {
return item.Type === 'A'
})
let recordID = recordList[0].RecordId
this.changeDomainIP(recordID)
} else {
console.log('DomainRecords record is null')
}
}, (ex) => {
console.log(ex);
})
}
changeDomainIP(recordID) {
var params = {
"RegionId": "cn-hangzhou",
"RecordId": recordID,
"RR": "@",
"Type": "A",
"Value": this.myIP
}
var requestOption = {
method: 'POST'
};
this.client.request('UpdateDomainRecord', params, requestOption).then((result) => {
// console.log(JSON.stringify(result));
console.log('修改成功船老,公網(wǎng)IP為', this.myIP)
}, (ex) => {
console.log(ex);
})
}
}
const aliDDns = new AliDDNS()
// 每五分鐘更新一次ip
schedule.scheduleJob('0 5 * * * *', ()=>{
aliDDns.init()
})