Files
homelab/scripts/cloudflare-ddns.sh
T

58 lines
2.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# ==============================================================================
# cloudflare-ddns.sh
# 用途:定时检测家庭宽带真实公网 IPv4 并自动同步至 Cloudflare (home.961504.xyz & *.home.961504.xyz)
# 运行频率:通过 macOS LaunchAgent 每 5 分钟自动执行一次
# ==============================================================================
set -euo pipefail
# 从环境变量或 .env 读取 Token
if [ -f "$HOME/homelab/.env" ]; then
# shellcheck disable=SC1091
source "$HOME/homelab/.env"
fi
ZONE_ID="${CF_ZONE_ID:-8cf327569373837f075fa7f9e5bb7edd}"
TOKEN="${CF_API_TOKEN}"
# 获取国内真实出口公网 IP(绕过国外代理分流)
WAN_IP=$(curl -4 -s --max-time 5 https://myip.ipip.net | grep -oE '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -n 1 || true)
if [ -z "$WAN_IP" ]; then
WAN_IP=$(curl -4 -s --max-time 5 http://members.3322.org/dyndns/getip | tr -d '[:space:]' || true)
fi
if [ -z "$WAN_IP" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: 无法获取当前家庭宽带公网 IP"
exit 1
fi
CACHE_FILE="$HOME/homelab/backups/last_wan_ip.txt"
LAST_IP=$(cat "$CACHE_FILE" 2>/dev/null || true)
if [ "$WAN_IP" = "$LAST_IP" ]; then
echo "[$(date '+%Y-%m-%d %H:%M:%S')] OK: 公网 IP 未变化 ($WAN_IP)"
exit 0
fi
echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: 检测到公网 IP 更新 ($LAST_IP -> $WAN_IP),正在同步至 Cloudflare..."
for NAME in "home.961504.xyz" "*.home.961504.xyz"; do
REC_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?type=A&name=$NAME" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" | /opt/homebrew/bin/jq -r '.result[0].id // empty')
if [ -n "$REC_ID" ]; then
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$REC_ID" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$NAME\",\"content\":\"$WAN_IP\",\"ttl\":60,\"proxied\":false}" >/dev/null
else
curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$NAME\",\"content\":\"$WAN_IP\",\"ttl\":60,\"proxied\":false}" >/dev/null
fi
done
echo "$WAN_IP" > "$CACHE_FILE"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: 已将 home.961504.xyz 与 *.home.961504.xyz 更新为 $WAN_IP"