Multi Wan Cloudflare DynDNS (Help)

Hi All,

I am using this script - to update my cloudflare DNS. I have 2 wan ports and double natted on both of them :frowning:

Ideal solution it to run 2 scripts each updating a DNS with their own WAN IP’s.

I can update the one wan ip however it’s not he wan port I want it’s the default wan address - how can I force it to use the second wan path? I have tried a mangle rule but the IP for api.cloudflare.com keeps changing every time I ping it.

suggestions and recommendations please

#########################################################################
#         ==================================================            #
#         $ Mikrotik RouterOS update script for CloudFlare $            #
#         ==================================================            #
#                                                                       #
# - You need a CloudFlare account & api key (look under settings),      #
#   a zone and A record in it                                           #
# - All variables in first section are obvious,                         #
#   except CFid and CFzoneid                                            #
# - Obtain CFzoneid from Cloudflare Dashboard,                          #
#   on Overview tab scroll down                                         # 
#   To obtain CFid use following command in any unix shell:             #
#    curl -X GET "https://api.cloudflare.com/client/v4/zones/YOUR_ZONE_ID/dns_records?name=YOUR_DOMAIN" -H "Authorization:Bearer $CFtkn" -H "Content-Type: application/json" | python -mjson.tool
# - You can use my Postman script to get those variables                #
# - Enable CFDebug if needed - it'll print some info to logs            #
# - Enable CFcloud if you don't get a public IP on interface            #
# - Put script under /system scripts giving "read,write,ftp" policy access.       #
#   For 6.29 and older "test" policy is also needed.                    #
# - Add script to /system scheduler using it's name in "on-event"       #
# - Requires at least RouterOS 6.44beta75 for multiple header support   #
#                                                                       #
#              Credits for Samuel Tegenfeldt, CC BY-SA 3.0              #
#                        Modified by kiler129                           #
#                        Modified by viritt                             #
#                        Modified by asuna                              #
#                        Modified by mike6715b                          #
#                                                                       #
#               Tested and working as of February 22, 2021              #
#########################################################################

################# CloudFlare variables #################
:local CFDebug "false"
:local CFcloud "false"

:global WANInterface "WAN_INTERFACE"

:local CFdomain "YOUR_DOMAIN"

:local CFtkn "YOUR_API_TOKEN"

:local CFzoneid "ZONE_ID"
:local CFid "RECORD_ID"

:local CFrecordType ""
:set CFrecordType "A"

:local CFrecordTTL ""
:set CFrecordTTL "120"

#########################################################################
########################  DO NOT EDIT BELOW  ############################
#########################################################################

:log info "Updating $CFDomain ..."

################# Internal variables #################
:local previousIP ""
:global WANip ""

################# Build CF API Url (v4) #################
:local CFurl "https://api.cloudflare.com/client/v4/zones/"
:set CFurl ($CFurl . "$CFzoneid/dns_records/$CFid");
 
################# Get or set previous IP-variables #################
:if ($CFcloud = "true") do={
    :set WANip [/ip cloud get public-address]
};

:if ($CFcloud = "false") do={
    :local currentIP [/ip address get [/ip address find interface=$WANInterface ] address];
    :set WANip [:pick $currentIP 0 [:find $currentIP "/"]];
};

:if ([/file find name=ddns.tmp.txt] = "") do={
    :log error "No previous ip address file found, createing..."
    :set previousIP $WANip;
    :execute script=":put $WANip" file="ddns.tmp";
    :log info ("CF: Updating CF, setting $CFDomain = $WANip")
    /tool fetch http-method=put mode=https output=none url="$CFurl" http-header-field="Authorization:Bearer $CFtkn,content-type:application/json" http-data="{\"type\":\"$CFrecordType\",\"name\":\"$CFdomain\",\"ttl\":$CFrecordTTL,\"content\":\"$WANip\"}"
    :error message="No previous ip address file found."
} else={
    :if ( [/file get [/file find name=ddns.tmp.txt] size] > 0 ) do={ 
    :global content [/file get [/file find name="ddns.tmp.txt"] contents] ;
    :global contentLen [ :len $content ] ;  
    :global lineEnd 0;
    :global line "";
    :global lastEnd 0;   
            :set lineEnd [:find $content "\n" $lastEnd ] ;
            :set line [:pick $content $lastEnd $lineEnd] ;
            :set lastEnd ( $lineEnd + 1 ) ;   
            :if ( [:pick $line 0 1] != "#" ) do={   
                #:local previousIP [:pick $line 0 $lineEnd ]
                :set previousIP [:pick $line 0 $lineEnd ];
                :set previousIP [:pick $previousIP 0 [:find $previousIP "\r"]];
            }
    }
}

######## Write debug info to log #################
:if ($CFDebug = "true") do={
 :log info ("CF: hostname = $CFdomain")
 :log info ("CF: previousIP = $previousIP")
 :log info ("CF: currentIP = $currentIP")
 :log info ("CF: WANip = $WANip")
 :log info ("CF: CFurl = $CFurl&content=$WANip")
 :log info ("CF: Command = \"/tool fetch http-method=put mode=https url=\"$CFurl\" http-header-field="Authorization:Bearer $CFtkn,content-type:application/json" output=none http-data=\"{\"type\":\"$CFrecordType\",\"name\":\"$CFdomain\",\"ttl\":$CFrecordTTL,\"content\":\"$WANip\"}\"")
};
  
######## Compare and update CF if necessary #####
:if ($previousIP != $WANip) do={
 :log info ("CF: Updating CF, setting $CFDomain = $WANip")
 /tool fetch http-method=put mode=https url="$CFurl" http-header-field="Authorization:Bearer $CFtkn,content-type:application/json" output=none http-data="{\"type\":\"$CFrecordType\",\"name\":\"$CFdomain\",\"ttl\":$CFrecordTTL,\"content\":\"$WANip\"}"
 /ip dns cache flush
    :if ( [/file get [/file find name=ddns.tmp.txt] size] > 0 ) do={
        /file remove ddns.tmp.txt
        :execute script=":put $WANip" file="ddns.tmp"
    }
} else={
 :log info "CF: No Update Needed!"
}

The script must be fixed, is full of errors…
Example, from this:

[…]
:local CFcloud "false"
[…]

:if ($CFcloud = "true") do={
    :set WANip [/ip cloud get public-address]
};

:if ($CFcloud = "false") do={
    :local currentIP [/ip address get [/ip address find interface=$WANInterface ] address];
    :set WANip [:pick $currentIP 0 [:find $currentIP "/"]];
};

to thins (untested):

[…]
:local CFcloud   false
:local currentIP 0.0.0.0
[…]

:if ($CFcloud) do={
    :set WANip     [/ip cloud get public-address]
} else={
    :set currentIP [/ip address get ([find where interface=$WANInterface]->0) address]
    :set WANip     [:pick $currentIP 0 [:find $currentIP "/" -1]]
}

If its full of errors how is it the OP claims… I am using this script - to update my cloudflare DNS.

Also dont understand the mangle bit??
For double nattted routers trying to update the third party dydns whenever ones IP changes would be difficult.
One would have to constantly going out to the internet with whats my IP and then sending the new IP to the DYNDNS third party site.
For at least one of the WANS, supposing one could somehow use IP cloud for one of them??

Thank you I will try that later today

Hi - when i run the script it is connecting to cloudflare and updating the IP with the wrong ip address
script.JPG
my idea was sending the traffic out the correct wan address when it’s doing its what’s my ip call


just an idea

# ONCE
/ip firewall address-list
add address=api.cloudflare.com list=apicloudflare



# need to get the gateway of each WAN
# :local GW1 ...
# :local GW2 ...

# WAN1
:foreach i in=[/ip/firewall/address-list/find list=apicloudflare && dynamic=yes] do={
    /ip/route/add dst-address=[/ip/firewall/address-list/get value-name=address $i] gateway=$GW1 comment="tmpCF"
}
# CF API Url (v4)
# ...
/ip/route/remove [find comment="tmpCF"]
# WAN2
:foreach i in=[/ip/firewall/address-list/find list=apicloudflare && dynamic=yes] do={
    /ip/route/add dst-address=[/ip/firewall/address-list/get value-name=address $i] gateway=$GW2 comment="tmpCF"
}
# CF API Url (v4)
# ...
/ip/route/remove [find comment="tmpCF"]

That’s a good idea

when I run it - It created all the rules except it was not putting the WAN interface in the gateway which is strange - that seems to be a smart way of forcing the which wan to use