cfip.acc: Cập nhật IP cho tất cả domain/subdomain thuộc một tài khoản cloudflare.com

Cú pháp

 cfip.acc [-f] [ip] [-sub.domain[,sub2 ...]]
   -f : buộc cập nhật
   ip : dùng ip/WAN IP
   -sub.domain: ngoại trừ sub.domain

Người dùng điền thông tin tài khoản cloudflare.com của mình vào trong script

AUTH_EMAIL='...'
AUTH_KEY='...'

Cú pháp cập nhật IP cho tất cả domain/subdomain thuộc tài khoản trên như sau

# cfip.acc

… trừ subdomain sub.example.comsub.domain.org

# cfip.acc -sub.example.com,sub.example.org

… trừ domain example.comtất cả subdomain

# cfip.acc -example.com,*.example.com

hoặc nếu không có gì nhầm lẫn

# cfip.acc -*example.com

Script

#!/bin/bash
# cfip.acc
# Update dynamic IP for all DNS record A on cloudflare
# © 2020 LNT <lnt@ly-le.info>
# version 20220102
#
[ ! command -v jq &> /dev/null ] && sudo apt install -y jq

AUTH_EMAIL=''
AUTH_KEY=''

[[ ! "$AUTH_EMAIL" || ! "$AUTH_KEY" ]] && { echo ">>> Thiếu AUTH_EMAIL/AUTH_KEY! <<<"; exit 1; }
SHM=/dev/shm/cfIP
[ -d $SHM ] || mkdir $SHM
[ '-f' = "$1" ] && { rm -rf $SHM/*; ff=1; shift; } || ff=0
[[ "$1" =~ ([0-9]{1,3}\.)+[0-9]{1,3} ]] && { uIP="$1"; shift; } || uIP=''
[ -z "$uIP" ] && uIP=`dig +short @1.1.1.1 whoami.cloudflare ch txt | sed 's/"//g'`
[ -e "$SHM/ip" ] && oIP=$(<$SHM/ip) || oIP=''
[ "$uIP" == "$oIP" ] && { echo ">>> IP không thay đổi! <<<"; exit 1; } || printf $uIP > $SHM/ip
BASE_URL='https://api.cloudflare.com/client/v4/zones'
if [ $# -eq 0 ]; then
  EXCLUDE='';
elif [ $# -eq 1 ] && [[ "$1" =~ -* ]]; then
  EXCLUDE="$1";
else
  echo
  echo 'Cập nhật IP cho tất cả domain/subdomain cùng tài khoản ở cloudflare.com'
  echo
  echo "Cú pháp: $(basename $0) [-f] [ip] [-sub.domain[,sub2 ...]]"
  echo ' -f : buộc cập nhật'
  echo ' ip : dùng ip/WAN IP'
  echo ' -sub.domain: ngoại trừ sub.domain'
  exit 1
fi
[ "$EXCLUDE" ] && { EXCLUDE=`sed -e 's/,-/,/g' -e 's/^-//' <<< "$EXCLUDE"`;IFS="," read -a EXCLUDE <<< "$EXCLUDE"; }
c='null'
for s in "${EXCLUDE[@]}"; do
  [[ $s == '*'* ]] && p="(.name|endswith(\"${s#*'*'}\"))" || p=".name==\"$s\""
  c="$c or $p"
done
ZONES=`curl -s -X GET "$BASE_URL" \
  -H "Content-Type:application/json" \
  -H "X-Auth-Key:$AUTH_KEY" \
  -H "X-Auth-Email:$AUTH_EMAIL" | jq -r '.result | .[] | with_entries(select(.key == ("id","name"))) | "\(.id)=\(.name)\r"'`
for zone in $ZONES; do
  echo "+ Domain ${zone#*=}"
  zid=${zone%=*}
  
  tmp=$(curl -s -X GET "${BASE_URL}/$zid/dns_records?type=A" \
  -H "X-Auth-Email: ${AUTH_EMAIL}" \
  -H "X-Auth-Key: ${AUTH_KEY}" \
  -H "Content-Type: application/json" | jq -r '.result[] | {id,name,content}' | jq -s .)
  # loại trừ các sub thuộc EXCLUDE
  [ "$c" ] && hosts=$(echo "$tmp" | jq ".[] | del(select($c)) | select(. != null)" | jq -s .) || hosts=$(echo "$tmp" | jq -s ".[]")

  echo "$hosts" | jq -r '.[] | [.id, .name, .content] | @tsv' |
  while IPS=$'\t' read id name cIP; do
    if [[ "$uIP" == "$cIP" ]]; then
      ret='IP không đổi!'
    else
      ret=$(curl -s -X PUT "${BASE_URL}/$zid/dns_records/$id" \
      -H "X-Auth-Email: ${AUTH_EMAIL}" \
      -H "X-Auth-Key: ${AUTH_KEY}" \
      -H "Content-Type: application/json" \
      --data "{\"type\":\"A\",\"name\":\"$name\",\"content\":\"${uIP}\",\"ttl\":3600,\"proxied\":false}" | jq -r '.success')
    fi
    echo "  $name =-> $ret"
  done
done

Leave a Comment

Filed under Software

Comments are closed.