原文鏈接:http://xcoder.in/2014/09/20/lets-build-ourselves-ddns/
起因
一開始我在移動的寬帶中庵朝。那個時候雖然還不是完全的局域網(wǎng)悄谐,但是電信網(wǎng)絡訪問不了我的外網(wǎng) IP隆嗅。又因為我需要一個 DDNS 服務來維持我的 kacaka.ca(目前暫失效)折柠。
為了解決讓電信網(wǎng)絡也能訪問我的 Web,于是我想到了免費 CDN 當中比較有名的 CloudFlare偏形。而且它也有提供 API 讓開發(fā)者自己開發(fā)通過他的服務解析域名的服務谎柄。
再然后,去年的九月份朋鞍,我的早期 Node.js 作品 dloucflare 發(fā)布了已添。所以就有了這個帖子。
現(xiàn)在滥酥,我已經(jīng)搬到電信了更舞,然后舊版的貌似不能用了,因為 CloudFlare 貌似 API 都遷移到了 https
上面坎吻。然后我為了我的小伙伴們能訪問我出租屋里的舊電腦缆蝉,又重構了一遍這個項目。
使用 dlouc-flare 構建
首先安裝最新的 dlouc-flare
包:
$ npm install dlouc-flare
然后去創(chuàng)建一個 DF 對象:
var DloucFlare = require("dlouc-flare");
var df = DloucFlare.create("你的郵箱", "API KEY", "域名(不需要 www)");
CloudFlare 如何使用的話這里就不多做解釋了瘦真,至于 API KEY 的話刊头,可以在這里獲取到。
然后調(diào)用 df.dynamicDomains
函數(shù)去把你這個域名下面的一些子域名加入你這個腳本的動態(tài)域名范疇當中:
df.dynamicDomains([ "@", "www", "子域名3", "子域名4", ... ], 檢測時間間隔);
其中
"@"
代表的是域名沒有www
前綴的本身吗氏。檢測時間間隔以毫秒為單位芽偏。
事實上雷逆,你也可以自定義一個檢測你當前主機的 IP 地址的函數(shù)(如果你不喜歡用包內(nèi)的默認檢測 IP 函數(shù))弦讽。
只要你寫一個函數(shù):
function checkIp(callback) {
// blahblah...
callback(undefined, IP地址);
}
然后覆蓋掉默認的 IP 檢測函數(shù)即可:
df.getIpFunction = checkIp;
最后保存退出并用 node
執(zhí)行你的程序就好了,程序就會開始歡快地跑了膀哲。
如何自己寫往产?
其實要完全自己寫也是很簡單的——無非就是調(diào)用一下 CloudFlare 的 API 而已。
我們定位明確就是要做 DDNS某宪,所以沒必要關系其它很多不相關的 API仿村,只需要最基礎的幾個就夠了。
API 解析
所有 API 的基礎 URI 都為:https://www.cloudflare.com/api_json.html兴喂。
驗證信息
根據(jù) CloudFlare 文檔所說蔼囊,所有的提交都要黏上驗證信息給 POST 過去。而驗證的字段如下:
- tkn: 從你的個人頁面當中復制出來的 API KEY衣迷。
- email: 你的登錄郵箱畏鼓。
- a: 操作名,每種操作都有其特有的操作名壶谒。
獲取域名下的子域名記錄
其操作名為 rec_load_all
云矫,我們不關心其它不重要的參數(shù),只需要再傳一個 z
字段代表其域名就好了汗菜,舉個例子:
var self = this;
var param = {
a : "rec_load_all",
tkn : this.apiKey,
email : this.email,
z : this.domain
};
var url = "https://www.cloudflare.com/api_json.html";
spidex.post(url, function(html, status) {
if(status !== 200) {
return callback(new Error("Error status while fetching DNS records."));
}
var json;
try {
json = JSON.parse(html);
} catch(e) {
return callback(new Error("Error while parsing DNS records: " + e.message));
}
if(json.result === "error") {
var msg = json.msg;
if(undefined === msg) msg = "Unknown error.";
return callback(new Error(msg));
} else if(json.result === "success") {
var count = json.response.recs.count;
var objects = json.response.recs.objs;
for(var i = 0; i < count; i++) {
self.records.push(new DNSRecordObject(self, objects[i]));
}
callback(undefined, self.records);
} else {
callback(new Error("Unknown error."));
}
}, param, "utf8").on("error", callback);
上述代碼就是把 param
數(shù)據(jù)給 POST 到 API 的 RESTful 里面去让禀。然后根據(jù)返回值進行解析挑社。
關于
DNSRecordObject
的代碼可以自行翻閱這里。以及 spidex 的文檔在這里巡揍。
修改某記錄
其操作名為 rec_edit
痛阻,如文檔所說,除了固有的幾個參數(shù)之外腮敌,我們還需要有如下參數(shù):
-
z:
域名录平。 -
id:
域名記錄編號,從rec_load_all
中獲取缀皱。 -
type:
記錄類型斗这。如A
/CNAME
等等。 -
name:
子域名名啤斗,如果無前綴子域名則與域名相同表箭。 -
content:
值。如果我們只是做動態(tài)域名的話钮莲,這里的值就是 IP免钻。 -
service_mode:
服務類型,填原值即可崔拥。 -
ttl
: TTL极舔,填原值即可。
上面參數(shù)的解說只是對于我們要做 DDNS 腳本而言的解釋链瓦。
所以說在 dnsrecordobject.js 中我是這么做的:
var param = {
a : "rec_edit",
tkn : this.dloucflare.apiKey,
email : this.dloucflare.email,
id : this.recordId(),
z : this.domain,
type : this.recordType(),
name : this.name,
content : ip,
service_mode : this.object.service_mode,
ttl : this.object.ttl
};
var self = this;
spidex.post(config.baseUrl, function(html, status, respHeader) {
if(status !== 200) {
return callback(new Error("Error status while editing " + self.name + "."));
}
var json;
try {
json = JSON.parse(html);
} catch(e) {
return callback(new Error("Error whileparsing editing result: " + e.message));
}
if(json.result === "success") {
self.object.content = ip;
return callback();
} else {
var msg = json.msg || "Unknown error.";
return callback(new Error(msg));
}
}, param, "utf8").on("error", callback);
上面的代碼就能將你某個域名(
this.domain
)下的子域名this.name
的 IP 給修改成ip
了拆魏。
探測 IP
這種 API 網(wǎng)上就多了去了。
舉個簡單的例子慈俯,我的 dlouc-flare
的獲取 IP 的 API 就是從
來的渤刃。
請求上面的地址之后,輸出的內(nèi)容(注意有換行符)就是你當前機子所在的網(wǎng)絡的公網(wǎng) IP 了贴膘。
類似的 API 還有很多:
- http://ip-api.com/json: 這個 API 就會輸出一堆的 JSON卖子,需要自行解析。
- http://ip.taobao.com/service/getIpInfo2.php?ip=myip: 這個是淘寶提供的 RESTful 獲取 IP 的 API刑峡。
- ...(其它的可以自己去發(fā)現(xiàn))
流程
有了上面的仨 API洋闽,一切都好說了,流程很簡單:
- 獲取自己某個使用
CloudFlare
解析的域名下的子域名突梦。 - 自己設置幾個子域名名拿來做 DDNS诫舅。
- 設置一個定時器,每次定時器到時的時候都進行如下操作:
- 通過 IP 的 API 獲取當前 IP阳似。
- 循環(huán)遍歷每個自己設置的子域名名骚勘。
- 對于每個子域名,都判斷其當前記錄 IP 是否等于當前剛探測的 IP。
- 是:修改該子域名的記錄值為剛探測的 IP俏讹。
- 否:不作任何操作当宴。
有了上面的幾個步驟,加上之前我們講的幾個 API泽疆,大家就能輕松加愉快地完成自己的 DDNS 腳本了户矢。
當然,如果自己懶的話也可以用本文一開始的方法殉疼,使用 dlouc-flare
這個包梯浪,通過簡單的編碼就能實現(xiàn)自己的 DDNS 動態(tài)域名腳本了。
這里的定時器時間自己按需而定瓢娜,就我自己而言挂洛,我是給設置了
1000 * 60
毫秒的間隔。
小結(jié)
最早與動態(tài)域名結(jié)緣的時候是初中的時候眠砾,大概七八年前了吧虏劲,那個時候花生殼什么的,但是最終用的是 3322.org
褒颈。
其實基本的動態(tài)域名的原理很簡單柒巫,無非就是本地開一個腳本,不停去探測本機 IP谷丸,一旦有變化就去解析服務器修改堡掏。
本人在這里拋磚引玉。如果哪里有別的解析商的 API刨疼,大家自己也可以舉一反三泉唁,寫什么 DNSPod 的動態(tài)域名,寫什么 jiasule 的動態(tài)域名等等等等币狠。
喵~?(?ˊ?ˋ)?* ?????