-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathcloudflare_ddns
executable file
·181 lines (148 loc) · 4.07 KB
/
cloudflare_ddns
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
169
170
171
172
173
174
175
176
177
178
179
180
181
#!/bin/sh
_DEBUG="off"
DEBUG_LOGFILE=$0.debug
debug()
{
if [ "$_DEBUG" == "on" ]; then
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
echo "$timestamp $1"
fi
} >> $DEBUG_LOGFILE
debug "Executed as: $0 $@"
CONFIG=$(dirname $0)/.cloudflare
if [ -r $CONFIG ]; then
. $CONFIG
else
( >&2 echo "Missing or unreadable $CONFIG" )
debug "Missing or unreadable $CONFIG"
fi
# *** USER SETTINGS ***
THROTTLE_SECONDS=5 # Limits calls to Cloudflare to minimize abuse
LOGFILE=$0.log
LOGFILE_LIMIT_IN_BYTES=$((200*1024)) # default is 200kb
# *** OTHER SETTINGS ***
CMD_ERROR_TEMPFILE=$(dirname $0)/.$(basename $0).command.stderr.tmp
LOGFILE_TEMPFILE=$(dirname $0)/.$(basename $0).tmp
FIRMWARE_NOTIFY_CMD=/sbin/ddns_custom_updated
FIRMWARE_UPDATE_SUCCESS=1
FIRMWARE_UPDATE_FAILURE=0
CLOUDFLARE_AUTH_HEADERS="X-Auth-Email: $CLOUDFLARE_EMAIL
X-Auth-Key: $CLOUDFLARE_API_KEY"
# cloudflare prefers token-based auth, so use that if available
if [ -n $CLOUDFLARE_API_TOKEN ]; then
CLOUDFLARE_AUTH_HEADERS="Authorization: Bearer $CLOUDFLARE_API_TOKEN"
fi
# ensure temp files are deleted even if unexpected exit
trap "rm -f $LOGFILE_TEMPFILE $CMD_ERROR_TEMPFILE" EXIT
# user input IP address
NEW_IP=$1
debug "Completed settings"
log_output()
{
timestamp=$(date +"%Y-%m-%d %H:%M:%S")
echo "$timestamp $1 $2"
} >> $LOGFILE
prune_log()
{
debug "prune_log"
tail -c$LOGFILE_LIMIT_IN_BYTES $LOGFILE > $LOGFILE_TEMPFILE
cat $LOGFILE_TEMPFILE > $LOGFILE
}
list_dns_records()
{
debug "list_dns_records"
curl --silent --show-error --request GET "https://api.cloudflare.com/client/v4/zones/$DNS_ZONE_ID/dns_records" \
-H @- <<- HEADERS
$CLOUDFLARE_AUTH_HEADERS
HEADERS
}
list_dns_records_onsuccess()
{
debug "list_dns_records_onsuccess"
log_output LIST_SUCCESS "$1"
}
list_dns_records_onfailure()
{
debug "list_dns_records_onfailure"
log_output LIST_FAILED "$1"
}
list_dns_records_onthrottled()
{
debug "list_dns_records_onthrottled"
log_output LIST_THROTTLED
}
update_record()
{
debug "update_record"
curl --silent --show-error --request PUT "https://api.cloudflare.com/client/v4/zones/$DNS_ZONE_ID/dns_records/$DNS_RECORD_ID" \
--data "{\"type\":\"$DNS_RECORD_TYPE\",\"name\":\"$DNS_RECORD_NAME\",\"content\":\"$NEW_IP\",\"ttl\":1,\"proxied\":$DNS_RECORD_PROXIED}" \
-H @- <<- HEADERS
$CLOUDFLARE_AUTH_HEADERS
Content-Type: application/json
HEADERS
}
update_record_onsuccess()
{
debug "update_record_onsuccess"
$FIRMWARE_NOTIFY_CMD $FIRMWARE_UPDATE_SUCCESS
log_output UPDATE_SUCCESS "$1"
}
update_record_onfailure()
{
debug "update_record_onfailure"
$FIRMWARE_NOTIFY_CMD $FIRMWARE_UPDATE_FAILURE
log_output UPDATE_FAILED "$1"
}
update_record_onthrottled()
{
debug "update_record_onthrottled"
$FIRMWARE_NOTIFY_CMD $FIRMWARE_UPDATE_FAILURE
log_output UPDATE_THROTTLED
}
throttle()
{
debug "throttle"
# if we can't read the log file, assume it's a first run
if [ ! -r $LOGFILE ]; then
return
fi
last_run_time=$(date -d "$(sort -r $LOGFILE | \
grep '^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] [0-9][0-9]:[0-9][0-9]' | \
grep -vm1 THROTTLED | cut -f 1)" +%s)
current_time=$(date +%s)
if [ $(expr $last_run_time + $THROTTLE_SECONDS) -gt $current_time ]; then
$throttled
exit 1
fi
}
debug "Completed function definitions"
command=update_record
success=update_record_onsuccess
failure=update_record_onfailure
throttled=update_record_onthrottled
# if argument is the word 'list', query for a listing of all zone records
if [ "$NEW_IP" = "list" ]; then
command=list_dns_records
success=list_dns_records_onsuccess
failure=list_dns_records_onfailure
throttled=list_dns_records_onthrottled
fi
debug "Completed function assignments"
throttle
debug "Completed throttle"
OUTPUT=$( $command 2> $CMD_ERROR_TEMPFILE )
debug "Completed command execution"
if echo $OUTPUT | grep -q '"success"\s*:\s*true'; then
$success "$OUTPUT"
else
$failure "$(cat <<- LOG_ENTRY_TEMPLATE
===== BEGIN ERROR OUTPUT =====
command stderr: $(cat $CMD_ERROR_TEMPFILE)
Cloudflare response: $OUTPUT
====== END ERROR OUTPUT ======
LOG_ENTRY_TEMPLATE
)"
fi
debug "Completed command result handling"
prune_log
debug "Completed pruning"