记一次 Cloudflare DDNS设置过程

“家里云”或 AWS Lightsail 之类的服务商通常会动态分配公网 IP。IP 地址可能随着重启或运行时间变化而改变,这会导致使用域名访问设备(如 NAS 或应用服务)时非常不便:只要 IP 变了,就必须手动到域名托管服务修改 DNS 记录。

为了解决这个问题,可以使用 DDNS(Dynamic Domain Name System,动态域名服务)。DDNS 能在公网 IP 变化时自动更新指定域名的 A 记录,让域名始终指向正确的服务器,即使 IP 改变,依然能够通过固定域名访问服务。

部分路由器原生支持 DDNS,但在笔者的场景中,VPS 每次重启后都会获得新的 IP,因此需要依赖脚本并结合 Cloudflare API,实现自动更新 DNS 记录的能力。

本文将整体过程拆分为两个部分:

  1. 获取 Cloudflare API Token 及必要的 Zone ID / Record ID
  2. 编写 DDNS 脚本并设置定时运行

1. Cloudflare Token 与相关 ID 获取

  1. 生成 Cloudflare API Token

    • 访问:https://dash.cloudflare.com/profile/api-tokens
    • 点击 创建令牌(Create Token)
    • 在模板中选择 编辑区域 DNS(Edit Zone DNS)
    • 权限配置:区域(Zone) → DNS → 编辑(Edit)
    • 资源配置:包括(Include) → 特定区域 → <你的域名>
    • 完成创建并保存 API Token
  2. 创建 DNS A 记录并获取 Zone ID / Record ID

    • 在 Cloudflare 的域名概览页面复制该域名对应的 Zone ID
    • 为域名新增一条 A 记录,例如主域名为 abc.com,可新建 ddns.abc.com,IP 可随意填写
    • 打开:
      https://dash.cloudflare.com/api/v4/zones/<ZONE_ID>/dns_records?per_page=200&order=name&direction=asc
      
      其中,<ZONE_ID> 替换为域名对应的ZONE_ID,并找到 ddns.abc.com (要设置子域名) 对应的 Record ID

至此,我们已经获得脚本所需的四项关键信息:

  • API Token:用于 API 鉴权
  • Zone ID:对应域名标识
  • Record ID:指定要更新的解析记录
  • Record Name:如 ddns.abc.com

2. DDNS 脚本编写与定时执行

  1. 在 VPS 上编写脚本

    创建 cf-ddns.sh 文件,并将下面脚本中开头的变量替换为你自己的 API Token、Zone ID、Record ID 及域名:

    #!/bin/bash
    # Cloudflare API Token
    API_TOKEN="xx"
    # Cloudflare Zone ID
    ZONE_ID="xxx"
    # DNS记录ID
    RECORD_ID="xxx"
    # 需要更新的域名
    RECORD_NAME="ddns.abc.com"
    
    # 时间戳
    ts() {
        date "+[%Y-%m-%d %H:%M:%S]"
    }
    
    # 获取当前公网IP
    CURRENT_IP=$(curl -s http://ipv4.icanhazip.com)
    
    # 获取DNS记录内容
    DNS_RECORD_RESPONSE=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \
         -H "Authorization: Bearer ${API_TOKEN}" \
         -H "Content-Type: application/json")
    
    DNS_RECORD_IP=$(echo "$DNS_RECORD_RESPONSE" | sed -n 's/.*"content":"\([^"]*\)".*/\1/p')
    
    # 判断是否需要更新
    if [ "$CURRENT_IP" == "$DNS_RECORD_IP" ]; then
        echo "$(ts) 当前IP: ${CURRENT_IP} | 解析IP: ${DNS_RECORD_IP} --> DNS无需更改"
    else
        RESPONSE=$(curl -s -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\":\"${RECORD_NAME}\",\"content\":\"${CURRENT_IP}\",\"ttl\":120,\"proxied\":false}")
    
        if echo "$RESPONSE" | grep -q "\"success\":true"; then
            echo "$(ts) 当前IP: ${CURRENT_IP} | 解析IP: ${DNS_RECORD_IP} --> DNS更改为: ${CURRENT_IP}"
        else
            echo "$(ts) 当前IP: ${CURRENT_IP} | 解析IP: ${DNS_RECORD_IP} --> 更新失败: ${RESPONSE}"
        fi
    fi
    
  2. 赋予执行权限并验证脚本

    chmod +x ./cf-ddns.sh
    ./cf-ddns.sh
    
  3. 配置定时任务

    使用 crontab -e 编辑定时任务,加入以下内容(按需修改路径):

    @reboot /root/cf-ddns.sh >> /root/ddns/ddns.log 2>&1
    */2 * * * * /root/cf-ddns.sh >> /root/ddns/ddns.log 2>&1
    

保存退出后,等待数分钟即可在日志目录看到更新记录,表示 DDNS 已成功运行。


参考文献

[1] 使用Cloudflare实现DDNS: https://www.ryanshang.com/2025/02/03/使用Cloudflare实现DDNS/
[2] cloudflare ddns通过API更新动态IP域名解析: https://blog.dollcode.cn/cloudflare-ddns

posted @ 2025-12-03 17:49  思言行知  阅读(63)  评论(0)    收藏  举报