批量修改 Cloudflare DNS 记录最稳妥的方式是使用 API v4 配合脚本,先导出备份再执行变更,适合需要同时调整多条记录的场景。
先说结论:通过 API 脚本批量操作是可行的,但必须严格控制权限和速率,避免误操作导致域名解析中断。
- 适合:需要同时修改几十条以上记录,或需要定期同步记录的场景
- 先准备:创建仅限 DNS 编辑权限的 API Token,并导出当前所有记录作为备份
- 验收:修改后通过 dig 命令验证解析结果,并观察 Cloudflare dashboard 状态
- 风险提示:API 不具备事务性,部分失败可能导致状态不一致,务必先备份
环境准备与备份
在执行任何修改前,必须获取 Zone ID 并备份现有记录。这是出错后的唯一回滚依据。
1. 获取 Zone ID:在 Cloudflare 控制台概述页面右侧可以找到,或通过 API 查询域名列表获取。
2. 创建 API Token:进入 User Profile > API Tokens,创建自定义令牌,权限仅勾选“区域 - DNS - 编辑”,限制仅限特定区域。不要使用 Global API Key。
3. 备份现有记录:使用以下命令将当前 DNS 记录保存为 JSON 文件,建议带上时间戳。
curl -X GET "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/dns_records" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
> dns_backup_$(date +%F).json
批量修改脚本实现
单个记录修改的 curl 示例如下,但批量操作需要循环、错误处理和速率控制。推荐使用 Python 脚本,便于处理 JSON 数据和逻辑判断。
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":"example.com","content":"192.0.2.1","ttl":120,"proxied":false}'
以下是完整的 Python 批量处理脚本,包含重试逻辑和速率限制:
import requests
import time
import json
import sys
# 配置区域
API_TOKEN = "YOUR_API_TOKEN"
ZONE_ID = "YOUR_ZONE_ID"
BASE_URL = "https://api.cloudflare.com/client/v4/zones/" + ZONE_ID + "/dns_records"
headers = {
"Authorization": f"Bearer {API_TOKEN}",
"Content-Type": "application/json"
}
# 待修改记录列表 (实际使用中可从文件读取)
records_to_update = [
{"id": "RECORD_ID_1", "type": "A", "name": "www.example.com", "content": "1.2.3.4", "proxied": False},
{"id": "RECORD_ID_2", "type": "CNAME", "name": "blog.example.com", "content": "target.com", "proxied": True}
]
def update_record(record):
url = f"{BASE_URL}/{record['id']}"
data = {
"type": record["type"],
"name": record["name"],
"content": record["content"],
"ttl": 120,
"proxied": record.get("proxied", False)
}
try:
resp = requests.put(url, headers=headers, json=data, timeout=10)
if resp.status_code == 200:
print(f"[Success] {record['name']}")
return True
else:
print(f"[Failed] {record['name']} - {resp.status_code} - {resp.text}")
return False
except Exception as e:
print(f"[Error] {record['name']} - {str(e)}")
return False
# 执行批量更新
for index, record in enumerate(records_to_update):
success = update_record(record)
if not success:
print("检测到失败,建议检查日志后手动回滚或重试")
# 生产环境可选择 break 停止或继续
# 速率限制:避免触发 API 封禁,每次请求间隔至少 1 秒
if index < len(records_to_update) - 1:
time.sleep(1)
print("批量操作完成")
如果需要修改大量记录,建议将 records_to_update 替换为读取本地 JSON 配置文件,格式如下:
[
{"id": "...", "type": "A", "name": "...", "content": "...", "proxied": false},
{"id": "...", "type": "A", "name": "...", "content": "...", "proxied": false}
]
回滚与验证
1. 验证生效:使用 dig 命令查询特定记录,对比返回的 IP 地址是否与修改后一致。注意本地 DNS 缓存可能导致验证结果滞后。
dig @1.1.1.1 example.com
# 或清除本地缓存后查询
sudo dscacheutil -flushcache # macOS
ipconfig /flushdns # Windows
同时登录 Cloudflare 控制台查看 DNS 列表,确认记录状态正常且无报错提示。
2. 回滚方案:Cloudflare API 不支持事务回滚。如果脚本中途失败,需利用之前备份的 dns_backup_*.json 文件。提取备份文件中对应记录 ID 的原始内容,再次运行修改脚本将值改回原状。
常见风险与排查
- 速率限制:API 有请求频率上限,脚本中必须加入
time.sleep延时,不要并发过高,否则返回 429 状态码。 - 缓存生效:DNS 修改受 TTL 影响,验证时需指定权威 DNS 服务器(如 1.1.1.1)以避免本地缓存干扰。
- 代理状态:修改记录时注意
proxied参数,橙色云朵(CDN 代理)和灰色云朵(仅 DNS)效果不同,误改可能导致 CDN 失效或暴露源站 IP。 - 权限过大:务必使用 scoped API Token,不要使用 Global API Key,一旦泄露后果严重。
- 部分失败:脚本循环中某条记录失败不会影响其他记录,但会导致最终状态不一致,需检查脚本输出日志。
参考来源
- Cloudflare API Documentation, "API token permissions", https://developers.cloudflare.com/fundamentals/api/get-started/create-token/
- Cloudflare API Documentation, "DNS Records", https://developers.cloudflare.com/api/operations/dns-record-for-a-zone-list-dns-records