Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ sudo mv update-cloudflare-dns.conf /usr/local/bin/update-cloudflare-dns.conf

| **Option** | **Example** | **Description** |
| ------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------- |
| what_ip | internal | Which IP should be used for the record: internal/external |
| dns_record | ddns.example.com | DNS **A** record which will be updated, you can pass multiple **A** records separated by comma |
| what_ip | internal | Which IP should be used for the record: internal/external/globalv6 |
| dns_record | ddns.example.com | DNS record which will be updated, you can pass multiple records of the same type separated by commas |
| dns_record_type | A | Record type to update, set to AAAA for IPv6 |
| cloudflare_zone_api_token | ChangeMe | Cloudflare API Token **KEEP IT PRIVATE!!!!** |
| zoneid | ChangeMe | Cloudflare's [Zone ID](https://developers.cloudflare.com/fundamentals/get-started/basic-tasks/find-account-and-zone-ids/) |
| proxied | false | Use Cloudflare proxy on dns record true/false |
Expand Down Expand Up @@ -159,7 +160,7 @@ Example:

## Limitations

- Does not support IPv6
- IPv6 address selection always picks the first IPv6 global address on the default interface

## License

Expand Down
6 changes: 4 additions & 2 deletions update-cloudflare-dns.conf
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
##### Config

## Which IP should be used for the record: internal/external
## Which IP should be used for the record: internal/external/globalv6
## Internal interface will be chosen automaticly as a primary default interface
what_ip="internal"
## DNS A record to be updated, you can separate multiple records by comma
## DNS record to be updated, you can separate multiple records by comma
dns_record="ddns.example.com,ddns2.example.com"
## DNS record type to update, set to AAAA when using IPv6
dns_record_type=A
## Cloudflare's Zone ID, you can find this on the landing/overview page of your domain.
zoneid="ChangeMe"
## Cloudflare Zone API Token
Expand Down
34 changes: 26 additions & 8 deletions update-cloudflare-dns.sh
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ else
fi
fi

dns_record_type=${dns_record_type:="A"}

### Check validity of "ttl" parameter
if [ "${ttl}" -lt 120 ] || [ "${ttl}" -gt 7200 ] && [ "${ttl}" -ne 1 ]; then
echo "Error! ttl out of range (120-7200) or not set to 1"
Expand All @@ -40,8 +42,8 @@ if [ "${proxied}" != "false" ] && [ "${proxied}" != "true" ]; then
fi

### Check validity of "what_ip" parameter
if [ "${what_ip}" != "external" ] && [ "${what_ip}" != "internal" ]; then
echo 'Error! Incorrect "what_ip" parameter, choose "external" or "internal"'
if [ "${what_ip}" != "external" ] && [ "${what_ip}" != "internal" ] && [ "${what_ip}" != "globalv6" ]; then
echo 'Error! Incorrect "what_ip" parameter, choose "external", "globalv6", or "internal"'
exit 0
fi

Expand Down Expand Up @@ -88,6 +90,22 @@ if [ "${what_ip}" == "internal" ]; then
echo "==> Internal ${interface} IP is: $ip"
fi

if [ "${what_ip}" == "globalv6" ]; then
if which ip >/dev/null; then
### "ip route get" (linux)
interface=$(ip -6 route get 2606:4700:4700::1111 | awk '/dev/ {print $7}')
ip=$(ip -o -6 addr show eth0 scope global | awk '{print $4}' | grep -v "^fd" | cut -d/ -f 1 | head -n 1)
else
interface=$(route -n get -inet6 2606:4700:4700::1111 | awk '/interface:/ {print $2}')
ip=$(ifconfig ${interface} inet6 | grep inet6 | grep -v deprecated | awk '{print $2}' | grep -v "^fd" | grep -v "^fe80::" | head -n 1)
fi
if [ -z "$ip" ]; then
echo "Error! Can't read ip from ${interface}"
exit 0
fi
echo "==> Global IPv6 IP for ${interface} is: $ip"
fi

### Build coma separated array fron dns_record parameter to update multiple A records
IFS=',' read -d '' -ra dns_records <<<"$dns_record,"
unset 'dns_records[${#dns_records[@]}-1]'
Expand All @@ -98,10 +116,10 @@ for record in "${dns_records[@]}"; do
if [ "${proxied}" == "false" ]; then
### Check if "nslookup" command is present
if which nslookup >/dev/null; then
dns_record_ip=$(nslookup ${record} 1.1.1.1 | awk '/Address/ { print $2 }' | sed -n '2p')
dns_record_ip=$(nslookup -query=${dns_record_type} ${record} 1.1.1.1 | awk '/Address/ { print $2 }' | sed -n '2p')
else
### if no "nslookup" command use "host" command
dns_record_ip=$(host -t A ${record} 1.1.1.1 | awk '/has address/ { print $4 }' | sed -n '1p')
dns_record_ip=$(host -t ${dns_record_type} ${record} 1.1.1.1 | awk '/has address/ { print $4 }' | sed -n '1p')
fi

if [ -z "$dns_record_ip" ]; then
Expand All @@ -113,7 +131,7 @@ for record in "${dns_records[@]}"; do

### Get the dns record id and current proxy status from Cloudflare API when proxied is "true"
if [ "${proxied}" == "true" ]; then
dns_record_info=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records?type=A&name=$record" \
dns_record_info=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records?type=${dns_record_type}&name=$record" \
-H "Authorization: Bearer $cloudflare_zone_api_token" \
-H "Content-Type: application/json")
if [[ ${dns_record_info} == *"\"success\":false"* ]]; then
Expand All @@ -134,7 +152,7 @@ for record in "${dns_records[@]}"; do
echo "==> DNS record of ${record} is: ${dns_record_ip}. Trying to update..."

### Get the dns record information from Cloudflare API
cloudflare_record_info=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records?type=A&name=$record" \
cloudflare_record_info=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records?type=${dns_record_type}&name=$record" \
-H "Authorization: Bearer $cloudflare_zone_api_token" \
-H "Content-Type: application/json")
if [[ ${cloudflare_record_info} == *"\"success\":false"* ]]; then
Expand All @@ -150,7 +168,7 @@ for record in "${dns_records[@]}"; do
update_dns_record=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zoneid/dns_records/$cloudflare_dns_record_id" \
-H "Authorization: Bearer $cloudflare_zone_api_token" \
-H "Content-Type: application/json" \
--data "{\"type\":\"A\",\"name\":\"$record\",\"content\":\"$ip\",\"ttl\":$ttl,\"proxied\":$proxied}")
--data "{\"type\":\"${dns_record_type}\",\"name\":\"$record\",\"content\":\"$ip\",\"ttl\":$ttl,\"proxied\":$proxied}")
if [[ ${update_dns_record} == *"\"success\":false"* ]]; then
echo ${update_dns_record}
echo "Error! Update failed"
Expand All @@ -167,7 +185,7 @@ for record in "${dns_records[@]}"; do

if [ ${notify_me_telegram} == "yes" ]; then
telegram_notification=$(
curl -s -X GET "https://api.telegram.org/bot${telegram_bot_API_Token}/sendMessage?chat_id=${telegram_chat_id}" --data-urlencode "text=${record} DNS record updated to: ${ip}"
curl -s -X GET "https://api.telegram.org/bot${telegram_bot_API_Token}/sendMessage?chat_id=${telegram_chat_id}" --data-urlencode "text=${record} ${dns_record_type} DNS record updated to: ${ip}"
)
if [[ ${telegram_notification=} == *"\"ok\":false"* ]]; then
echo ${telegram_notification=}
Expand Down