如何設置Cloudflare動態DNS

假設您從家用網絡發布了一個網站,並創建了一個將指向您路由器的公共IP地址的DNS記錄。當您的公共IP地址更改時,您如何保持DNS記錄的更新?也許您應該考慮設置Cloudflare動態DNS。

互聯網服務提供商(ISP)通常為其用戶分配動態IP地址,這些地址可能隨時更改。因此,您的DNS記錄仍然指向不再屬於您的IP地址,您的網站變得無法訪問。

繼續閱讀,因為本教程將幫助您使用Cloudflare的應用程序編程接口(API)和PowerShell來保持DNS記錄的更新。讓我們開始吧!

先決條件

如果您計劃跟隨本教程進行實作,以下是您需要的要求。

  • A computer with PowerShell 7.1 where you’ll run the Cloudflare dynamic DNS update script. This tutorial will use a Windows 10 computer.
  • A script editor of your choice. This tutorial will use Visual Studio Code v1.59.1 (recommended).
  • A domain that you already own. The example domain in this tutorial is lazyexchangeadmin.cyou.

免費頂級域名(TLD),如.ml、.ga、.tk、.cf和.gq,不適用於Cloudflare動態DNS自動化,並且無法在本教程中使用。

  • A Cloudflare account. A free account is enough to use in this tutorial.
    • 您一定已經將您的域名添加到了Cloudflare中。
    • 您一定已經在Cloudflare中的您的域名下添加了一個DNS記錄。本教程中的DNS A記錄將是demo.lazyexchangeadmin.cyou,初始IP地址為0.0.0.0。
Sample DNS A record in Cloudflare

什麼是Cloudflare動態DNS?

DNS記錄本質上是靜態的,因此無法與動態IP地址很好地配合。現在,為了解決這個問題,您需要設置動態DNS。幸運的是,Cloudflare提供了一個API,可以讓您以程序化的方式管理DNS記錄。

要設置Cloudflare動態DNS,您需要在您的網絡內運行一個進程,執行兩個主要操作:獲取您網絡的當前公共IP地址,並自動更新相應的DNS記錄。

下面的圖顯示了 Cloudflare 動態 DNS 更新流程的高級概要。

Cloudflare Dynamic DNS update flow

有許多可安裝的動態 DNS 客戶端,主要用於 Linux 系統,例如 Ubuntu 伺服器或 Raspberry PI。也存在第三方動態 DNS 服務,可能是付費的或免費的。但在本教程中,您將部署一個在 PowerShell 7.1 上運行的 DNS 更新腳本。

獲取 Cloudflare API 標記

當以程式方式更新 Cloudflare 動態 DNS 記錄時,您的腳本必須對 Cloudflare API 進行身份驗證。只有這樣,Cloudflare 才允許您對帳戶中的 DNS 記錄進行更改。

Cloudflare 允許您創建具有足夠權限的 API 標記。然後,您可以使用 Cloudflare 帳戶的用戶名和生成的 API 標記來對 Cloudflare API 进行身份验证。

要创建 Cloudflare API 標記,請按照以下步驟進行。

1. 打開瀏覽器,訪問 https://dash.cloudflare.com/login/,並登錄到您的 Cloudflare 帳戶。

2. 在 Cloudflare 控制面板中登錄後,點擊右上角的個人資料按鈕,然後點擊 我的個人資料

Opening your Cloudflare profile page

3. 接下來,點擊 API 標記 鏈接標籤。在 API 標記 部分,點擊 創建標記 按鈕。以下示例假設您尚未創建任何 API 標記。

Clicking Create Token

4. 在 API 令牌模板 列表中,點擊 編輯區域 DNS 模板以使用它。此模板允許您創建一個具有編輯權限的 API 令牌,以編輯您帳戶中的所有或選定的 DNS 區域。

Selecting the Edit zone DNS API token template

5. 在 創建令牌 頁面的 區域資源 部分下,點擊最右邊的下拉框,選擇要包含在此 API 令牌訪問權限中的 DNS 區域。選擇 DNS 區域後,點擊 繼續到摘要

選擇性地,要限制 API 令牌的有效期,請填寫 開始日期結束日期TTL 部分下。如果留空,API 令牌將沒有到期日期。

Selecting the DNS Zone

6. 檢查摘要,確保 API 具有對先前選定的 DNS 區域的 DNS:Edit 權限。最後,點擊 創建令牌 以創建 API 令牌。

Reviewing the API token permission

7. 創建 API 令牌後,複製令牌值並確保安全存儲。請像處理密碼一樣處理 API 令牌。

Copying the API Token

8. 返回到 API 令牌 選項卡,確認您創建的 API 令牌是否存在。

Verifying the API Token

設置 Cloudflare 動態 DNS 更新腳本

您現在擁有 Cloudflare 帳戶和具有編輯 DNS 區域權限的 Cloudflare API 令牌。接下來呢?您需要使用 API 令牌並將其與一個腳本集成起來,該腳本將以程序方式更新 Cloudflare 動態 DNS 記錄。

此教程为您提供了一个用于在Cloudflare中更新DNS记录的可工作的PowerShell脚本。

保存脚本

按照以下步骤将Cloudflare动态DNS PowerShell脚本保存到客户端计算机上。

1. 决定将脚本存储在哪个文件夹中,并在该文件夹不存在时创建该文件夹。在此示例中,脚本位置位于C:\CloudflareDDNS

2. 打开您的代码编辑器,例如VSCode,并创建一个名为Update-CloudflareDDNS.ps1的新PowerShell脚本文件。将脚本保存在C:\CloudflareDDNS文件夹中。

3. 复制下面的脚本,粘贴到您的代码编辑器中,并保存文件。请参考内联注释以了解脚本的功能。

#需要 -版本 7.1

[cmdletbinding()]
param (
    [parameter(Mandatory)]
    $Email,
    [parameter(Mandatory)]
    $Token,
    [parameter(Mandatory)]
    $Domain,
    [parameter(Mandatory)]
    $Record
)

# 建立一次請求標頭。這些標頭將在整個腳本中使用。
$headers = @{
    "X-Auth-Email"  = $($Email)
    "Authorization" = "Bearer $($Token)"
    "Content-Type"  = "application/json"
}

#區域 Token 測試
## 這個區塊驗證你的 API 金鑰是否有效。
## 如果無效,腳本將終止。

$uri = "https://api.cloudflare.com/client/v4/user/tokens/verify"

$auth_result = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers -SkipHttpErrorCheck
if (-not($auth_result.result)) {
    Write-Output "API token validation failed. Error: $($auth_result.errors.message). Terminating script."
    # 結束腳本
    return
}
Write-Output "API token validation [$($Token)] success. $($auth_result.messages.message)."
#結束區域

#區域取得區域識別碼
## 根據區域名稱取得網域的識別碼。如果找不到識別碼,腳本將終止。
$uri = "https://api.cloudflare.com/client/v4/zones?name=$($Domain)"
$DnsZone = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers -SkipHttpErrorCheck
if (-not($DnsZone.result)) {
    Write-Output "Search for the DNS domain [$($Domain)] return zero results. Terminating script."
    # 結束腳本
    return
}
## 儲存 DNS 區域識別碼
$zone_id = $DnsZone.result.id
Write-Output "Domain zone [$($Domain)]: ID=$($zone_id)"
#結束區域

#區域取得 DNS 記錄
## 從 Cloudflare 取得現有 DNS 記錄的詳細資訊。
$uri = "https://api.cloudflare.com/client/v4/zones/$($zone_id)/dns_records?name=$($Record)"
$DnsRecord = Invoke-RestMethod -Method GET -Uri $uri -Headers $headers -SkipHttpErrorCheck
if (-not($DnsRecord.result)) {
    Write-Output "Search for the DNS record [$($Record)] return zero results. Terminating script."
    # 結束腳本
    return
}
## 儲存 DNS 記錄中的現有 IP 位址
$old_ip = $DnsRecord.result.content
## 儲存 DNS 記錄類型值
$record_type = $DnsRecord.result.type
## 儲存 DNS 記錄識別碼值
$record_id = $DnsRecord.result.id
## 儲存 DNS 記錄 TTL 值
$record_ttl = $DnsRecord.result.ttl
## 儲存 DNS 記錄代理值
$record_proxied = $DnsRecord.result.proxied
Write-Output "DNS record [$($Record)]: Type=$($record_type), IP=$($old_ip)"
#結束區域

#區域取得當前公共 IP 位址
$new_ip = Invoke-RestMethod -Uri 'https://v4.ident.me'
Write-Output "Public IP Address: OLD=$($old_ip), NEW=$($new_ip)"
#結束區域

#區域更新動態 DNS 記錄
## 比較當前 IP 位址與 DNS 記錄
## 如果當前 IP 位址與 DNS 記錄 IP 位址不匹配,則更新 DNS 記錄。
if ($new_ip -ne $old_ip) {
    Write-Output "The current IP address does not match the DNS record IP address. Attempt to update."
    ## 使用新的 IP 位址更新 DNS 記錄
    $uri = "https://api.cloudflare.com/client/v4/zones/$($zone_id)/dns_records/$($record_id)"
    $body = @{
        type    = $record_type
        name    = $Record
        content = $new_ip
        ttl     = $record_ttl
        proxied = $record_proxied
    } | ConvertTo-Json

    $Update = Invoke-RestMethod -Method PUT -Uri $uri -Headers $headers -SkipHttpErrorCheck -Body $body
    if (($Update.errors)) {
        Write-Output "DNS record update failed. Error: $($Update[0].errors.message)"
        ## 結束腳本
        return
    }

    Write-Output "DNS record update successful."
    return ($Update.result)
}
else {
    Write-Output "The current IP address and DNS record IP address are the same. There's no need to update."
}
#結束區域

執行腳本

現在您已經保存了Cloudflare動態DNS更新腳本,接下來該做什麼呢?在部署腳本之前,測試其功能是否正常是必不可少的。執行腳本需要四個詳細信息才能成功,它們是:

  • 電子郵件 – 這是您Cloudflare帳戶的電子郵件地址。
  • 令牌 – 您之前從Cloudflare帳戶中創建的API令牌。
  • 域名 – 包含您要更新的DNS記錄的DNS域名(例如,lazyexchangeadmin.cyou)。
  • 記錄 – 您要更新的DNS記錄(例如,demo.lazyexchangeadmin.cyou)。

要執行腳本,請按照以下步驟進行。

1. 首先,打開PowerShell會話。或者,如果您使用VSCode,請改用VSCode PowerShell終端。

2. 接下來,執行DNS記錄查找以確認當前DNS記錄的IP地址。為此,運行Resolve-DnsName cmdlet,如下所示。請確保使用-Name參數提供完全限定的域名(FQDN)。

Resolve-DnsName -Name demo.lazyexchangeadmin.cyou

該命令應返回您查找的DNS記錄,包括其IP地址。

Looking up a DNS record before the Cloudflare dynamic DNS update

3. 現在,執行以下命令調用 Update-CloudflareDDNS.ps1 腳本來更新 Cloudflare 中的 DNS 記錄。請確保更改 EmailTokenDomainRecord。以下命令假設您的腳本位於 C:\CloudflareDDNS\Update-CloudflareDDNS.ps1

C:\CloudflareDDNS\Update-CloudflareDDNS.ps1 `
-Email '[email protected]' `
-Token 'kGW8n........eJl5a' `
-Domain 'lazyexchangeadmin.cyou' `
-Record 'demo.lazyexchangeadmin.cyou'

然後,腳本執行以下操作,如下圖所示。

  1. 驗證 API 令牌。
  2. 查找包含要更新的 DNS 記錄的域。
  3. 查找要更新的 DNS 記錄。
  4. 將 DNS 記錄的 IP 地址與實際的外部或公共 IP 地址進行比較。
  5. 在 Cloudflare 中更新 DNS 記錄的 IP 地址。
  6. 顯示動態 DNS 更新結果。
Running the Cloudflare dynamic DNS update script

4. 返回到您的 Cloudflare 控制台,並驗證 DNS 記錄是否反映了新的 IP 地址。如下圖所示,在運行更新腳本後,IP 地址已更改為外部 IP 地址值。

Verifying the DNS record in Cloudflare

5. 最後,像在步驟 2 中所做的那樣,執行另一個 DNS 記錄查找,以確認新的 IP 地址是否已公開傳播。

Resolve-DnsName -Name demo.lazyexchangeadmin.cyou

DNS 記錄傳播可能需要幾分鐘、幾小時,甚至幾天。在此示例中,Cloudflare 傳播僅花費不到一分鐘。

Looking up a DNS record after the Cloudflare dynamic DNS update

安排 Cloudflare 動態 DNS 更新任務

這時,您已經有一個可以更新 Cloudflare 動態 DNS 記錄的工作腳本。但是,手動運行腳本並不是目標。您必須確保動態 DNS 更新以所需的頻率自動運行。

根據您使用的操作系統,安排腳本運行的方式會有所不同,比如在 Linux 中使用 cron 作業。本教程將創建一個 Windows 定期任務,每五分鐘運行一次 Cloudflare 動態 DNS 更新腳本。

定義定期任務操作

您的定期任務必須有一個操作,您可以通過運行 New-ScheduledTaskAction cmdlet 來創建它。在此示例中,操作是使用 PowerShell 可執行文件 Update-CloudflareDDNS.ps1 運行腳本。

為此,以管理員身份打開新的 PowerShell 窗口。然後,複製並在 PowerShell 中運行下面的代碼。請務必更改 $scriptPath$Email, $Token$Domain$Record 變數。

# 定義預定任務動作屬性
## 輸入 PowerShell 腳本路徑
$scriptPath = 'C:\CloudflareDDNS\Update-CloudflareDDNS.ps1'
## Cloudflare 帳戶的電子郵件地址
$Email = '[email protected]'
## Cloudflare API 令牌
$Token = 'kGW8n........eJl5a'
## DNS 域名
$Domain = 'lazyexchangeadmin.cyou'
## 要更新的 DNS 記錄
$Record = 'demo.lazyexchangeadmin.cyou'

# 創建預定任務動作對象
$taskAction = New-ScheduledTaskAction `
    -Execute "pwsh.exe" `
    -Argument "-File $scriptPath -Email $Email -Token $Token -Domain $Domain -Record $Record"

創建預定任務觸發器

在定義任務的操作後,您必須通過運行 New-ScheduledTaskTrigger cmdlet 來為任務創建觸發器或計劃。複製下面的代碼並在 PowerShell 中運行它,以創建一個在十年內每五分鐘運行一次的新任務觸發器。

# 創建新的預定任務觸發器計劃
## 觸發器 = 每 5 分鐘,持續 10 年。
$taskTrigger = New-ScheduledTaskTrigger `
-Once `
-At (Get-Date -Minute 0 -Second 0) `
-RepetitionInterval (New-TimeSpan -Minutes 5) `
-RepetitionDuration (New-TimeSpan -Days 3650)

在系統中註冊新的預定任務

最後,您準備在計算機上註冊新的定期任務。為此,您需要運行 Register-ScheduledTask 命令,與下面的代碼相同。複製下面的代碼並在 PowerShell 中運行它以註冊定期任務。

生成的定期任務將在 本地 SYSTEM 帳戶 下運行。如有需要,請隨意 指定不同的使用者帳戶 來運行定期任務。

# 在系統中註冊定期任務。
## 定期任務名稱
$TaskName = 'Update Cloudflare Dynamic DNS'
## 定期任務描述
$Description = 'Update Cloudflare DDNS Entry every 5 minutes'
## 創建定期任務
Register-ScheduledTask `
-TaskName $TaskName `
-Description $Description `
-Action $taskAction `
-Trigger $taskTrigger `
-User 'NT AUTHORITY\SYSTEM'

如下所示,命令創建了定期任務,狀態為就緒。從這一點開始,腳本將以五分鐘的間隔運行。

Registering the New Scheduled Task

結論

保持 DNS 記錄與動態 IP 地址變更的更新並不一定是一個挑戰。您也不需要為動態 DNS 服務付費!通過在 Cloudflare 中管理您的 DNS 區域,您可以利用其 API,允許您以程序方式更新您的 DNS 記錄。

您在本教程中學習了如何使用 API 調用、PowerShell 7 和定期任務來更新 Cloudflare 動態 DNS 記錄的組合。所有這些都允許您設置您的 Cloudflare 動態 DNS 更新機制一次並保持定期更新而無需監督。

您會考慮使用 Cloudflare 管理您的 DNS 區域以獲取其 API 的好處嗎?還是您知道更方便和易於使用的方式?

Source:
https://adamtheautomator.com/cloudflare-dynamic-dns/