讓咱們用 Node.js 寫本身的 DDNS 動態域名程序

原文連接:http://xcoder.in/2014/09/20/lets-build-ourselves-ddns/javascript

原由

一開始我在移動的寬帶中。那個時候雖然還不是徹底的局域網,可是電信網絡訪問不了個人外網 IP。又由於我須要一個 DDNS 服務來維持個人 kacaka.ca(目前暫失效)。php

爲了解決讓電信網絡也能訪問個人 Web,因而我想到了免費 CDN 當中比較有名的 CloudFlare。並且它也有提供 API 讓開發者本身開發經過他的服務解析域名的服務。html

再而後,去年的九月份,個人早期 Node.js 做品 dloucflare 發佈了。因此就有了這個帖子java

如今,我已經搬到電信了,而後舊版的貌似不能用了,由於 CloudFlare 貌似 API 都遷移到了 https 上面。而後我爲了個人小夥伴們能訪問我出租屋裏的舊電腦,又重構了一遍這個項目node

使用 dlouc-flare 構建

首先安裝最新的 dlouc-flare 包:git

$ npm install dlouc-flare

而後去建立一個 DF 對象:github

var DloucFlare = require("dlouc-flare");
var df = DloucFlare.create("你的郵箱", "API KEY", "域名(不須要 www)");

CloudFlare 如何使用的話這裏就很少作解釋了,至於 API KEY 的話,能夠在這裏獲取到。npm

而後調用 df.dynamicDomains 函數去把你這個域名下面的一些子域名加入你這個腳本的動態域名範疇當中:json

df.dynamicDomains([ "@", "www", "子域名3", "子域名4", ... ], 檢測時間間隔);

其中 "@" 表明的是域名沒有 www 前綴的自己。檢測時間間隔以毫秒爲單位。api

事實上,你也能夠自定義一個檢測你當前主機的 IP 地址的函數(若是你不喜歡用包內的默認檢測 IP 函數)。

只要你寫一個函數:

function checkIp(callback) {
    // blahblah...
    callback(undefined, IP地址);
}

而後覆蓋掉默認的 IP 檢測函數便可:

df.getIpFunction = checkIp;

最後保存退出並用 node 執行你的程序就行了,程序就會開始歡快地跑了。

Preview

如何本身寫?

其實要徹底本身寫也是很簡單的——無非就是調用一下 CloudFlare 的 API 而已。

咱們定位明確就是要作 DDNS,因此不必關係其它不少不相關的 API,只須要最基礎的幾個就夠了。

API 解析

全部 API 的基礎 URI 都爲:https://www.cloudflare.com/api_json.html

驗證信息

根據 CloudFlare 文檔所說,全部的提交都要黏上驗證信息給 POST 過去。而驗證的字段以下:

  • tkn: 從你的我的頁面當中複製出來的 API KEY。
  • email: 你的登陸郵箱。
  • a: 操做名,每種操做都有其特有的操做名。

獲取域名下的子域名記錄

其操做名爲 rec_load_all,咱們不關心其它不重要的參數,只須要再傳一個 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 數據給 POST 到 API 的 RESTful 裏面去。而後根據返回值進行解析。

關於 DNSRecordObject 的代碼能夠自行翻閱這裏

以及 spidex 的文檔在這裏

修改某記錄

其操做名爲 rec_edit,如文檔所說,除了固有的幾個參數以外,咱們還須要有以下參數:

  • z: 域名。
  • id: 域名記錄編號,從 rec_load_all 中獲取。
  • type: 記錄類型。如 A / CNAME 等等。
  • name: 子域名名,若是無前綴子域名則與域名相同。
  • content: 值。若是咱們只是作動態域名的話,這裏的值就是 IP。
  • service_mode: 服務類型,填原值便可。
  • ttl: TTL,填原值便可。

上面參數的解說只是對於咱們要作 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 網上就多了去了。

舉個簡單的例子,個人 dlouc-flare 的獲取 IP 的 API 就是從

http://www.telize.com/ip

來的。

請求上面的地址以後,輸出的內容(注意有換行符)就是你當前機子所在的網絡的公網 IP 了。

相似的 API 還有不少:

流程

有了上面的仨 API,一切都好說了,流程很簡單:

  • 獲取本身某個使用 CloudFlare 解析的域名下的子域名
  • 本身設置幾個子域名名拿來作 DDNS。
  • 設置一個定時器,每次定時器到時的時候都進行以下操做:

    1. 經過 IP 的 API 獲取當前 IP。
    2. 循環遍歷每一個本身設置的子域名名。
    3. 對於每一個子域名,都判斷其當前記錄 IP 是否等於當前剛探測的 IP。


有了上面的幾個步驟,加上以前咱們講的幾個 API,你們就能輕鬆加愉快地完成本身的 DDNS 腳本了。

固然,若是本身懶的話也能夠用本文一開始的方法,使用 dlouc-flare 這個包,經過簡單的編碼就能實現本身的 DDNS 動態域名腳本了。

這裏的定時器時間本身按需而定,就我本身而言,我是給設置了 1000 * 60 毫秒的間隔。

小結

最先與動態域名結緣的時候是初中的時候,大概七八年前了吧,那個時候花生殼什麼的,可是最終用的是 3322.org

其實基本的動態域名的原理很簡單,無非就是本地開一個腳本,不停去探測本機 IP,一旦有變化就去解析服務器修改。

本人在這裏拋磚引玉。若是哪裏有別的解析商的 API,你們本身也能夠觸類旁通,寫什麼 DNSPod 的動態域名,寫什麼 jiasule 的動態域名等等等等。

喵~ଘ(੭ˊᵕˋ)੭* ੈ✩‧₊˚

相關文章
相關標籤/搜索