#!/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"