-
Notifications
You must be signed in to change notification settings - Fork 1
/
cf_ddns.sh
169 lines (149 loc) · 4.11 KB
/
cf_ddns.sh
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#!/usr/bin/env bash
# CloudFlare as DDNS
# ARG PARSER
################
# Load Default Config
interval=10
save=''
always_update_dns=false
source ./config.ini > /dev/null 2>&1 || true
while (( "$#" )); do
case "$1" in
-z|--zone)
zone=$2
shift 2
;;
-k|--key)
key=$2
shift 2
;;
-e|--email)
email=$2
shift 2
;;
-c|--config)
config_file=$2
shift 2
;;
-i|--interval)
interval=$2
shift 2
;;
-s|--save)
save=true
shift
;;
--always-update-dns)
always_update_dns=true
shift
;;
-h|--help)
printf "Usage: ./cf_ddns.sh \t[-z|--zone <zone id>
-e|--email <email>
-k|--key <API key>]
[-c|--config <config file to load/store>]
[-s|--save]
[--always-update-dns]
[-i|--interval <update interval in seconds>]
[sub.primary.com] [sub2.primary.com] [sub3.primary.com]
Use --alway-update-dns will match DNS record with the machine IP at every interval. Not recommended for free tier DNS.
Example:
To host current ip at test.example.com
./cf_ddns.sh --key <api key> --zone <zone id> --email <your email> --interval 60 --config config.ini --save test.example.com test2.example.com
"
exit 0
;;
--)
shift
break
;;
*)
name=$*
shift
break
;;
esac
done
if [[ $config_file ]]; then
if [[ $save ]]; then
echo "Saving config...";
echo "zone=$zone;" > $config_file;
echo "key=$key;" >> $config_file;
echo "email=$email;" >> $config_file;
echo "name='$name';" >> $config_file;
echo "interval=$interval;" >> $config_file;
else
. $config_file
fi
fi
printf "[config] Zone:\t$zone
[config] Key:\t************
[config] Email:\t$email
[config] Name:\t$name\n";
# Main Code
###############
endpoint="https://api.cloudflare.com/client/v4/zones/$zone/dns_records";
headers="-H Content-type:application/json -H X-Auth-Key:$key -H X-Auth-Email:$email";
id="null";
last_ip="null";
while [[ true ]]; do
# Update IP
current_ip=$(curl -s http://api.ipify.org||echo 'null')
# Check if offline
if [[ $current_ip = 'null' ]]; then
echo "[$(date)] WARNING: Failed to get your IP.";
sleep $interval
continue
else
echo "[$(date)] INFO: Current IP:$current_ip";
fi
if [[ $always_update_dns = 'false' ]] ; then
# Skip to start if there is no updates in IP
if [[ $current_ip = $last_ip ]]; then
echo "[$(date)] INFO: Host IP Unchanged. Not checking DNS Records.";
sleep $interval;
continue;
else
last_ip=$current_ip;
fi
fi
for cur_name in $name
do
a_name=$(echo $cur_name|cut -d'.' -f1)
# Check if DNS Record Exist
echo "[$(date)] INFO: Checking for existing DNS Record $cur_name.";
content=$(curl -s -X GET $headers $endpoint\?\&name=$cur_name||echo 'null');
id=$(echo $content|jq -r '.result[0].id');
ip_on_record=$(echo $content|jq -r '.result[0].content');
echo "[$(date)] INFO: DNS Record ID:$id";
echo "[$(date)] INFO: IP on DNS Record $ip_on_record";
if [[ $id = 'null' ]] ; then
# Create Record
echo "[$(date)] INFO: Creating New Record"
content=$(curl -s -X POST $headers $endpoint -d "{\"type\":\"A\",\"name\":\"$a_name\",\"content\":\"$current_ip\",\"proxied\":false}");
id=$(echo $content|jq -r '.result.id');
echo "[$(date)] INFO: $content";
echo "[$(date)] INFO: Record ID:$id";
if [[ $(echo $content | jq -r '.success') != 'true' ]]; then
echo "[$(date)] ERROR: Failed with errors $(echo $content | jq -r '.errors')";
continue;
fi
else
if [[ $ip_on_record != $current_ip ]]; then
# Update Existing DNS Record
echo "[$(date)] INFO: Updating Existing Record ID: $id";
content=$(curl -s -X PUT $headers $endpoint/$id -d "{\"type\":\"A\",\"name\":\"$a_name\",\"content\":\"$current_ip\",\"proxied\":false}");
id=$(echo $content|jq -r '.result.id');
echo "[$(date)] INFO: $content";
echo "[$(date)] INFO: Record ID:$id";
if [[ $(echo $content | jq -r '.success') != 'true' ]]; then
echo "[$(date)] ERROR: Failed with errors $(echo $content | jq -r '.errors')";
continue;
fi
else
echo "[$(date)] INFO: Not updating A record because IP on record is same as host ip.";
fi
fi
done
sleep $interval
done