记一次 Cloudflare DDNS设置过程
“家里云”或 AWS Lightsail 之类的服务商通常会动态分配公网 IP。IP 地址可能随着重启或运行时间变化而改变,这会导致使用域名访问设备(如 NAS 或应用服务)时非常不便:只要 IP 变了,就必须手动到域名托管服务修改 DNS 记录。
为了解决这个问题,可以使用 DDNS(Dynamic Domain Name System,动态域名服务)。DDNS 能在公网 IP 变化时自动更新指定域名的 A 记录,让域名始终指向正确的服务器,即使 IP 改变,依然能够通过固定域名访问服务。
部分路由器原生支持 DDNS,但在笔者的场景中,VPS 每次重启后都会获得新的 IP,因此需要依赖脚本并结合 Cloudflare API,实现自动更新 DNS 记录的能力。
本文将整体过程拆分为两个部分:
- 获取 Cloudflare API Token 及必要的 Zone ID / Record ID
- 编写 DDNS 脚本并设置定时运行
1. Cloudflare Token 与相关 ID 获取
-
生成 Cloudflare API Token
- 访问:https://dash.cloudflare.com/profile/api-tokens
- 点击 创建令牌(Create Token)
- 在模板中选择 编辑区域 DNS(Edit Zone DNS)
- 权限配置:
区域(Zone) → DNS → 编辑(Edit) - 资源配置:
包括(Include) → 特定区域 → <你的域名> - 完成创建并保存 API Token
-
创建 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 脚本编写与定时执行
-
在 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 -
赋予执行权限并验证脚本
chmod +x ./cf-ddns.sh ./cf-ddns.sh -
配置定时任务
使用
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

浙公网安备 33010602011771号