|
#!/bin/bash |
|
|
|
# CHANGE THESE |
|
domain="example.domain" # Which domain you want to be synced |
|
auth_email="example.domain.admin@example.domain.com" # The email used to login 'https://dash.cloudflare.com' |
|
auth_key="112233445566778899aabbccddeeff001122a" # Top right corner, "My profile" > "Global API Key" |
|
zone_identifier="ffeeddccbbaa99887766554433221100" # Can be found in the "Overview" tab of your domain |
|
outputif="ppp0" |
|
# Optional |
|
# When domain is proxied by Cloudflare ttl is 1 (set default by Cloudflare) |
|
ttl=1 |
|
proxied=true |
|
|
|
# DO NOT CHANGE LINES BELOW |
|
# SCRIPT START |
|
main() { |
|
echo "[Cloudflare DDNS] Check Initiated" | systemd-cat |
|
|
|
# Let's check connection to the Internet (Google is always online) |
|
while :; do |
|
check_connect=$(ping -q -w1 -c1 google.com &>/dev/null && echo online || echo offline) |
|
if [ "$check_connect" == "online" ]; then |
|
break |
|
else |
|
echo "[Cloudflare DDNS] Waiting for Internet connection" | systemd-cat |
|
sleep 30 |
|
fi |
|
done |
|
|
|
sleep 3 |
|
|
|
# Checking IPv4 on output interface (if IPv4 is not behind a router) |
|
ipv4_local=$(ifconfig $outputif | grep -Po '(?<=inet )[^"]*(?= netmask)') |
|
#ipv4=$(curl -4 -s https://icanhazip.com/) |
|
ipv4=$(curl -4 -s http://plain-text-ip.com/) |
|
#ipv4=$(curl -4 -s https://ip.seeip.org) |
|
#ipv4=$(curl -4 -s https://ident.me/) |
|
#ipv4=$(curl -4 -s https://wtfismyip.com/text) |
|
if [[ $ipv4 != "$ipv4_local" ]]; then |
|
echo "[Cloudflare DDNS] Warning! IPv4 is routed by the ISP" | systemd-cat -p notice |
|
ipv4="noipv4" |
|
fi |
|
|
|
# Checking IPv6 on output interface (if global IPv6 present) |
|
ipv6_local=$(ifconfig $outputif | grep global | grep -Po '(?<=inet6 )[^"]*(?= prefixlen)') |
|
if [ "$ipv6_local" == "" ]; then |
|
echo "[Cloudflare DDNS] Warning! No IPv6 detected on $outputif interface" | systemd-cat -p notice |
|
ipv6="noipv6" |
|
else |
|
#ipv6=$(curl -6 -s https://icanhazip.com/) |
|
ipv6=$(curl -6 -s http://plain-text-ip.com/) |
|
#ipv6=$(curl -6 -s https://ip.seeip.org) |
|
#ipv6=$(curl -6 -s https://ident.me/) |
|
#ipv6=$(curl -6 -s https://wtfismyip.com/text) |
|
fi |
|
|
|
if [ "$ipv4" == "noipv4" ] && [ "$ipv6" == "noipv6" ]; then |
|
echo -e "[Cloudflare DDNS] Cannot update any records (IPv4 or IPv6)" | systemd-cat -p err |
|
exit 1 |
|
fi |
|
|
|
record=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records?name=$domain" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json") |
|
|
|
ver_err=0 |
|
|
|
if [ "$ipv4" != "noipv4" ]; then |
|
insupd_record "4" |
|
else |
|
delete_record "4" |
|
fi |
|
|
|
if [ "$ipv6" != "noipv6" ]; then |
|
insupd_record "6" |
|
else |
|
delete_record "6" |
|
fi |
|
|
|
if [ "$ver_err" -gt 0 ]; then |
|
echo -e "[Cloudflare DDNS] Errors were encountered" | systemd-cat -p err |
|
exit 1 |
|
fi |
|
|
|
echo "[Cloudflare DDNS] Check finished successfully" | systemd-cat |
|
exit 0 |
|
} |
|
|
|
insupd_record() { |
|
local record_type |
|
local ip |
|
if [ "$1" == "4" ]; then |
|
record_type="A" |
|
ip=$ipv4 |
|
else |
|
record_type="AAAA" |
|
ip=$ipv6 |
|
fi |
|
local id_ip |
|
id_ip=$(echo "$record" | jq -j '.result[] | select(.type == "'$record_type'") | .id' | head -1) |
|
if [ "$id_ip" != "" ]; then |
|
# Set existing IP address from the fetched record |
|
local oldip |
|
oldip=$(echo "$record" | jq -j '.result[] | select(.type == "'$record_type'") | .content' | head -1) |
|
# Compare if they're the same |
|
if [ "$ip" == "$oldip" ]; then |
|
echo "[Cloudflare DDNS] IP($oldip) for record $domain has not changed." | systemd-cat -p notice |
|
return 0 |
|
fi |
|
local update |
|
update=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$id_ip" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"id\":\"$zone_identifier\",\"type\":\"$record_type\",\"name\":\"$domain\",\"content\":\"$ip\",\"ttl\":$ttl,\"proxied\":$proxied}") |
|
case "$update" in |
|
*"\"success\":false"*) |
|
echo -e "[Cloudflare DDNS] Update failed for $id_ip. DUMPING RESULTS:\n$update" | systemd-cat -p err |
|
return 1;; |
|
*) |
|
echo -e "[Cloudflare DDNS] IP $ip was updated for $domain" | systemd-cat -p notice |
|
return 0;; |
|
esac |
|
else |
|
local insert |
|
insert=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json" --data "{\"type\":\"$record_type\",\"name\":\"$domain\",\"content\":\"$ip\",\"ttl\":$ttl,\"proxied\":$proxied}") |
|
case "$insert" in |
|
*"\"success\":false"*) |
|
echo -e "[Cloudflare DDNS] Insert failed for $ip. DUMPING RESULTS:\n$insert" | systemd-cat -p err |
|
return 1;; |
|
*) |
|
echo -e "[Cloudflare DDNS] IP $ip was inserted for $domain" | systemd-cat -p notice |
|
return 0;; |
|
esac |
|
fi |
|
} |
|
|
|
delete_record() { |
|
local record_type |
|
local ip |
|
if [ "$1" == "4" ]; then |
|
record_type="A" |
|
ip=$ipv4 |
|
else |
|
record_type="AAAA" |
|
ip=$ipv6 |
|
fi |
|
local id_ip |
|
id_ip=$(echo "$record" | jq -j '.result[] | select(.type == "'$record_type'") | .id' | head -1) |
|
if [ "$id_ip" != "" ]; then |
|
delete=$(curl -s -X DELETE "https://api.cloudflare.com/client/v4/zones/$zone_identifier/dns_records/$id_ip" -H "X-Auth-Email: $auth_email" -H "X-Auth-Key: $auth_key" -H "Content-Type: application/json") |
|
case "$delete" in |
|
*"\"success\":false"*) |
|
echo -e "[Cloudflare DDNS] Delete failed for $id_ip. DUMPING RESULTS:\n$delete" | systemd-cat -p err |
|
return 1;; |
|
*) |
|
echo -e "[Cloudflare DDNS] IP $ip was deleted for $domain" | systemd-cat -p notice |
|
return 0;; |
|
esac |
|
fi |
|
return 0 |
|
} |
|
|
|
main "$@" |