Community discussions

MikroTik App
 
msachse
just joined
Topic Author
Posts: 8
Joined: Mon Jun 26, 2023 3:46 pm

Update Cloudflare DNS with script

Wed Jun 26, 2024 1:23 am

Hello,
I am trying to write a script that would allow routerOS to update cloudflare through their API any time my ISP changes the WAN IP on my router. I found some starting point in GIT (https://github.com/dudanov/mikrotik-clo ... ns-scripts) but have not been successful in running the script as it is giving me errors. The device is running RouterOS 7.14.3.

Anybody can point out how the script needs to be reworked? I tried adding line by line and found the first error is coming where the current IP address for WAN is being retrieved.
# Update Cloudflare DNS IPv4 address script
# RouterOS version >= 6.44 is required

# ** CONFIGURE SECTION **

# WAN IPv4 interface
:local wanif    "wan1"

# Cloudflare section
:local email    "e-mail"
:local key      "token"
:local zoneId   "zoneId"
:local hostId   "hostId"

# Domain hostname
:local hostName "host.yourdomain.com"

# ** END OF CONFIGURE SECTION **

# Get WAN interface IPv4 address
:global ip4wan
:local ip4new [/ip address get [/ip address find interface=$wanif] address]
:set ip4new [:pick [:tostr $ip4new] 0 [:find [:tostr $ip4new] "/"]]

:if ([:len $ip4new] = 0) do={
  :log error "[Cloudflare DDNS] Could not get IPv4 for interface $wanif"
  :error "[Cloudflare DDNS] Could not get IPv4 for interface $wanif"
}

:if ($ip4new != $ip4wan) do={

  :log info "[Cloudflare DDNS] WAN IPv4 address for interface $wanif has been changed to $ip4new."

  :local url    "https://api.cloudflare.com/client/v4/zones/$zoneId/dns_records/$hostId"
  :local header "X-Auth-Email: $email, X-Auth-Key: $key, content-type: application/json"
  :local data   "{\"type\":\"A\",\"name\":\"$hostName\",\"content\":\"$ip4new\",\"ttl\":120}"

#  :log info "[Cloudflare DDNS] URL: $url"
#  :log info "[Cloudflare DDNS] HEADER: $header"
#  :log info "[Cloudflare DDNS] DATA: $data"
#  :log info "[Cloudflare DDNS] Updating host $hostName address."

  :local jsonAnswer [/tool fetch mode=https http-method=put http-header-field=$header http-data=$data url=$url as-value output=user]

  :if ([:len $jsonAnswer] > 0) do={

    /system script run "JParseFunctions"; global JSONLoads; global JSONUnload
    :local result ([$JSONLoads ($jsonAnswer->"data")]->"success")
    $JSONUnload

    :if ($result = true) do={
      :log info "[Cloudflare DDNS] Successfully updated IPv4 address to $ip4new."
      :set ip4wan $ip4new
    } else={
      :log error "[Cloudflare DDNS] Error while updating IPv4 address."
    }
  } else={
    :log error "[Cloudflare DDNS] No answer from Cloudflare API."
  }
}

 
User avatar
tangent
Forum Guru
Forum Guru
Posts: 1656
Joined: Thu Jul 01, 2021 3:15 pm
Contact:

Re: Update Cloudflare DNS with script

Sat Jun 29, 2024 9:59 am

Do you have an interface called “wan1”? If not, the script will of course fail. Either change the name to that of your actual WAN interface or rename it to wan1 to placate the script.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12534
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Update Cloudflare DNS with script

Sat Jun 29, 2024 10:07 am

Or much more simply, the script is made with the feet, and if the interface wan1 has more than one IP the script fails...

When making a script, all the steps must be validated step by step...

Incomplete example:
Does the interface exist?
It has exactly one IP (neither 0, nor more than 1)???
[or] if it has more than one IP, ignore the local ones (for example 192.168. 100.2/24) etc...
 
msachse
just joined
Topic Author
Posts: 8
Joined: Mon Jun 26, 2023 3:46 pm

Re: Update Cloudflare DNS with script

Thu Jul 25, 2024 3:41 am

@rextended: Interesting enough, the script works but with a flaw that doesn't come from itself. The interface gets a second IP assigned through IPSec. Now I'm not sure why my VPN Tunnels do that since I am running two and only one is being created by the policies. But if I delete that second address, the script works.

Now to the million dollar question: How do I modify the script so it not only looks for the address on my wan1 interface but also the right one of the two? I tried to combine the statement using AND but get a syntax error in the terminal. Any ideas? I suppose the following line has to be modified:
:local ip4new [/ip address get [/ip address find interface=$wanif] address]
and this doesn't do the trick:
:local ip4new [/ip address get [/ip address find interface=$wanif and address!=10.6.*] address][/code
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12534
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Update Cloudflare DNS with script

Fri Jul 26, 2024 1:46 am

:local ip4new [/ip address get [/ip address find interface=$wanif] address]

+ "the first assigned only"

=

:local ip4new [/ip address get ([/ip address find interface=$wanif]->0) address]

But what I write before is still valid.
 
User avatar
Lokamaya
Member Candidate
Member Candidate
Posts: 101
Joined: Thu Nov 11, 2021 4:40 am
Location: Bandung

Re: Update Cloudflare DNS with script

Sat Nov 09, 2024 3:21 pm

... found the first error is coming where the current IP address for WAN is being retrieved.
# Update Cloudflare DNS IPv4 address script
:local ip4new [/ip address get [/ip address find interface=$wanif] address]
:set ip4new [:pick [:tostr $ip4new] 0 [:find [:tostr $ip4new] "/"]]
How your router connect to the internet? Using DHCP or PPPoE?

PPPoE: via /ip/address
:local wanif "pppoe-interface" 
...
:local ip4new [/ip/address/get [find where interface=$wanif] value-name=address];
DHCP: how does the router connect to the modem? If your router only had local ip (i.e. 192.168.x.x), you can't get the public ip from your modem using that script. But there is a workaround, for example using public service like http://checkip.amazonaws.com/.

DHCP: via /tool/fetch
# :local wanif "dhcp-interface" (not used)
:local ip4new "0"

:local result [:tool fetch url="http://checkip.amazonaws.com/" as-value output=user]
:if ($result->"status" = "finished") do={
  :local ip4new [:pick ($result->"data") 0 ( [ :len ($result->"data") ] -1 )]
}

:if ([:len $ip4new] < 7) do={
  :log error "[Cloudflare DDNS] Could not get IPv4 for interface $wanif"
  :error "[Cloudflare DDNS] Could not get IPv4 for interface $wanif"
}

...

Who is online

Users browsing this forum: No registered users and 7 guests