先决条件
开始之前,您需要准备以下物品,以便机器人正常工作。.
- Cloudflare账户 以及管理域名 DNS 的权限。.
- 创建 API令牌 在 Cloudflare 中具有访问级别 区域:DNS:编辑 针对所需区域。.
- 访问 区域 ID 域名和记录名称(例如
vpn.example.com). - 在 AWS (EC2) 中具有可访问的公共 IP 地址的服务器或服务,或者可用于查询的 AWS API 访问权限。.
- 基本工具:
卷曲,jqPython 3+请求. - 安全建议:请将令牌保存在…… AWS Secrets Manager 或受保护的环境变量。.
从 AWS 获取 IP 地址的方法
从亚马逊服务器获取公网 IP 地址有几种常见方法;方法的选择取决于具体实施场景。.
1. EC2 内部(元数据)
如果脚本运行在同一个 EC2 实例上,最简单的方法是使用元数据服务:
curl -s http://169.254.169.254/latest/meta-data/public-ipv4对于 IPv6:
curl -s http://169.254.169.254/latest/meta-data/ipv62. 使用 AWS CLI/SDK
使用 描述实例 您可以通过标签或实例 ID 进行筛选来获取 IP 地址。使用 IAM 角色,您可以省去访问密钥。.
aws ec2 describe-instances --instance-ids i-0123456789abcdef --query "Reservations[].Instances[].PublicIpAddress" --output text3. 弹性 IP 和复杂网络
对于弹性 IP 或复杂的网络配置,请检查与以下各项的关联: 描述地址 这种方法是合适的。.
机器人设计:拟议架构
根据需求和规模的不同,有几种合适的建筑模式:
- 简单方案: 该脚本运行在同一个 EC2 实例上,每隔 n 分钟检查一次 IP 地址;如果 IP 地址发生变化,则会使用 Cloudflare API 进行更新。.
- 可扩展选项: 不同区域的多个 EC2 实例 → 中央 Lambda/Serverless 负责收集 IP 地址并更新多个记录。.
- 保存状态: 将最后注册的 IP 地址存储在本地文件或 S3/数据库中,以避免不必要的更新。.
- 错误处理和重试: 使用退避机制和日志记录(CloudWatch)。.
使用 Bash + curl 快速实现(实用示例)
本示例假设脚本运行在同一个 EC2 实例上,并且正在更新 A 记录。首先,获取一次区域 ID 和记录 ID:
curl -s -X GET "https://api.cloudflare.com/client/v4/zones?name=example.com" -H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json" | jq -r '.result[0].id'
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=vpn.example.com" -H "Authorization: Bearer $CF_API_TOKEN" -H "Content-Type: application/json" | jq -r '.result[0].id'示例脚本 更新 IP 地址脚本:
#!/usr/bin/env bash
set -e
CF_TOKEN="---FROM SECRETS MANAGER OR ENV---"
ZONE_ID="your_zone_id"
RECORD_NAME="vpn.example.com"
RECORD_ID="your_record_id"
PROXY=false
TTL=120
get_ip() {
curl -s http://169.254.169.254/latest/meta-data/public-ipv4
}
current_ip=$(get_ip)
old_ip_file="/var/run/current_ip_${RECORD_NAME}"
if [ -f "$old_ip_file" ]; then
old_ip=$(cat "$old_ip_file")
else
old_ip=""
fi
if [ "$current_ip" = "" ]; then
echo "No public IP found" >&2
exit 1
fi
if [ "$current_ip" != "$old_ip" ]; then
echo "Updating Cloudflare DNS from $old_ip to $current_ip"
payload=$(jq -n --arg type "A" --arg name "$RECORD_NAME" --arg content "$current_ip" --argjson proxied $PROXY --argjson ttl $TTL '{type:$type, name:$name, content:$content, proxied:$proxied, ttl:$ttl}')
resp=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" -H "Authorization: Bearer $CF_TOKEN" -H "Content-Type: application/json" --data "$payload")
success=$(echo "$resp" | jq -r '.success')
if [ "$success" = "true" ]; then
echo "$current_ip" > "$old_ip_file"
echo "Update successful"
else
echo "Update failed: $resp" >&2
exit 2
fi
else
echo "IP unchanged ($current_ip)"
fi尖端: 从 jq 用于构建 JSON。存储 IP 地址。 /var/run 这样做是为了防止不必要的更新。请将令牌保存在环境变量或密钥管理器中,不要保存在脚本中。.
使用 Python 实现可靠功能(实际示例)
这是一个 Python 脚本示例,可以作为 Lambda 函数运行,也可以在服务器上运行,并管理多个记录。.
requests
boto3import os, requests, json
CF_TOKEN = os.environ['CF_TOKEN']
ZONE_ID = os.environ['ZONE_ID']
RECORDS = json.loads(os.environ.get('RECORDS_JSON', '[]'))
HEADERS = {
"Authorization": f"Bearer {CF_TOKEN}",
"Content-Type": "application/json"
}
def get_ec2_public_ip():
try:
r = requests.get("http://169.254.169.254/latest/meta-data/public-ipv4", timeout=2)
if r.ok:
return r.text.strip()
except:
pass
return None
def find_record_id(name, type="A"):
url = f"https://api.cloudflare.com/client/v4/zones/{ZONE_ID}/dns_records?name={name}&type={type}"
r = requests.get(url, headers=HEADERS)
data = r.json()
if data.get("success") and data["result"]:
return data["result"][0]["id"]
return None
def update_record(record_id, name, ip, type="A", ttl=120, proxied=False):
url = f"https://api.cloudflare.com/client/v4/zones/{ZONE_ID}/dns_records/{record_id}"
payload = {"type": type, "name": name, "content": ip, "ttl": ttl, "proxied": proxied}
r = requests.put(url, headers=HEADERS, json=payload)
return r.json()
def lambda_handler(event, context=None):
ip = get_ec2_public_ip()
if not ip:
print("No public IP found")
return
for rec in RECORDS:
name = rec["name"]
typ = rec.get("type","A")
rec_id = find_record_id(name, typ)
if not rec_id:
print(f"No record id for {name}")
continue
resp = update_record(rec_id, name, ip, typ, rec.get("ttl",120), rec.get("proxied",False))
print(resp)
if __name__ == "__main__":
lambda_handler(None)部署和管理(systemd、cron、Lambda)
运行和管理机器人的一些常见方法:
- systemd创建一个每 5 分钟运行一次脚本的单元,或者创建一个监视更改的守护服务。.
- cron:定期执行(每 n 分钟一次),使用本地状态内存以避免冗余更新。.
- AWS Lambda + EventBridge:定期执行,无需服务器维护,具有 IAM 角色和密钥管理器。.
- 日志:将日志发送到 CloudWatch 并定义持续性错误的警报。.
安全性、密钥存储和最小访问权限
为降低风险并遵循最小权限原则,需要满足以下安全要求:
- API Token Limited: 在 Cloudflare 中,使用 API 令牌而不是全局 API 密钥,并将范围限制为 区域:DNS:编辑 仅限所需区域。.
- IAM角色: 在 AWS 中,使用 IAM 角色管理 EC2/Lambda,并使用 AWS Secrets Manager 或 SSM Parameter Store 存储 CF_TOKEN。.
- 从日志中删除令牌: 清除令牌存储中的日志并使用 TLS。.
- 限制更新次数: 如果 IP 地址没有改变,请不要发送任何更新,以免受到速率限制。.
实用技巧:TTL、代理、IPv6、故障排除和监控
- TTL较低的 TTL(例如 120 秒)有利于快速更改,但会增加查询次数。.
- 代理(Cloudflare 橙色云)如果您希望流量通过 Cloudflare(CDN、WAF、DDoS 防护),
proxy=true. 但对于像交易所这样的允许列表 IP,你需要proxy=false为了保护真正的知识产权。. - IPv6如果 IPv6 地址存在,则更新
AAAA记录也至关重要。. - 重试:遇到网络错误时,使用指数退避并记录错误。.
- 监测在控制面板中保留成功/失败的更新、API 响应时间和 IP 更改等指标,并设置频繁错误通知。.
交易、游戏和网络方面的比较和实用建议
贸易: 网络延迟和稳定性至关重要。建议使用靠近交易所且具备防DDoS攻击能力的交易型VPS。对于固定IP地址,建议使用弹性IP或更新机器人。某些交易所API可能需要额外配置。 proxy=false 有必要。.
游戏: 低延迟和稳定性至关重要。选择靠近玩家的服务器位置。是否使用 Cloudflare Spectrum 代理,取决于具体游戏。.
Web 和 API: 使用 Cloudflare proxy=true 推荐用于 CDN、WAF 和 DDoS 防护。在这种情况下,更改 IP 地址并非至关重要,但必须管理源服务器。.
结论
使用上述方法,您可以根据从 EC2 收到的 IP 地址自动安全地更新 Cloudflare 上的 DNS 记录。.
- 从 API Token Limited 使用 Cloudflare。.
- 从 IAM 角色 和 秘密管理器 充分利用AWS。.
- 实施适当的日志记录、监控和重试机制,使流程更加稳健。.
- 针对特定需求(交易、游戏、人工智能/渲染),使用专用服务器、防 DDoS 攻击和优化位置,以降低延迟并提高稳定性。.
接受技术援助的意愿
如果您在专业实施、选择合适的地点或在 AWS 和 Cloudflare 上安全部署方面需要帮助,您可以联系技术团队,我们将为您提供定制解决方案和全面支持。.









