Quantcast
Channel: MikroTik
Viewing all articles
Browse latest Browse all 21293

Scripting • DDNS Cloudflare script

$
0
0
Hello everyone,

I would like to preface by saying that I am not a programmer and I need help solving the following issue. I have written the following script for RouterOS that updates the IP in a given DNS record on Cloudflare when the router's IP changes. I started from the script I had previously written for Gandi's liveDNS. The script works well with "no proxied" records. I wanted to make it work with "proxied" records as well, but obviously, resolving the IP using 1.1.1.1 or any other public DNS returns not the original IP but the IP of the proxy. Therefore, I need to make a query using Cloudflare's APIs and extract the registered IP to compare it with the new one. If they are the same, I do nothing; if it is new, I update the record. This is the script:
Code:
# ------Cloudflare DDNS script licensed under GPL 3 write by Massimo Ciani ----------####--------------- Change Values in this section to match your setup ------------------# Your Clouflare API token variables. Generate in your cloudflare website area:local cfToken "...................................."# work with only one root domain or subdomain.# if you want to manage multiple domain or subdomain clone the script and change based on new domain# policy read, write and test# IMPORTANT: Before to start the script, remember to create manually the records for all domain. I think.# ZoneID is inside the website area in the cloudflare user area:local cfZoneId "................................"##### To obtain cfDnsId use following command in any unix shell:#####     curl -X GET "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/dns_records" -H "X-Auth-Email: YOUR_EMAIL" -H "X-Auth-Key: YOUR_API_KEY" -H "Content-Type: application/json" | python -mjson.tool:local cfDnsId "................................":local domain "sub.example.com":local dnsType "A":local dnsTTL 300:local dnsProxied false:local resolver "1.1.1.1"# Set the name of interface where get the internet public IP:local inetinterface "ether1"#------------------------------------------------------------------------------------# No more changes need# get current IP:global currentIP:if ([/interface get $inetinterface value-name=running]) do={    :global currentIPa [/ip address get [find interface="$inetinterface" disabled=no] address]    # cancel netmask from interface IP address    :for i from=( [:len $currentIPa] - 1) to=0 do={        :if ( [:pick $currentIPa $i] = "/") do={             :set currentIP [:pick $currentIPa 0 $i]       }    }} else={    :log info "Cloudflare: $inetinterface is not currently running, so therefore will not update."    :error [:log info "bye"]}# Resolve domain and update on IP changes. This method work only if use non proxied record.#:global previousIPb [:resolve domain-name="$domain" server="$resolver"]#### find a way to extract ip from the record using the cloudflare API. needed if you want to use proxied record ####:local getApiUrl "https://api.cloudflare.com/client/v4/zones/$cfZoneId/dns_records/$cfDnsId":local authHeader "content-type:application/json,Authorization:Bearer $cfToken":local jsonData [/tool fetch mode=https http-method=get url="$getApiUrl" http-header-field="$authHeader" as-value]#### extract IP from the result query. but don't work:global previousIPb ($jsonData->"result"->"content")#####################################################################################################################:log info "RecordIP is $previousIPb":if ($currentIP != $previousIPb) do={    :log info "Cloudflare $domain: Current IP $currentIP is not equal to previous IP, update needed"    :log info "Cloudflare $domain: Sending update"    # compose endpoint    # docs: https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record    :local apiUrl "https://api.cloudflare.com/client/v4/zones/$cfZoneId/dns_records/$cfDnsId"    # compose headers    :local headers "content-type:application/json,Authorization:Bearer $cfToken"    :local payload "{\"type\":\"$dnsType\",\"name\":\"$domain\",\"content\":\"$currentIP\",\"ttl\":$dnsTTL,\"proxied\":$dnsProxied}"    /tool fetch mode=https http-method=put url="$apiUrl" http-header-field="$headers" http-data="$payload" dst-path="" output=none    :log info "Cloudflare $domain: updated on Cloudflare with IP $currentIP"} else={    :log info "Cloudflare $domain: Previous IP $previousIPb is equal to current IP, no update needed"}
To make a query using Cloudflare's APIs, I use the fetch command and everything works fine; I can download the data of the record in JSON format.
Code:
:local getApiUrl "https://api.cloudflare.com/client/v4/zones/$cfZoneId/dns_records/$cfDnsId":local authHeader "content-type:application/json,Authorization:Bearer $cfToken":local jsonData [/tool fetch mode=https http-method=get url="$getApiUrl" http-header-field="$authHeader" as-value]
Unfortunately, however, I cannot extract the IP from the JSON data downloaded with fetch, using the following code.
Code:
:global previousIPb ($jsonData->"result"->"content")
The field I am interested in extracting is the "result"->"content" field inside the JSON data. It always returns an empty field.

I have read the RouterOS scripting documentation, but I have not been able to find a method that works with my limited programming knowledge.

Could someone help me?

Thank you

Statistics: Posted by nocivo — Mon Mar 18, 2024 9:51 am



Viewing all articles
Browse latest Browse all 21293

Trending Articles