|
#!/bin/bash |
|
|
|
# GET CONFIG PATH |
|
configjson="$( cd "$(dirname "$0")" ; pwd -P )/config.json" |
|
|
|
# GET INTERFACE FROM CONFIG FILE |
|
interface=$(jq -r '.interface' $configjson) |
|
|
|
# GET AUTH VALUES FROM CONFIG FILE |
|
api_tok=$(jq -r '.api_tok' $configjson) |
|
global_key=$(jq -r '.global_key' $configjson) |
|
auth_email=$(jq -r '.auth_email' $configjson) |
|
|
|
# GET IPv4 ADDRESS |
|
ipv4=$(curl -4 -s -m 60 --interface $interface https://wtfismyip.com/text) |
|
|
|
# CHECK IPv4 ADDRESS EXISTS |
|
if [ -z "$ipv4" ]; then |
|
ipv4="noipv4" |
|
echo -e "[Cloudflare DDNS] No IPv4 address found for interface $interface! Please check connection and interface in config.json" | systemd-cat -p notice |
|
fi |
|
|
|
# GET IPv6 ADDRESS |
|
ipv6=$(curl -6 -s -m 60 --interface $interface https://wtfismyip.com/text) |
|
|
|
# CHECK IPv6 ADDRESS EXISTS |
|
if [ -z "$ipv6" ]; then |
|
ipv6="noipv6" |
|
echo -e "[Cloudflare DDNS] No IPv6 address found for interface $interface! Please check connection and interface in config.json" | systemd-cat -p notice |
|
fi |
|
|
|
# IF IPv4 & IPv6 NOT FOUND THEN ASSUME NOT CONNECTED TO INTERNET |
|
if [ "$ipv4" == "noipv4" ] && [ "$ipv6" == "noipv6" ]; then |
|
echo -e "[Cloudflare DDNS] No internet connectivity on interface $interface! Please check connection and interface in config.json" | systemd-cat -p crit |
|
exit 1 |
|
fi |
|
|
|
# MAKE AUTH_HEADERS |
|
if [ -z "$api_tok" ]; then |
|
declare -a auth_headers=('-H' "X-Auth-Email: $auth_email" '-H' "X-Auth-Key: $global_key" '-H' "Content-Type: application/json") |
|
else |
|
declare -a auth_headers=('-H' "Authorization: Bearer $api_tok" '-H' "Content-Type: application/json") |
|
fi |
|
|
|
# GET ALL ZONES FROM API |
|
api_zones=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones" "${auth_headers[@]}") |
|
|
|
# CHECK NO ERROR WITH AUTH_HEADERS |
|
if [[ $api_zones = *"\"code\":6003"* ]]; then |
|
echo -e "[Cloudflare DDNS] Unknown Api Token, Global API Key or Email! Check config.json" | systemd-cat -p crit |
|
exit 1 |
|
fi |
|
|
|
# GET ALL ZONES FROM CONFIG FILE |
|
declare -a config_zones=($(jq -r '.zones[] | .zone' $configjson)) |
|
|
|
# CHECK CONFIG ZONES LOADED |
|
lenz=${#config_zones[@]} |
|
if [ "$lenz" == 0 ]; then |
|
echo -e "[Cloudflare DDNS] No Zones in config file! Check config.json" | systemd-cat -p crit |
|
exit 1 |
|
fi |
|
|
|
# LOOP OVER CONFIG ZONES |
|
for (( z=0; z < $lenz; z++ )) |
|
do |
|
# CHECK CONFIG ZONE EXISTS ON CLOUDFLARE |
|
config_zone_name=${config_zones[$z]} |
|
api_zone_id=$(echo $api_zones | jq -r --arg zone $config_zone_name '.result[] | select(.name==$zone) | "\(.id)"') |
|
if [ "$api_zone_id" == "" ]; then |
|
echo -e "[Cloudflare DDNS] Zone $config_zone_name invalid! Check spelling in config.json or that it exists on your Cloudflare account" | systemd-cat -p crit |
|
continue |
|
fi |
|
|
|
# GET ALL RECORDS FOR CONFIG ZONE |
|
declare -a config_records=($(jq -r --arg zone $config_zone_name '.zones[] | select(.zone==$zone) | .records[] | .record + " " + .type' $configjson)) |
|
|
|
# CHECK CONFIG RECORDS LOADED |
|
lenr=${#config_records[@]} |
|
if [ "$lenr" == 0 ]; then |
|
echo -e "[Cloudflare DDNS] No records in config file for ${config_zones[$z]}! Check config.json" | systemd-cat -p crit |
|
continue |
|
fi |
|
|
|
# GET ALL API RECORDS FOR CONFIG ZONE |
|
api_records=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$api_zone_id/dns_records" "${auth_headers[@]}") |
|
|
|
# LOOP OVER CONFIG RECORDS |
|
for (( r=0; r < $lenr; r++ )) |
|
do |
|
# CHECK IF CONFIG RECORD IS ROOT OR SUBDOMAIN |
|
if [ "${config_records[$r]}" == "@" ]; then |
|
config_record_name=$config_zone_name |
|
else |
|
config_record_name="${config_records[$r]}.$config_zone_name" |
|
fi |
|
r=$(( $r + 1 )) |
|
type=${config_records[$r]} |
|
|
|
# SET CURRENT RECORD TYPE TO CHECK |
|
if [ "$type" == "A" ]; then |
|
# FOR A RECORDS, CHECK IPv4 AVAILABLE |
|
if [ "$ipv4" == "noipv4" ]; then |
|
echo "[Cloudflare DDNS] Warning! No IPv4 detected. Cannot update A (IPv4) record for $config_record_name" | systemd-cat -p crit |
|
continue |
|
fi |
|
ip=$ipv4 |
|
elif [ "$type" == "AAAA" ]; then |
|
# FOR AAAA RECORDS, CHECK IPv6 AVAILABLE |
|
if [ "$ipv6" == "noipv6" ]; then |
|
echo "[Cloudflare DDNS] Warning! No IPv6 detected. Cannot update AAAA (IPv6) record for $config_record_name" | systemd-cat -p crit |
|
continue |
|
fi |
|
ip=$ipv6 |
|
else |
|
echo "[Cloudflare DDNS] Warning! Record type \"$type\" not valid. Check config.json" | systemd-cat -p crit |
|
continue |
|
fi |
|
|
|
# CHECK CONFIG RECORD EXISTS ON CLOUDFLARE |
|
api_record_id=$(echo "$api_records" | jq -r --arg record $config_record_name --arg type $type '.result[] | select(.name==$record and .type==$type) | "\(.id)"') |
|
if [ "$api_record_id" == "" ]; then |
|
echo -e "[Cloudflare DDNS] Record $config_record_name invalid! Check spelling in config.json or that it exists on your Cloudflare account" | systemd-cat -p crit |
|
continue |
|
fi |
|
|
|
# GET API RECORD IP ADDRESS |
|
api_record_ip=$(echo "$api_records" | jq -r --arg id $api_record_id '.result[] | select(.id==$id) | "\(.content)"') |
|
|
|
# CHECK IF API RECORD IP IS DIFFERENT TO CURRENT IP |
|
if [ "$ip" == "$api_record_ip" ]; then |
|
echo "[Cloudflare DDNS] IP ($ip) for record $config_record_name has not changed." | systemd-cat -p notice |
|
continue |
|
else |
|
proxied=$(echo "$api_records" | jq -r --arg id $api_record_id '.result[] | select(.id==$id) | "\(.proxied)"') |
|
ipupdate=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$api_zone_id/dns_records/$api_record_id" "${auth_headers[@]}" --data "{\"type\":\"$type\",\"name\":\"$config_record_name\",\"content\":\"$ip\",\"proxied\":$proxied}") |
|
fi |
|
|
|
# CHECK STATUS OF UPDATE |
|
case "$ipupdate" in |
|
*"\"success\":false"*) |
|
echo -e "[Cloudflare DDNS] Update failed for $config_record_name. DUMPING RESULTS:\n$ipupdate" | systemd-cat -p err;; |
|
*) |
|
echo "[Cloudflare DDNS] $type record for $config_record_name synced to $ip" | systemd-cat -p notice;; |
|
esac |
|
done |
|
done |
NOPE!
Just tried out. Now it's reversed! If I use this,
{\"id\":\"$zone_id\",\"type\":\"$record_type\",\"name\":\"$record_name\",\"content\":\"$cur_ip\",\"proxied\":$proxied_value}
then proxied value gets placed as the variable value. But if I use this,
{\"id\":\"$zone_id\",\"type\":\"$record_type\",\"name\":\"$record_name\",\"content\":\"$cur_ip\"}
then proxied value gets placed as DNS only. Previously Cloudflare sets it to Proxied.