Community discussions

MikroTik App
 
aldoir
newbie
Topic Author
Posts: 27
Joined: Fri Aug 24, 2012 4:19 am

Dynamic DNS: One script to rule them all

Fri Aug 24, 2012 4:29 am

Hi,

I see many scripts for different providers or situations. This script is aimed to work as many situations and providers as possible, no matter if you are behind a NAT or have a public IP. As a plus, you get a "Force update every X days" feature.

If you think this script is useful, I can add other providers as well.

Some snippets of code were taken from existing scripts published in the wiki
#************************************************************************************************
# Parameters
#************************************************************************************************
:local username "<your username>"
:local password "<your password>"
:local hostname "<subdomain.yourprovider.net>"

#availabe options: "http" or "iface"
# - http: will query an external server and discover you public ip (userful for NATted connections)
# - iface: will use the ip address assigned to the $iface interface (see below)

:local discoverBy "iface"

# interface used to get ip address from (only if discoverBy = iface)

:local iface "public-dsl"

# current available services: "dyndns", "noip" and "changeip"
:local service "changeip"

# number of days to force an update if your IP did not change (helps keeping your account active)
:local forceUpdate 15

#************************************************************************************************
# do not change below this unless you know what you are doing
#************************************************************************************************

:local force
:global lastUpdate
:local currentIP

:if ($discoverBy="http") do={ 
   /tool fetch mode=http address="checkip.dyndns.org" src-path="/" dst-path="/dyndns.checkip.html"
   :local result [/file get dyndns.checkip.html contents]
   :local resultLen [:len $result]
   :local startLoc [:find $result ": " -1]
   :set startLoc ($startLoc + 2)
   :local endLoc [:find $result "</body>" -1]
   :set currentIP [:pick $result $startLoc $endLoc]
} else={
   :set currentIP [ /ip address get [find interface=$iface disabled=no] address ]
   :for i from=( [:len $currentIP] - 1) to=0 do={
      :if ( [:pick $currentIP $i] = "/") do={ :set currentIP [:pick $currentIP 0 $i] } 
   }
}

#get IP from DynDNS for our hostname
:local resolvedIP [:resolve $hostname]

# get current date in format mm/DD/YYYY
:local date [ /system clock get date ]

# convert to YYYYMMDD
:local months ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
:local month [ :pick $date 0 3 ]; :local day [ :pick $date 4 6 ]; :local year [ :pick $date 7 11 ];
:local mm ([ :find $months $month -1 ] + 1);
:if ($mm < 10) do={ :set month ("0" . $mm); } else={ :set month $mm; }
:set date ($year . $month . $day);

:if ([ :typeof $lastUpdate ]=[:nothing] || (($date-$lastUpdate) >= $forceUpdate  && $forceUpdate > 0)) do={ 
   :set force true 
}

:put ("Current IP: $currentIP ($discoverBy), Last update: $lastUpdate")

# Determine if dyndns update is needed
:if (($currentIP != $resolvedIP) || ($force = true)) do={
    
    :if ($service = "dyndns") do={
       /tool fetch user=$username password=$password mode=http address="members.dyndns.org" \
            src-path="/nic/update?hostname=$hostname&myip=$currentIP" dst-path="/output.txt"
    }
    :if ($service = "noip") do={
       /tool fetch user=$username password=$password mode=http address="dynupdate.no-ip.com" \
            src-path="/nic/update?hostname=$hostname&myip=$currentIP" dst-path="/output.txt"
    }
    :if ($service = "changeip") do={
       /tool fetch user=$username password=$password mode=http address="nic.changeip.com" \
            src-path="/nic/update?hostname=$hostname&myip=$currentIP" dst-path="/output.txt"
    }
	
    :local result [/file get output.txt contents]
    :log info ("dynamic-dns-updater: Service = $service, Hostname = $hostname")
    :log info ("dynamic-dns-updater: CurrentIP = $currentIP, Resolved IP = $resolvedIP")
    :log info ("dynamic-dns-updater: Update result: ".$result)
    /ip dns cache flush
    :set lastUpdate $date
}
 
yohanvil
just joined
Posts: 7
Joined: Fri Aug 21, 2009 3:22 pm

Re: Dynamic DNS: One script to rule them all

Tue Feb 05, 2013 6:49 am

Im afraid to tell you that it doesnt work on 5.22 version of RouterOS.

Thanks anyway!!!
 
aldoir
newbie
Topic Author
Posts: 27
Joined: Fri Aug 24, 2012 4:19 am

Re: Dynamic DNS: One script to rule them all

Tue Feb 05, 2013 3:51 pm

What is the error?

Run in console (/system script run script-name) and paste the output here pls
 
avazquez61
just joined
Posts: 1
Joined: Mon Apr 01, 2013 6:55 pm

Re: Dynamic DNS: One script to rule them all

Mon Apr 01, 2013 9:07 pm

Thanks works great rb751 5.24
 
gargola
newbie
Posts: 42
Joined: Tue Nov 20, 2012 12:05 am

Re: Dynamic DNS: One script to rule them all

Wed Aug 07, 2013 8:36 pm

This script works perfect on 6.2 version, no problem updating dyndns host :D
 
brodie7838
just joined
Posts: 18
Joined: Thu Oct 20, 2011 5:10 pm

Re: Dynamic DNS: One script to rule them all

Sun Aug 11, 2013 3:50 am

DNS O Matic uses the exact same syntax as DynDNS: http://dnsomatic.com/wiki/api

I added the following to the script:
    :if ($service = "dnsomatic") do={
       /tool fetch user=$username password=$password mode=http address="updates.dnsomatic.com" \
            src-path="/nic/update?hostname=$hostname&myip=$currentIP" dst-path="/output.txt"
    }
and got
status: failed

failure: closing connection: <301 Moved Permanently> 67.215.92.215:80 (4)
in the Terminal output. I assume that's a HTTP 301 return from "updates.dnsomatic.com"? Any thoughts?
 
mcskiller
newbie
Posts: 40
Joined: Mon Feb 13, 2012 7:12 am
Location: Argentina
Contact:

Re: Dynamic DNS: One script to rule them all

Sun Aug 11, 2013 10:21 am

Excelent job!

Enviado desde mi XT890 usando Tapatalk 2
 
brodie7838
just joined
Posts: 18
Joined: Thu Oct 20, 2011 5:10 pm

Re: Dynamic DNS: One script to rule them all

Thu Aug 15, 2013 5:20 am

Figured I'd update my progress on this. I used Packet Sniffer to get a capture at the WAN to see what was going on. The DNS O Matic server is definately sending a 301 response, and redirects me to
http://www.opendns.com/nic/update?
Here's the GET Request from the Mikrotik:
Image

And the 301 Response from the DNS O Matic server:
Image

So I edited the URL portion of the script to opendns.com so as to send
opendns.com/nic/update?hostname=$hostname&myip=$currentIP
and took another packet capture. The Mikrotik sends the request exactly as anticipated, and the server again responds with the exact same 301 Moved response. What's interesting is I can take either the updates.dnsomatic.com or the dns.com URL string, throw it in my computer's browser and get a Good response back.

Finally, for kicks and grins, I took a capture of the script updating my DynDNS account. The exact same request and URL structure from the Mikrotik, but this time a 200 OK Good response from DynDNS's server.

So conclusion at this point is it has something to do with OpenDNS's API server. I sent their support email a quick rundown with these screenshots, hopefully I'll get a reply soon. I'll post once I get a response. If anyone has any other suggestions I'd love to hear them.
 
specialist
just joined
Posts: 15
Joined: Wed Jan 02, 2013 5:30 pm
Location: Puerto RIco
Contact:

Re: Dynamic DNS: One script to rule them all

Fri Aug 30, 2013 11:23 pm

This script work on 6.2 ? !!!
 
brodie7838
just joined
Posts: 18
Joined: Thu Oct 20, 2011 5:10 pm

Re: Dynamic DNS: One script to rule them all

Sat Aug 31, 2013 1:22 am

Yes, it works on 6.2
 
brodie7838
just joined
Posts: 18
Joined: Thu Oct 20, 2011 5:10 pm

Re: Dynamic DNS: One script to rule them all

Sat Aug 31, 2013 2:45 am

OpenDNS got back to me today. Basically, because the server is shared and the Mikrotik does not send a Host: in the header, the server sends a redirect to HTTPS (they do not allow updates via HTTP any longer), and another redirect to updates.opendns.com. The latter only updates your OpenDNS account, not DNS-O-Matic.

So the question is, is there a way to get the Mikrotik to send
Host:updates.dnsomatic.com
in the header of the request?
 
specialist
just joined
Posts: 15
Joined: Wed Jan 02, 2013 5:30 pm
Location: Puerto RIco
Contact:

Re: Dynamic DNS: One script to rule them all

Sat Aug 31, 2013 5:32 am

:? In my rb2011 6.2 with dyndns already worked on 6.1 now don't work. The log said the last IP its the same, no update need. For 6.2 and dyndns account ? Only paste and nothing more ?
 
sirdir
Frequent Visitor
Frequent Visitor
Posts: 51
Joined: Tue Aug 27, 2013 8:17 pm

Re: Dynamic DNS: One script to rule them all

Sun Sep 01, 2013 4:11 am

I have dyndnses on more than one interface.. any idea how to update them all, not just the one on the default gateway?
one would have to send the request out by another than the default gateway, maybe using routing marks?
On pfsense, life was so easy ;)

Regards
Patrick
 
brodie7838
just joined
Posts: 18
Joined: Thu Oct 20, 2011 5:10 pm

Re: Dynamic DNS: One script to rule them all

Mon Sep 02, 2013 4:45 pm

Patrick,
I'm sure there's a more efficient way to do this in the existing script, but a method you could try would be to create two copies of the script, and set the second script up with your second DynDNS account information and set it to obtain by the appropriate Interface. You'll have to create a second Scheduler event to make it run around the same time as the first one.

If I had any better scripting experience, I'd put something together for you; it can't be that hard to do what you're asking in a single script.
 
efaden
Forum Guru
Forum Guru
Posts: 1708
Joined: Sat Mar 30, 2013 1:55 am
Location: New York, USA

Re: Dynamic DNS: One script to rule them all

Mon Sep 02, 2013 4:51 pm

Patrick,
I'm sure there's a more efficient way to do this in the existing script, but a method you could try would be to create two copies of the script, and set the second script up with your second DynDNS account information and set it to obtain by the appropriate Interface. You'll have to create a second Scheduler event to make it run around the same time as the first one.

If I had any better scripting experience, I'd put something together for you; it can't be that hard to do what you're asking in a single script.
A nice way to do it would be based on comments on the interfaces..

Either that or based on an array....

Sent from my SCH-I545 using Tapatalk 4
 
efaden
Forum Guru
Forum Guru
Posts: 1708
Joined: Sat Mar 30, 2013 1:55 am
Location: New York, USA

Re: Dynamic DNS: One script to rule them all

Tue Sep 03, 2013 2:21 am

I wrote two versions... I didn't actually test these. But they are an example of using either the comment on the interface or an array of hostnames to update. These only allow IP Identification by Interface Address. If you wanted to allow it via fetch and you were using HTTP (NOT HTTPS), you could use a layer7 filter to match update requests for specific hostnames and then add routing marks... that way specific hostnames request through specific interfaces.

I don't have enough hardware to setup a test to try out how that would work...

This is the Interface Comment Version:

ros code

#.* by RouterOS
#
# Dynamic DNS Master Script
#

# Set Interface Comment = "+<service>+hostname"
# Where service = dyndns | noip | changeip


#
# Variables
# 
:local dyndnsUsername ""
:local dyndnsPassword ""

:local noipUsername ""
:local noipPassword ""

:local changeipUsername ""
:local changeipPassword ""

:local forceUpdate false
:local flushDNSCache true

:local forceUpdateTime 15

# 
# Script
#
:global lastUpdate

# Date Calculations
:local date [ /system clock get date ]
:local months ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
:local month [ :pick $date 0 3 ]; :local day [ :pick $date 4 6 ]; :local year [ :pick $date 7 11 ];
:local mm ([ :find $months $month -1 ] + 1);
:if ($mm < 10) do={ :set month ("0" . $mm); } else={ :set month $mm; }
:set date ($year . $month . $day);

:if ([:typeof $lastUpdate] = "nothing" || (($date-$lastUpdate) >= $forceUpdate  && $forceUpdate > 0)) do={ 
	:set forceUpdate true
}

/interface ethernet {
	:local hadUpdate false;
	
	:foreach i in [peer find comment~"^([^+]*)\\+([^+]*)\\+([^+]*)\$"] do={
		:local commentString [get $i comment]	
		:local interfaceName [get $i name]


		:local tcomment [:pick $peerComment ([:find $peerComment "+"]+1) [:len $peerComment]]
		:local ddnsService [:pick $tcomment 0 ([:find $tcomment "+"])]
		:local ddnsHostname][ [:pick $tcomment ([:find $tcomment "+"]+1) [:len $tcomment]]
	
		:local ddnsAddress [:resolve $ddnsHostname]
		:local currentAddress [/ip address get [/ip address find interface=$interfaceName disabled=no] address]
		:set currentAddress [:pick $currentAddress 0 [:find $currentAddress "/" -1]]

		:local elseIf true

		:if (($force = true) || ($currentAddress != $ddnsAddress)) do={
    		:if ($ddnsService = "dyndns") do={
       			/tool fetch user=$username password=$password mode=http address="members.dyndns.org" \
            	src-path="/nic/update?hostname=$ddnsHostname&myip=$currentAddress" dst-path="/output.txt"
					
				:set elseIf false
    		}
			
    		:if ($elseIf && $ddnsService = "noip") do={
       			/tool fetch user=$username password=$password mode=http address="dynupdate.no-ip.com" \
            	src-path="/nic/update?hostname=$ddnsHostname&myip=$currentAddress" dst-path="/output.txt"

				:set elseIf false
    		}
    
			:if ($elseIf && $service = "changeip") do={
       			/tool fetch user=$username password=$password mode=http address="nic.changeip.com" \
            	src-path="/nic/update?hostname=$ddnsHostname&myip=$currentAddress" dst-path="/output.txt"
				
				:set elseIf false
    		}
   
   			:set hadUpdate true
		}
	}
		
	:if ($hadUpdate && $flushDNSCache) do={
		/ip dns cache flush
	}
}
This is the Array Version:

ros code

#.* by RouterOS
#
# Dynamic DNS Master Script
#

#
# Variables
# 
:local hostnamesToUpdate { \
	"hostname, service, interface"; \
	"hostname, service, interface" }

:local dyndnsUsername ""
:local dyndnsPassword ""

:local noipUsername ""
:local noipPassword ""

:local changeipUsername ""
:local changeipPassword ""

:local forceUpdate false
:local flushDNSCache true

:local forceUpdateTime 15

# 
# Script
#
:global lastUpdate

# Date Calculations
:local date [ /system clock get date ]
:local months ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
:local month [ :pick $date 0 3 ]; :local day [ :pick $date 4 6 ]; :local year [ :pick $date 7 11 ];
:local mm ([ :find $months $month -1 ] + 1);
:if ($mm < 10) do={ :set month ("0" . $mm); } else={ :set month $mm; }
:set date ($year . $month . $day);

:if ([:typeof $lastUpdate] = "nothing" || (($date-$lastUpdate) >= $forceUpdate  && $forceUpdate > 0)) do={ 
	:set forceUpdate true
}

:local hadUpdate false;
	
:foreach i in $hostnamesToUpdate do={
	:local tempArray [:toarray $i]

	:local ddnsHostname [:pick $temparray 0]
	:local ddnsService [:pick $temparray 1]
	:local interfaceName [:pick $temparray 2]

	:local ddnsAddress [:resolve $ddnsHostname]
	:local currentAddress [/ip address get [/ip address find interface=$interfaceName disabled=no] address]
	:set currentAddress [:pick $currentAddress 0 [:find $currentAddress "/" -1]]

	:local elseIf true

	:if (($force = true) || ($currentAddress != $ddnsAddress)) do={
    	:if ($ddnsService = "dyndns") do={
       		/tool fetch user=$username password=$password mode=http address="members.dyndns.org" \
           	src-path="/nic/update?hostname=$ddnsHostname&myip=$currentAddress" dst-path="/output.txt"
			:set elseIf false
    	}
			
    	:if ($elseIf && $ddnsService = "noip") do={
       		/tool fetch user=$username password=$password mode=http address="dynupdate.no-ip.com" \
           	src-path="/nic/update?hostname=$ddnsHostname&myip=$currentAddress" dst-path="/output.txt"
			:set elseIf false
    	}
    
		:if ($elseIf && $service = "changeip") do={
       		/tool fetch user=$username password=$password mode=http address="nic.changeip.com" \
           	src-path="/nic/update?hostname=$ddnsHostname&myip=$currentAddress" dst-path="/output.txt"	
			:set elseIf false
    	}
   
   		:set hadUpdate true
	}
		
:if ($hadUpdate && $flushDNSCache) do={
	/ip dns cache flush
}
 
sirdir
Frequent Visitor
Frequent Visitor
Posts: 51
Joined: Tue Aug 27, 2013 8:17 pm

Re: Dynamic DNS: One script to rule them all

Thu Sep 12, 2013 7:33 pm

I have just seen your replies and haven't tested them yet, but thank you very much for your help!

While having a very quick review of the code (I don't really know that scripting language yet…) I'm not sure if it addresses my main problem:

Say I have 2 WAN Links, WAN1 and WAN2. To correctly update the IP of WAN2, the fetch/get whatever command would have to get routed through WAN2, do the scripts do that?

Regards
Patrick
 
efaden
Forum Guru
Forum Guru
Posts: 1708
Joined: Sat Mar 30, 2013 1:55 am
Location: New York, USA

Re: Dynamic DNS: One script to rule them all

Thu Sep 12, 2013 7:52 pm

I have just seen your replies and haven't tested them yet, but thank you very much for your help!

While having a very quick review of the code (I don't really know that scripting language yet…) I'm not sure if it addresses my main problem:

Say I have 2 WAN Links, WAN1 and WAN2. To correctly update the IP of WAN2, the fetch/get whatever command would have to get routed through WAN2, do the scripts do that?

Regards
Patrick
No... unfortunately you cannot control the interface a fetch/get goes out of. If you want to use fetch or get to identify two different interfaces then what you would have to do is to use some sort of Layer7 filtering or something to tag the requests and use routing tags to get the fetch requests to go through specific routes. I'd have to think about the correct way to do it... but it is much more complex.

There isn't an option on fetch to force it to use a specific interface for its request.

The two scripts I wrote above.... one uses an array to tell the script which interfaces to use and the other just uses comments on the interfaces. Both assume that they can get the correct IP address off the interface itself.

Do you need to use fetch to get the correct addresses?
 
efaden
Forum Guru
Forum Guru
Posts: 1708
Joined: Sat Mar 30, 2013 1:55 am
Location: New York, USA

Re: Dynamic DNS: One script to rule them all

Thu Sep 12, 2013 7:54 pm

I have just seen your replies and haven't tested them yet, but thank you very much for your help!

While having a very quick review of the code (I don't really know that scripting language yet…) I'm not sure if it addresses my main problem:

Say I have 2 WAN Links, WAN1 and WAN2. To correctly update the IP of WAN2, the fetch/get whatever command would have to get routed through WAN2, do the scripts do that?

Regards
Patrick
No... unfortunately you cannot control the interface a fetch/get goes out of. If you want to use fetch or get to identify two different interfaces then what you would have to do is to use some sort of Layer7 filtering or something to tag the requests and use routing tags to get the fetch requests to go through specific routes. I'd have to think about the correct way to do it... but it is much more complex.

There isn't an option on fetch to force it to use a specific interface for its request.

The two scripts I wrote above.... one uses an array to tell the script which interfaces to use and the other just uses comments on the interfaces. Both assume that they can get the correct IP address off the interface itself.

Do you need to use fetch to get the correct addresses?
I can think about how to do it to see, if that is what you need... But I "THINK".... you could do something like this....

Make a Layer7 filter rule to set the routing mark on packets to http://myip.dnsomatic.com/interface1 and then use the routing mark to route over interface 1.... same for interface 2...

But that would require a little more thought and experimentation.
 
sirdir
Frequent Visitor
Frequent Visitor
Posts: 51
Joined: Tue Aug 27, 2013 8:17 pm

Re: Dynamic DNS: One script to rule them all

Thu Sep 12, 2013 8:48 pm

I
No... unfortunately you cannot control the interface a fetch/get goes out of. If you want to use fetch or get to identify two different interfaces then what you would have to do is to use some sort of Layer7 filtering or something to tag the requests and use routing tags to get the fetch requests to go through specific routes. I'd have to think about the correct way to do it... but it is much more complex.
That would probably be the way to do it. I already use routing tags to force certain IPs to use a specific Interfact. So if there were a way to set that mark for a request… But I have no idea how that would work…
The two scripts I wrote above.... one uses an array to tell the script which interfaces to use and the other just uses comments on the interfaces. Both assume that they can get the correct IP address off the interface itself.

Do you need to use fetch to get the correct addresses?
One has the correct address on the interface, that's easy. But others do double-nat, so the interface just has an internal IP and you have to request the public IP (like the scripts do…)

Before I used a pfsense based router, there it was very easy, you could just set up several dyndns clients, one for every interface ,)
But then, Mikrotik is of course much more powerful, when you know what you're doing (which I don't, yet ;) )
 
efaden
Forum Guru
Forum Guru
Posts: 1708
Joined: Sat Mar 30, 2013 1:55 am
Location: New York, USA

Re: Dynamic DNS: One script to rule them all

Thu Sep 12, 2013 9:06 pm

Yeah. Unfortunately there is no simple way to do that on MikroTik.

I did play around with a layer 7 filtering option with routing marks. I believe it would actually work.

Basically what you do is create two layer7 rules... 1 to match requests to http://myip.dnsomatic.com/interface1 and one to match http://myip.dnsomatic.com/interface2 ... This will work since actually it doesn't matter what URL you request from http://myip.dnsomatic.com/ ... it always just returns the IP. So then once you have matches on those rules you can create prerouting rules to add routing marks to the packets coming from your router (this way you don't do Layer7 on all your traffic). With that mark added you could then force the requests to route out the specific interfaces.

Then once all that is setup you could use a modified version of the script I posted... I can modify it for you if you want... to just use fetch on a list of interfaces.

Does all that make sense? If I get a chance tomorrow I can play around with the REGEX, etc for the above and see if I can post some sort of example of what I'm talking about.

-Eric
 
sirdir
Frequent Visitor
Frequent Visitor
Posts: 51
Joined: Tue Aug 27, 2013 8:17 pm

Re: Dynamic DNS: One script to rule them all

Fri Sep 13, 2013 4:43 pm

efaden sounds pretty plausible to me at least ;) But I'll have to look into layer 7 filtering etc. never used that before..

Regards
Patrick
 
efaden
Forum Guru
Forum Guru
Posts: 1708
Joined: Sat Mar 30, 2013 1:55 am
Location: New York, USA

Re: Dynamic DNS: One script to rule them all

Sun Sep 15, 2013 4:39 pm

efaden sounds pretty plausible to me at least ;) But I'll have to look into layer 7 filtering etc. never used that before..

Regards
Patrick
Yeah. Me either. Unfortunately there isn't a simpler way to do this. The problem is that your cannot force fetch to use a specific interface...
 
lanham
newbie
Posts: 45
Joined: Tue Jun 08, 2004 8:05 pm

Re: Dynamic DNS: One script to rule them all

Mon Oct 28, 2013 5:44 pm

FYI: Works with mipsbe but not x86 (6.5npk)

Hi,

I see many scripts for different providers or situations. This script is aimed to work as many situations and providers as possible, no matter if you are behind a NAT or have a public IP. As a plus, you get a "Force update every X days" feature.

If you think this script is useful, I can add other providers as well.

Some snippets of code were taken from existing scripts published in the wiki
#************************************************************************************************
# Parameters
#************************************************************************************************
:local username "<your username>"
:local password "<your password>"
:local hostname "<subdomain.yourprovider.net>"

#availabe options: "http" or "iface"
# - http: will query an external server and discover you public ip (userful for NATted connections)
# - iface: will use the ip address assigned to the $iface interface (see below)

:local discoverBy "iface"

# interface used to get ip address from (only if discoverBy = iface)

:local iface "public-dsl"

# current available services: "dyndns", "noip" and "changeip"
:local service "changeip"

# number of days to force an update if your IP did not change (helps keeping your account active)
:local forceUpdate 15

#************************************************************************************************
# do not change below this unless you know what you are doing
#************************************************************************************************

:local force
:global lastUpdate
:local currentIP

:if ($discoverBy="http") do={ 
   /tool fetch mode=http address="checkip.dyndns.org" src-path="/" dst-path="/dyndns.checkip.html"
   :local result [/file get dyndns.checkip.html contents]
   :local resultLen [:len $result]
   :local startLoc [:find $result ": " -1]
   :set startLoc ($startLoc + 2)
   :local endLoc [:find $result "</body>" -1]
   :set currentIP [:pick $result $startLoc $endLoc]
} else={
   :set currentIP [ /ip address get [find interface=$iface disabled=no] address ]
   :for i from=( [:len $currentIP] - 1) to=0 do={
      :if ( [:pick $currentIP $i] = "/") do={ :set currentIP [:pick $currentIP 0 $i] } 
   }
}

#get IP from DynDNS for our hostname
:local resolvedIP [:resolve $hostname]

# get current date in format mm/DD/YYYY
:local date [ /system clock get date ]

# convert to YYYYMMDD
:local months ("jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec");
:local month [ :pick $date 0 3 ]; :local day [ :pick $date 4 6 ]; :local year [ :pick $date 7 11 ];
:local mm ([ :find $months $month -1 ] + 1);
:if ($mm < 10) do={ :set month ("0" . $mm); } else={ :set month $mm; }
:set date ($year . $month . $day);

:if ([ :typeof $lastUpdate ]=[:nothing] || (($date-$lastUpdate) >= $forceUpdate  && $forceUpdate > 0)) do={ 
   :set force true 
}

:put ("Current IP: $currentIP ($discoverBy), Last update: $lastUpdate")

# Determine if dyndns update is needed
:if (($currentIP != $resolvedIP) || ($force = true)) do={
    
    :if ($service = "dyndns") do={
       /tool fetch user=$username password=$password mode=http address="members.dyndns.org" \
            src-path="/nic/update?hostname=$hostname&myip=$currentIP" dst-path="/output.txt"
    }
    :if ($service = "noip") do={
       /tool fetch user=$username password=$password mode=http address="dynupdate.no-ip.com" \
            src-path="/nic/update?hostname=$hostname&myip=$currentIP" dst-path="/output.txt"
    }
    :if ($service = "changeip") do={
       /tool fetch user=$username password=$password mode=http address="nic.changeip.com" \
            src-path="/nic/update?hostname=$hostname&myip=$currentIP" dst-path="/output.txt"
    }
	
    :local result [/file get output.txt contents]
    :log info ("dynamic-dns-updater: Service = $service, Hostname = $hostname")
    :log info ("dynamic-dns-updater: CurrentIP = $currentIP, Resolved IP = $resolvedIP")
    :log info ("dynamic-dns-updater: Update result: ".$result)
    /ip dns cache flush
    :set lastUpdate $date
}
 
lanham
newbie
Posts: 45
Joined: Tue Jun 08, 2004 8:05 pm

Re: Dynamic DNS: One script to rule them all

Tue May 20, 2014 7:34 pm

What is the error?

Run in console (/system script run script-name) and paste the output here pls
Interesting that my script works with above method but does not work when clicking the Run Script button from Winbox.
 
aldoir
newbie
Topic Author
Posts: 27
Joined: Fri Aug 24, 2012 4:19 am

Re: Dynamic DNS: One script to rule them all

Wed May 21, 2014 7:21 pm

Yes, this seems to be a bug in Mikrotik, the script runs well on scheduler but not thru the Run Script button
 
RazorMX
just joined
Posts: 1
Joined: Mon Aug 04, 2014 6:45 pm

Re: Dynamic DNS: One script to rule them all

Mon Aug 04, 2014 6:49 pm

Saludos tengo problemas al correr el script me aparece
failure: dns name does not exist
 
yan2x
newbie
Posts: 27
Joined: Sat Jun 14, 2014 2:28 am

Re: Dynamic DNS: One script to rule them all

Wed Aug 06, 2014 2:06 am

this No-Ip script doesn't work on v6.18
im on NAT pls help me....
[code]# No-IP automatic Dynamic DNS update for RouterOS v6.x

#--------------- Change Values in this section to match your setup ------------------

# No-IP User account info
:local noipuser "USERNAME"
:local noippass "PASSWORD"

# Set the hostname or label of network to be updated.
# Hostnames with spaces are unsupported. Replace the value in the quotations below with your host names.
# To specify multiple hosts, separate them with commas.
:local noiphost "no-ip.org"

# Change to the name of interface that gets the dynamic IP address
:local inetinterface "GATEWAY"

#------------------------------------------------------------------------------------
# No more changes need

:global previousIP

:if ([/interface get $inetinterface value-name=running]) do={
# Get the current IP on the interface
   :local currentIP [/ip address get [find interface="$inetinterface" disabled=no] address]

# Strip the net mask off the IP address
   :for i from=( [:len $currentIP] - 1) to=0 do={
       :if ( [:pick $currentIP $i] = "/") do={ 
           :set currentIP [:pick $currentIP 0 $i]
       } 
   }

# Get your previous IP address
   :set previousIP [:resolve $noiphost]
   
   :if ($currentIP != $previousIP) do={
       :log info "No-IP: Current IP $currentIP is not equal to previous IP $previousIP, update needed"
       :set previousIP $currentIP

# The update URL. Note the "\3F" is hex for question mark (?). Required since ? is a special character in commands.
       :local url "http://dynupdate.no-ip.com/nic/update\3Fmyip=$currentIP"
       :local noiphostarray
       :set noiphostarray [:toarray $noiphost]
       :foreach host in=$noiphostarray do={
           :log info "No-IP: Sending update for $host"
           /tool fetch url=($url . "&hostname=$host") user=$noipuser password=$noippass mode=http keep-result=no;
           :log info "No-IP: Host $host updated on No-IP with IP $currentIP"
       }
   }  else={
       :log info "No-IP: Previous IP $previousIP is equal to current IP, no update needed"
   }
} else={
   :log info "No-IP: $inetinterface is not currently running, so therefore will not update."
}


# --------------------------------------------------------------------------------------
[/code]
 
Airell
just joined
Posts: 9
Joined: Fri Mar 25, 2016 3:40 pm

Re: Dynamic DNS: One script to rule them all

Fri Apr 08, 2016 3:24 pm

So the question is, is there a way to get the Mikrotik to send
Host:updates.dnsomatic.com
in the header of the request?
I have been running into the same as you did, but two years later... until I read this and I read your communication with OpenDNS. Thank you for sharing this.

It seems you can do that now, add:
host="updates.dnsomatic.com" 
to the fetch command, and then it works!
 
User avatar
berisz
newbie
Posts: 43
Joined: Tue Dec 12, 2017 12:50 am

Re: Dynamic DNS: One script to rule them all

Tue Dec 12, 2017 1:10 am

DNS O Matic uses the exact same syntax as DynDNS: http://dnsomatic.com/wiki/api

I added the following to the script:
    :if ($service = "dnsomatic") do={
       /tool fetch user=$username password=$password mode=http address="updates.dnsomatic.com" \
            src-path="/nic/update?hostname=$hostname&myip=$currentIP" dst-path="/output.txt"
    }
and got
status: failed

failure: closing connection: <301 Moved Permanently> 67.215.92.215:80 (4)
in the Terminal output. I assume that's a HTTP 301 return from "updates.dnsomatic.com"? Any thoughts?

"fetch" "address" replace "url":
 > /tool fetch mode=http url="http://myip.dnsomatic.com/" src-path="/" dst-path="/output.txt"
 > :put [/file get output.txt contents]
so the query works, probably the update as well!

Who is online

Users browsing this forum: baragoon, bocaditos, parm and 10 guests