Cập nhật IP cho domain, subdomain quản lý bới cloudflare.com
Cú pháp: cfip [-f] [ip] [domain [@|*|sub[,…]]]
-f : thử cập nhật dù theo ghi chép ip chưa thay đổi
ip : cập nhật theo ip này
sub : thay cho sub.domain
@ : thay cho domain
* : tất cả subdomain, trừ @
Các giá trị mặc định khi chỉ gọi tắt cfip là domain @,\* trong đó domain được trích ra rừ $(hostname) hoặc @,\* nếu có chỉ định domain như cfip domain
Script cài đặt jq nếu chưa có, jq là con dao Thụy Sĩ để xử lý các đối tượng Json.
Script này cũng cập nhật/tạo mới record SPF (nếu tìm được MX record) và PTR cũng như cập nhật /etc/hosts. Tuy nhiên phần này bị cắt đi do chỉ phục vụ cho mail server.
Trước hết script lấy thông tin về tất cả A record của domain và subdomain từ cloudflare.com Sau đó đối chiếu với tham số dòng lệnh để biết domain hay subdomain nào cần tác động. Tạo mới nếu chưa có, cập nhật IP nếu cần hoặc thông báo IP không thay đổi.
Như vậy nếu có tham số -f, script sẽ gọi API của cloudflare ít nhất 1 lần. Với n domain hay subdomain, script sẽ gọi API cloudflare tối đa n+1 lần.
#!/bin/bash
# cfip+.sh v.20210408, Ly Anh Tuan <lnt@ly-le.info>
echo "Cập nhật IP cho cloudflare.com"
( command -v jq &> /dev/null ) || apt install -y jq &> /dev/null
# cloudflare account
AUTH_EMAIL='your_email'
AUTH_KEY='your_auth_key'
ZID='your_zone_id'
#
BU="https://api.cloudflare.com/client/v4/zones/${ZID}/dns_records"
hdr='-H X-Auth-Email:'${AUTH_EMAIL}' -H X-Auth-Key:'${AUTH_KEY}' -H Content-Type:application/json'
SM=/dev/shm/cfIP
[ -d $SM ] || mkdir $SM
[ '-f' == "$1" ] && { rm -rf $SM/*; shift; }
[[ "$1" =~ ([0-9]{1,3}\.)+[0-9]{1,3} ]] && { uIP="$1"; shift; } || uIP=''
set -f
H=$(hostname)
# default: -f domain @,\*
if [ $# -eq 0 ]; then
DM=${H#*.}
PR="@,*"
elif [ $# -eq 1 ]; then
DM="$1"
PR="@,*"
elif [ $# -eq 2 ]; then
DM="$1"
PR="$2"
else
echo "usage : $(basename $0) [-f] [ip] [domain [@|\*|sub[,...]]]"
echo ' -f : luôn cập nhật'
echo ' ip : cập nhật theo ip này'
echo ' sub : thay cho sub.domain'
echo ' @ : thay cho domain'
echo ' * : tất cả subdomain, trừ @'
exit 1
fi
zc="-► không thay đổi!"
[ ! -z "$uIP" ] && IP="$uIP" || IP=$(curl -s -S ifconfig.me/ip)
[ -e "$SM/ip" ] && oIP=$(<$SM/ip) || oIP=''
printf $IP > $SM/ip
[[ "$IP" = "$oIP" ]] && { echo "IP: $zc"; exit 0; }
#
cfr=$(curl -s -S $hdr -G "${BU}?type=A" | jq -r '.result[] | {id,name,content,type}' | jq -s '.')
A=()
[[ "$PR" == *\** ]] && A=( `echo $cfr | jq -r '.[] | select(.type == "A") | .name'` )
A+=( `echo $PR | grep -Po '([^,*]+)' | sed -e "/@/!s/\(.*\)/\1.$DM/g" -e "s/@/$DM/"` )
A=( `printf "%s\n" "${A[@]}" | sort -u` )
#IP
for n in "${A[@]}"; do
echo "+ A: $n"
IFS=$'\t' read id co <<<$(echo "$cfr" | jq '.[] | select(.name == "'$n'")' | jq -s . | jq -r '.[] | [.id, .content] | @tsv')
if [ "$co" == "$IP" ]; then echo " $zc"
else
[ -z "$id" ] && mt='POST' || mt='PATCH'
m=$(curl -s -S $hdr -X $mt "${BU}/$id" -d '{"type":"A", "name":"'$n'", "content":"'$IP'", "ttl":3600, "proxied":false}' | jq -r '.errors[].message')
[ -z "$m" ] && echo " -► $mt: success" || echo " -► $mt: $m"
fi
done