Script này sẽ khiểm tra public IP hiện tại của bạn và update IP domain trên Cloudflare một cách nhanh chóng
cloudflare_dynamic_ip_update.bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
| #!/usr/bin/env bash
## Author: Hyecheol (Jerry) Jang
## Shell Script that check current public (dynamic) ip address of server,
## and update it to the Cloudflare DNS record after comparing ip address registered to Cloudflare
## basic shell scripting guide https://blog.gaerae.com/2015/01/bash-hello-world.html
## Using dig command (https://en.wikipedia.org/wiki/Dig_(command)) to get current public IP address
currentIP=$(dig -4 TXT +short o-o.myaddr.1.google.com @ns1.google.com)
if [ $? == 0 ] && [ ${currentIP} ]; then ## when dig command run without error,
## Making substring, only retrieving ip address of this server
## https://stackabuse.com/substrings-in-bash/
currentIP=$(echo $currentIP | cut -d'"' -f 2)
echo "current public IP address is "$currentIP
else ## error happens,
echo "Check your internet connection, or google DNS server maybe interruptted"
exit
fi
## Use Cloudflare API to retrieve recordIP
## https://api.cloudflare.com/
## Read configuration from separated cloudflare_config file (need to locate in the same directory)
## https://stackoverflow.com/questions/10929453/read-a-file-line-by-line-assigning-the-value-to-a-variable
## https://stackoverflow.com/questions/10586153/split-string-into-an-array-in-bash
SCRIPT_PATH=$(dirname $(realpath $0))
readResult="" ## Store configuration
while IFS= read -r line || [[ -n "$line" ]]; do
readResult+=" " ## Delimiter: space
readResult+="$line"
done < $SCRIPT_PATH"/cloudflare_config" ## use cloudflare_config file
unset IFS
unset SCRIPT_PATH
## After retrieve information from file, cut result string into configuration elements
key=$(echo $(echo $readResult | cut -d' ' -f 1) | cut -d'=' -f 2)
email=$(echo $(echo $readResult | cut -d' ' -f 2) | cut -d'=' -f 2)
zoneID=$(echo $(echo $readResult | cut -d' ' -f 3) | cut -d'=' -f 2)
IFS=',' read -r -a updateTarget <<< "$(echo $(echo $readResult | cut -d' ' -f 4) | cut -d'=' -f 2)"
unset readResult
unset IFS
## Make space for saving record's IP Address, Type, and Name
declare -a recordIP
declare -a recordType
declare -a recordName
declare -a dnsID
declare -a recordProxied
for string in ${updateTarget[@]}; do ## retrieve record's IP Address and save to recordIP
content=$(
curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$zoneID/dns_records?name=${string}" \
-H "X-Auth-Email: $email" \
-H "X-Auth-Key: $key" \
-H "Content-Type: application/json"
)
## Parse JSON https://stackoverflow.com/questions/42427371/cloudflare-api-cut-json-response
## Using jq https://stedolan.github.io/jq/
ip=$(echo $content | jq '.result | map(.content) | add' | cut -d'"' -f 2)
rType=$(echo $content | jq '.result | map(.type) | add' | cut -d'"' -f 2)
name=$(echo $content | jq '.result | map(.name) | add' | cut -d'"' -f 2)
id=$(echo $content | jq '.result | map(.id) | add' | cut -d'"' -f 2)
proxied=$(echo $content | jq '.result | map(.proxied) | add' | cut -d'"' -f 2)
recordIP=(${recordIP[@]} $ip)
recordType=(${recordType[@]} $rType)
recordName=(${recordName[@]} $name)
dnsID=(${dnsID[@]} $id)
recordProxied=(${recordProxied[@]} $proxied)
unset id
unset rType
unset name
unset ip
unset content
unset string
unset proxied
done
unset updateTarget
## Compare currentIP and recordIP
declare -a needUpdate ## Array to store whether each record needs to be updated or not
for string in ${recordIP[@]}; do
if [ ${string} == ${currentIP} ]; then
needUpdate=(${needUpdate[@]} 'False')
else
needUpdate=(${needUpdate[@]} 'True')
fi
unset string
done
unset recordIP ## X Need recordIP Anymore
## Update record if needed
count=0
while [ $count -lt ${#needUpdate[@]} ]; do
if [ ${needUpdate[count]} == 'True' ]; then
echo "record IP needs to be updated for "${recordName[count]}
success=$(
curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$zoneID/dns_records/${dnsID[count]}" \
-H "X-Auth-Email: $email" \
-H "X-Auth-Key: $key" \
-H "Content-Type: application/json" \
--data '{"type":"'"${recordType[count]}"'","name":"'"${recordName[count]}"'","content":"'"$currentIP"'","proxied":'${recordProxied[count]}'}' | \
jq '.success' | cut -d'"' -f 2
)
if [ $success == true ]; then
echo "Success update record IP of "${recordName[count]}
else
echo "Fail to update record IP of "${recordName[count]}"\n""Please Check result!!"
fi
else
echo "record IP does not need to be updated for "${recordName[count]}
fi
count=$((${count}+1))
done
unset count
unset currentIP
unset key
unset email
unset zoneID
unset recordType
unset recordName
unset dnsID
unset recordProxied
unset needUpdate
|
cloudflare_config
1
2
3
4
| Auth-Key=[Global API Key]
Auth-Email=[Login Mail]
Zone-ID=[Zone ID]
Update-Target=subdomain.pnghia.com
|
Credit: Hyecheol (Jerry) Jang