Physical Address

304 North Cardinal St.
Dorchester Center, MA 02124

利用 Cloudflare API v4 建立 DDNS

前幾篇提到透過 No-IP 來建立 DDNS 的做法,來避免被 fail2ban 擋下。後來在阿竣的建議下,研究了 Cloudflare 的作法。透過這種方法,可以讓 DDNS 使用自己的主要域名,而非 No-IP 或其他 DDNS 服務的子域名。

在網路上搜尋「DDNS Cloudflare」後,找到了網友分享的操作方式。以下內容都是根據他的說明進行延伸。

系統環境

  • macOS 10.15.2
  • 終端機環境 iTerm2 3.1.6
  • Cloudflare API v4

步驟一:建立一個子網域

首先,先前往 Cloudflare,建立一個用來作為 DDNS 用的 A 紀錄。以這次的例子,我建立了一個 ddns.huanyichuang.com 的子網域紀錄。

步驟二:取得所需的 Zone ID、API Token 與 Record ID

原文所使用的方法是利用 Global API Key 來進行,但基於安全考量,這篇文章會使用 API 存取權杖的方式,給予特定的 Zone 所需權限。

取得 Zone ID

首先,先到 Overview 分頁取得網域紀錄的 Zone ID。

取得存取權杖

接著,在同一頁下方點選 [Get your API Token],開始建立新的 API 存取權杖。

進到 API Tokens 的頁面後,按下 Create Token 以建立新權杖。

在權限部分,由於我們只需要修改 DNS 的權限,因此我們只要點選 [Start with a template],選擇 [Edit zone DNS],系統便會自動帶入預設的權限「Zone 層級、修改 (Edit) DNS 的權限」。接著,在 Zone Resources 的地方,指定特定的網域資源後,就能夠產生存取權杖。

取得 ddns.huanyichuang.com 的 Record ID

將存取權杖記下來後,我們接著要找到特定網域紀錄的 Record ID。這個步驟可以直接透過終端機執行,不需要另外寫成 Shell 檔案。

#!/bin/sh
ZONE_ID="你的 Zone ID"
API_TOKEN="剛才產生的存取權杖"
curl -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
     -H "Authorization: Bearer '$API_TOKEN'" \
     -H "Content-Type: application/json"

執行上述指令後,會回傳 JSON 格式的查詢結果,找到 “name” 與目標相符的紀錄。

步驟三:建立 Shell 指令碼並加以排程

得到 Zone ID、API Token 跟 Record ID 後,接著就用任何文字編輯器建立 Shell 的指令碼檔案。

#!/bin/sh
NEW_IP=`curl -s http://ipv4.icanhazip.com`
CURRENT_IP=`cat ~/tmp/current_ip.txt`
CURRENT_TIME=$(date +"%F %T")
DDNS="ddns.huanyichuang.com"
ZONE_ID="{{步驟二第一段取得的 Zone ID}}"
API_TOKEN="{{步驟二第二段取得的 API Token}}"
RECORD_ID="{{步驟二第三段取得的 Record ID}}"
if [ "$NEW_IP" = "$CURRENT_IP" ]
then
        echo "[$CURRENT_TIME] No Change in IP Adddress" >> ~/tmp/crontab_log.txt
else
curl -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
     -H "Authorization: Bearer $API_TOKEN" \
     -H "Content-Type: application/json" \
     --data '{"type":"A","name":"'$DDNS'","content":"'$NEW_IP'","ttl":1,"proxied":false}' > /dev/null
echo $NEW_IP > ~/tmp/current_ip.txt
echo "[$CURRENT_TIME] IP changed to $NEW_IP" >> ~/tmp/crontab_log.txt
fi

這支程式會先從 icanhazip 的網站取得現在裝置的 IP,與之前用來暫存 IP 位置的檔案 ~/tmp/current_ip.txt 進行比對,如果兩組 IP 一樣,就不需要執行後續程式。如果偵測到 IP 位置改變,就會自動將新 IP 同步到 Cloudflare 上的網域紀錄中。

另外,根據網友的實測,TTL 的單位是「秒」,因此如果寫 1 的話,會變成自動 (從 Cloudflare 後台看,目前預設最小的值是 60 秒)。

將檔案儲存 (以我自己為例,~/bin/ddns.sh) 後,接著在終端機中輸入 crontab -e 編輯排程。在 macOS 的環境下執行,需要再 Shell 檔案前加上 bash 的指令,才會生效。以下是以「每五分鐘檢查一次」為例。

*/5 * * * * bash ~/bin/ddns.sh

後記

學習 DDNS 最早是希望能透過 FileZilla 用來存取 fail2ban 所保護的檔案,避免把自己給封鎖。但是網路上看到的 DDNS 應用通常是結合 NAS 系統,讓自己可以更容易連上家中的 NAS 系統,而不需要背 IP。

目前這個程式的寫法並不聰明,很多資料都還是要先透過 Cloudflare 的介面取得。有空的時候再把取得 Record ID 的步驟自動化好了。

Eric Chuang

正職是廣告行銷人員,因為 Google Tag Manager 的關係開始踏入網站製作的領域,進一步把 WordPress 當成 PHP + HTML + CSS + JavaScript 的學習教材。此外,因為工作的關係,曾經用 Automattic 的 Underscores (_s) 替客戶與公司官網進行全客製化佈景主題開發。

4 則留言

  1. 你好, 非常感謝您的文章, 實際測試時發現一個小問題, 更新DNS時傳入的屬姓
    “ttl”:1
    這邊的單位實際上是秒, 而非分鐘
    如果傳入 1 的話, 會導致 TTL 自動跳成 “自動”
    而非 1 分鐘

    以上提供修正

  2. […] 文章參考來源:利用 Cloudflare API v4 建立 DDNS – 桓桓鄉寇 (huanyichuang.com)主要補充了 Record ID 直接透過指令過濾出來,連貫運行接下來的 IP 修改作法同樣是抓出該域名下所有 DNS 紀錄,再針對要修改的域名 ,利用 jq 取得 Record IDjq 需事先安裝好,用法可以參考這邊:Shell:jq 循环 json 对象, jq 循环 json 数组 […]

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

Exit mobile version