DNS_Tools/Dynamic_DNS/Dynamic_DNS_Cloudflare/update_cloudflare_ip.sh

143 lines
4.0 KiB
Bash

#!/bin/bash
set -euo pipefail
# --- Configuration ---
: "${ENV_DIR:="./zones"}"
: "${LOG_DIR:="./logs"}"
DATE=$(date +%F)
LOG_FILE="$LOG_DIR/update_${DATE}.log"
# --- Ensure log directory exists ---
mkdir -p "$LOG_DIR"
# --- Logging function ---
log() {
local message="$1"
echo "$message" | tee -a "$LOG_FILE"
}
# --- Check required tools ---
for cmd in curl jq; do
if ! command -v "$cmd" >/dev/null 2>&1; then
echo "[!] Required tool '$cmd' not found. Please install it." >&2
exit 1
fi
done
# --- Fetch current IP from Mullvad ---
log "[*] Fetching IP from Mullvad..."
IP_INFO=$(curl -sf https://ipv4.am.i.mullvad.net/json)
if ! echo "$IP_INFO" | jq -e '.ip' >/dev/null; then
log "[!] Invalid Mullvad response or missing IP."
log "$IP_INFO"
exit 1
fi
CURRENT_IP=$(echo "$IP_INFO" | jq -r '.ip')
log "[*] Current public IP is: $CURRENT_IP"
log ""
# --- Get list of .env files ---
shopt -s nullglob
ENV_FILES=("$ENV_DIR"/*.env)
if [[ ${#ENV_FILES[@]} -eq 0 ]]; then
log "[!] No .env files found in $ENV_DIR"
exit 0
fi
# --- Process each env file ---
for ENV_FILE in "${ENV_FILES[@]}"; do
log "[*] Processing config: $ENV_FILE"
# Load environment variables
set -a
source "$ENV_FILE"
set +a
# Validate required vars
missing_vars=()
[[ -z "${ZONE_ID:-}" ]] && missing_vars+=("ZONE_ID")
[[ -z "${DNS_NAME:-}" ]] && missing_vars+=("DNS_NAME")
[[ -z "${CLOUDFLARE_EMAIL:-}" ]] && missing_vars+=("CLOUDFLARE_EMAIL")
[[ -z "${CLOUDFLARE_API_KEY:-}" ]] && missing_vars+=("CLOUDFLARE_API_KEY")
if (( ${#missing_vars[@]} )); then
log "[!] Missing variables in $ENV_FILE: ${missing_vars[*]}"
log ""
continue
fi
# --- Fetch DNS records for the zone ---
log "[*] Checking DNS record for $DNS_NAME..."
DNS_LOOKUP=$(curl -sf -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?type=A&name=$DNS_NAME" \
-H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
-H "X-Auth-Key: $CLOUDFLARE_API_KEY" \
-H "Content-Type: application/json")
RECORD_ID=$(echo "$DNS_LOOKUP" | jq -r '.result[0].id // empty')
EXISTING_IP=$(echo "$DNS_LOOKUP" | jq -r '.result[0].content // empty')
if [[ -z "$RECORD_ID" ]]; then
log "[!] No existing record found. Creating new A record for $DNS_NAME..."
CREATE_RESPONSE=$(curl -sf -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
-H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
-H "X-Auth-Key: $CLOUDFLARE_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"type\": \"A\",
\"name\": \"$DNS_NAME\",
\"content\": \"$CURRENT_IP\",
\"ttl\": 3600,
\"proxied\": true,
\"comment\": \"Created via script\"
}")
if [[ $(echo "$CREATE_RESPONSE" | jq -r '.success') == "true" ]]; then
log "[+] Successfully created DNS record for $DNS_NAME$CURRENT_IP"
else
log "[!] Failed to create DNS record for $DNS_NAME"
echo "$CREATE_RESPONSE" | tee -a "$LOG_FILE"
fi
log ""
continue
fi
# --- If record exists, check if update is needed ---
if [[ "$EXISTING_IP" == "$CURRENT_IP" ]]; then
log "[=] No update needed. $DNS_NAME already points to $CURRENT_IP"
log ""
continue
fi
# --- Patch the existing record ---
log "[*] IP has changed: $EXISTING_IP$CURRENT_IP"
log "[*] Updating existing DNS record via PATCH..."
UPDATE_RESPONSE=$(curl -sf -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
-H "X-Auth-Email: $CLOUDFLARE_EMAIL" \
-H "X-Auth-Key: $CLOUDFLARE_API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"type\": \"A\",
\"name\": \"$DNS_NAME\",
\"content\": \"$CURRENT_IP\",
\"ttl\": 3600,
\"proxied\": true,
\"comment\": \"Updated via script\"
}")
if [[ $(echo "$UPDATE_RESPONSE" | jq -r '.success') == "true" ]]; then
log "[+] Successfully updated $DNS_NAME to $CURRENT_IP"
else
log "[!] Failed to update $DNS_NAME"
echo "$UPDATE_RESPONSE" | tee -a "$LOG_FILE"
fi
log ""
done