Skip to content

DDNS.sh

Published: at 01:09 PM

Self use only!

#!/bin/bash

# define your own variables here
API_TOKEN="cloudflare-api-token" # replace with your own Cloudflare API Token
ZONE_ID="cloudflare-zone-id"     # replace with your own Cloudflare Zone ID
DNS_NAME="yourdomain"            # replace with your own domain name you want to update

die() {
  echo $1
  exit 1
}

date

# check if jq is installed
if ! command -v jq &> /dev/null; then
  die "jq is not installed"
fi
# check if curl is installed
if ! command -v curl &> /dev/null; then
  die "curl is not installed"
fi

# login to the modem
COOKIE=$(curl --request POST \
  --url http://192.168.1.1/cgi-bin/luci \
  --header 'content-type: application/x-www-form-urlencoded' \
  --header 'user-agent: vscode-restclient' \
  --data username=useradmin \
  --data psd=123321 \
  -i -s | grep -i 'Set-Cookie')

# parse cookie
COOKIE=${COOKIE#*Set-Cookie: }

# check if cookie is empty
[ -z "$COOKIE" ] && die "Failed to get cookie"

# get gateway info from modem
gwinfo=$(curl --request GET \
  --url 'http://192.168.1.1/cgi-bin/luci/admin/settings/gwinfo?get=part' \
  --header 'content-type: application/json' \
  --header "cookie: $COOKIE" \
  --header 'user-agent: vscode-restclient' \
  --cookie "$COOKIE" -s
)

# check if gwinfo is empty
[ -z "$gwinfo" ] && die "Failed to get gwinfo"

# extract current ip
CURRENT_IP=$(echo $gwinfo | jq -r '.WANIP')

# check if current ip is empty
[ -z "$CURRENT_IP" ] && die "Failed to get IP"

echo " Current IP: $CURRENT_IP"

# query the DNS record ID
RECORD_INFO=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=$DNS_NAME" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json")

# extract the DNS record ID and the existing IP
DNS_RECORD_ID=$(echo "$RECORD_INFO" | jq -r '.result[0].id')
EXISTING_IP=$(echo "$RECORD_INFO" | jq -r '.result[0].content')

# check if DNS record ID is empty
( [ -z "$DNS_RECORD_ID" ] || [ "$DNS_RECORD_ID" == "null" ] ) && die "Failed to get DNS record ID"
echo "Found DNS record ID: $DNS_RECORD_ID, existing IP: $EXISTING_IP"

# check if the current IP is the same as the existing IP
[ "$CURRENT_IP" == "$EXISTING_IP" ] && die "IP has not changed"

# update the DNS record
RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$DNS_RECORD_ID" \
  -H "Authorization: Bearer $API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
      "type": "A",
      "name": "'"$DNS_NAME"'",
      "content": "'"$CURRENT_IP"'",
      "ttl": 60,
      "proxied": false
  }')

# check if the DNS record was updated successfully
if echo "$RESPONSE" | grep -q '"success":true'; then
  echo "DNS record updated successfully: $CURRENT_IP"
else
  die "Failed to update DNS record"
fi

# add a cron job to run this script every 5 minutes
# chmod +x ddns.sh
# crontab -e
# */5 * * * * sh /home/username/ddns.sh > /home/username/ddns.log 2>&1 &