update_cloudflare_com_v1.sh 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #
  2. #.Distributed under the terms of the GNU General Public License (GPL) version 2.0
  3. #
  4. # script for sending updates to cloudflare.com
  5. #.2014-2017 Christian Schoenebeck <christian dot schoenebeck at gmail dot com>
  6. # many thanks to Paul for testing and feedback during development
  7. #
  8. # This script is parsed by dynamic_dns_functions.sh inside send_update() function
  9. #
  10. # using following options from /etc/config/ddns
  11. # option username - your cloudflare e-mail
  12. # option password - cloudflare api key, you can get it from cloudflare.com/my-account/
  13. # option domain - your full hostname to update, in cloudflare its subdomain.domain
  14. # i.e. myhost.example.com where myhost is the subdomain and example.com is your domain
  15. #
  16. # variable __IP already defined with the ip-address to use for update
  17. #
  18. [ $use_https -eq 0 ] && write_log 14 "Cloudflare only support updates via Secure HTTP (HTTPS). Please correct configuration!"
  19. [ -z "$username" ] && write_log 14 "Service section not configured correctly! Missing 'username'"
  20. [ -z "$password" ] && write_log 14 "Service section not configured correctly! Missing 'password'"
  21. local __RECID __URL __KEY __KEYS __FOUND __SUBDOM __DOMAIN __FQDN
  22. # split __SUBDOM __DOMAIN from $domain
  23. # given data:
  24. # @example.com for "domain record"
  25. # host.sub@example.com for a "host record"
  26. __SUBDOM=$(printf %s "$domain" | cut -d@ -f1)
  27. __DOMAIN=$(printf %s "$domain" | cut -d@ -f2)
  28. # Cloudflare v1 needs:
  29. # __DOMAIN = the base domain i.e. example.com
  30. # __SUBDOM = the host.sub to change if a "host record" or blank if domain record
  31. # __FQDN = the FQDN to detect record_id to change
  32. # i.e. example.com for the "domain record" or host.sub.example.com for "host record"
  33. if [ -z "$__SUBDOM" -o "$__SUBDOM" = "$__DOMAIN" ]; then
  34. __SUBDOM=""
  35. __FQDN="$__DOMAIN"
  36. else
  37. __FQDN="${__SUBDOM}.${__DOMAIN}"
  38. fi
  39. # parse OpenWrt script with
  40. # functions for parsing and generating json
  41. . /usr/share/libubox/jshn.sh
  42. # function copied from /usr/share/libubox/jshn.sh
  43. # from BB14.09 for backward compatibility to AA12.09
  44. type "json_get_keys" >/dev/null 2>&1 || json_get_keys() {
  45. local __dest="$1"
  46. local _tbl_cur
  47. if [ -n "$2" ]; then
  48. json_get_var _tbl_cur "$2"
  49. else
  50. _json_get_var _tbl_cur JSON_CUR
  51. fi
  52. local __var="${JSON_PREFIX}KEYS_${_tbl_cur}"
  53. eval "export -- \"$__dest=\${$__var}\"; [ -n \"\${$__var+x}\" ]"
  54. }
  55. # function to "sed" unwanted string parts from DATFILE
  56. cleanup() {
  57. # based on the sample output on cloudflare.com homepage we need to do some cleanup
  58. sed -i 's/^[ \t]*//;s/[ \t]*$//' $DATFILE # remove invisible chars at beginning and end of lines
  59. sed -i '/^-$/d' $DATFILE # remove lines with "-" (dash)
  60. sed -i '/^$/d' $DATFILE # remove empty lines
  61. sed -i "#'##g" $DATFILE # remove "'" (single quote)
  62. }
  63. [ -n "$rec_id" ] && __RECID="$rec_id" || {
  64. # build url according to cloudflare client api at https://www.cloudflare.com/docs/client-api.html
  65. # to "rec_load_all" to detect rec_id needed for update
  66. __URL="https://www.cloudflare.com/api_json.html" # https://www.cloudflare.com/api_json.html
  67. __URL="${__URL}?a=rec_load_all" # -d 'a=rec_load_all'
  68. __URL="${__URL}&tkn=$password" # -d 'tkn=8afbe6dea02407989af4dd4c97bb6e25'
  69. __URL="${__URL}&email=$username" # -d 'email=sample@example.com'
  70. __URL="${__URL}&z=$__DOMAIN" # -d 'z=example.com'
  71. # lets request the data
  72. do_transfer "$__URL" || return 1
  73. cleanup # cleanup dat file
  74. json_load "$(cat $DATFILE)" # lets extract data
  75. __FOUND=0 # found record indicator
  76. json_get_var __RES "result" # cloudflare result of last request
  77. json_get_var __MSG "msg" # cloudflare error message
  78. [ "$__RES" != "success" ] && {
  79. write_log 4 "'rec_load_all' failed with error: \n$__MSG"
  80. return 1
  81. }
  82. json_select "response"
  83. json_select "recs"
  84. json_select "objs"
  85. json_get_keys __KEYS
  86. for __KEY in $__KEYS; do
  87. local __ZONE __DISPLAY __NAME __TYPE
  88. json_select "$__KEY"
  89. # json_get_var __ZONE "zone_name" # for debugging
  90. # json_get_var __DISPLAY "display_name" # for debugging
  91. json_get_var __NAME "name"
  92. json_get_var __TYPE "type"
  93. if [ "$__NAME" = "$__FQDN" ]; then
  94. # we must verify IPv4 and IPv6 because there might be both for the same host
  95. [ \( $use_ipv6 -eq 0 -a "$__TYPE" = "A" \) -o \( $use_ipv6 -eq 1 -a "$__TYPE" = "AAAA" \) ] && {
  96. __FOUND=1 # mark found
  97. break # found leave for loop
  98. }
  99. fi
  100. json_select ..
  101. done
  102. [ $__FOUND -eq 0 ] && {
  103. # we don't need to continue trying to update cloudflare because record to update does not exist
  104. # user has to setup record first outside ddns-scripts
  105. write_log 14 "No valid record found at Cloudflare setup. Please create first!"
  106. }
  107. json_get_var __RECID "rec_id" # last thing to do get rec_id
  108. json_cleanup # cleanup
  109. write_log 7 "rec_id '$__RECID' detected for host/domain '$__FQDN'"
  110. }
  111. # build url according to cloudflare client api at https://www.cloudflare.com/docs/client-api.html
  112. # for "rec_edit" to update IP address
  113. __URL="https://www.cloudflare.com/api_json.html" # https://www.cloudflare.com/api_json.html
  114. __URL="${__URL}?a=rec_edit" # -d 'a=rec_edit'
  115. __URL="${__URL}&tkn=$password" # -d 'tkn=8afbe6dea02407989af4dd4c97bb6e25'
  116. __URL="${__URL}&id=$__RECID" # -d 'id=9001'
  117. __URL="${__URL}&email=$username" # -d 'email=sample@example.com'
  118. __URL="${__URL}&z=$__DOMAIN" # -d 'z=example.com'
  119. [ $use_ipv6 -eq 0 ] && __URL="${__URL}&type=A" # -d 'type=A' (IPv4)
  120. [ $use_ipv6 -eq 1 ] && __URL="${__URL}&type=AAAA" # -d 'type=AAAA' (IPv6)
  121. # handle subdomain or domain record
  122. [ -n "$__SUBDOM" ] && __URL="${__URL}&name=$__SUBDOM" # -d 'name=sub' (HOST/SUBDOMAIN)
  123. [ -z "$__SUBDOM" ] && __URL="${__URL}&name=$__DOMAIN" # -d 'name=example.com'(DOMAIN)
  124. __URL="${__URL}&content=$__IP" # -d 'content=1.2.3.4'
  125. __URL="${__URL}&service_mode=0" # -d 'service_mode=0'
  126. __URL="${__URL}&ttl=1" # -d 'ttl=1'
  127. # lets do the update
  128. do_transfer "$__URL" || return 1
  129. cleanup # cleanup tmp file
  130. json_load "$(cat $DATFILE)" # lets extract data
  131. json_get_var __RES "result" # cloudflare result of last request
  132. json_get_var __MSG "msg" # cloudflare error message
  133. [ "$__RES" != "success" ] && {
  134. write_log 4 "'rec_edit' failed with error:\n$__MSG"
  135. return 1
  136. }
  137. write_log 7 "Update of rec_id '$__RECID' successful"
  138. return 0