Community discussions

MikroTik App
 
craigthom
just joined
Topic Author
Posts: 8
Joined: Sat Mar 28, 2015 11:45 pm

Dynamic DNS scripting and global variables

Sun Mar 29, 2015 12:52 am

I am brand new to RouterOS, so forgive me if this is a silly question.

All the example scripts I've seen to update dynamic DNS services use a global variable to store the previous IP address to compare to the new one.

Is there a reason this is done instead of using :resolve "hostname"?

I guess my main objection to global variables is one of style, but I'd still like to avoid them if possible.

Along the same lines, is there any way to get "/tool fetch" to store its results in a variable instead of a file? That would make a cleaner script, too.
 
jarda
Forum Guru
Forum Guru
Posts: 7756
Joined: Mon Oct 22, 2012 4:46 pm

Mon Mar 30, 2015 5:00 am

You cannot get file into memory. And you need to compare your ip to something in order to know whether it has changed or not because you would be telling to your ddns service the same ip repeatedly so it will become banning you.
 
User avatar
ZeroByte
Forum Guru
Forum Guru
Posts: 4047
Joined: Wed May 11, 2011 6:08 pm

Re: Dynamic DNS scripting and global variables

Mon Mar 30, 2015 5:33 am

You could store the "current" IP in an ip firewall address list.
Those are persistent even through reboots.
(global environment variables don't survive reboots)

Or you could use the comment of the WAN interface to store the 'current' ip and if the comment != ip address, then you know it's changed.
 
craigthom
just joined
Topic Author
Posts: 8
Joined: Sat Mar 28, 2015 11:45 pm

Re:

Mon Mar 30, 2015 7:48 am

You cannot get file into memory. And you need to compare your ip to something in order to know whether it has changed or not because you would be telling to your ddns service the same ip repeatedly so it will become banning you.
I am comparing the current address, from "/IP cloud current-address", with the last one set, but I'm determining the last one set using ":resolve $hostName" rather than storing it as a global variable. ":resolve" will return the address the dynamic DNS provider has without storing it in the router.

That seems like a more elegant solution to me, but I wonder if there is a reason not to execute a ":resolve" once a minute. Half the scripts determine the current IP by fetching a "what's my IP" type Web page, which would generate much more traffic, so I don't think that's the reason. I know that "/IP cloud" is relatively new, but the current address can still be read from the interface without hitting an external Web site.

As noted, using a global variable will cause the dynamic DNS provider to be hit unnecessarily every time the router is rebooted and the variable lost. This won't happen often, so I don't think it's a problem, but I won't happen if ":resolve" is used to determine the last address sent to them.

As for getting a file into memory, I am doing that with "/file get", but I was hoping there was a way to get the results of a fetch directly into a variable, rather than writing it to a file and then reading that file into a variable, but I don't think "fetch" can work that way; it either writes the results to a file or doesn't return them at all.
 
deanMKD1
Member
Member
Posts: 366
Joined: Fri Dec 12, 2014 12:06 am
Location: Macedonia
Contact:

Re: Dynamic DNS scripting and global variables

Mon Mar 30, 2015 12:54 pm

I found this: http://mikrotikmacedonia.com/index.php/topic,6.0.html

I use the same script, on my RB2011 and works great for NO-IP DDNS. :)
 
craigthom
just joined
Topic Author
Posts: 8
Joined: Sat Mar 28, 2015 11:45 pm

Re: Dynamic DNS scripting and global variables

Mon Mar 30, 2015 2:31 pm

I found this: http://mikrotikmacedonia.com/index.php/topic,6.0.html

I use the same script, on my RB2011 and works great for NO-IP DDNS. :)
And that script also uses a global variable to store the previous IP between executions of the script.

It looks as if the answer to my question "why do it that way?" is that everyone is just copying scripts and the ones they copied did it that way.

I'm doing it this way, and it works just fine.
:local currentIP ""
:local previousIP ""
:set currentIP [/ip cloud get public-address]
:set previousIP [:resolve "$hostName"]
The advantage to do it this way is that $previousIP is not the last value the script set; it's the actual value being used. It's right the first time the script executes, it's right if the router has been rebooted, and it's even right if some other method has been used to update the IP address.

I thought there might be some disadvantage to doing it this way, so I asked, but I think the only reason it isn't being used is because the script copied didn't do it this way.
 
User avatar
ZeroByte
Forum Guru
Forum Guru
Posts: 4047
Joined: Wed May 11, 2011 6:08 pm

Re: Dynamic DNS scripting and global variables

Mon Mar 30, 2015 3:53 pm

And that script also uses a global variable to store the previous IP between executions of the script.

I thought there might be some disadvantage to doing it this way, so I asked, but I think the only reason it isn't being used is because the script copied didn't do it this way.
My suggestion doesn't use a global variable.

The only drawback I can see for :resolve every minute is cacheing. If the Mikrotik is not using the authoritative server for :resolve - then whatever server it is using will cache the answer for the TTL amount of time. If the TTL is 10 minutes or something like that, then querying every minute will not be useful because the cache will stay for 10 minutes, even if you update to the DDNS server - in fact, your script would send updates to DDNS server 9 extra times before seeing the "previous" address matches the current one.

(of course, you control the TTL value of your ddns RR, so make it something short like 5 minutes, and set your script to execute once every 5 minutes, and you won't have that problem)
 
craigthom
just joined
Topic Author
Posts: 8
Joined: Sat Mar 28, 2015 11:45 pm

Re: Dynamic DNS scripting and global variables

Mon Mar 30, 2015 4:19 pm

And that script also uses a global variable to store the previous IP between executions of the script.

I thought there might be some disadvantage to doing it this way, so I asked, but I think the only reason it isn't being used is because the script copied didn't do it this way.
My suggestion doesn't use a global variable.

The only drawback I can see for :resolve every minute is cacheing. If the Mikrotik is not using the authoritative server for :resolve - then whatever server it is using will cache the answer for the TTL amount of time. If the TTL is 10 minutes or something like that, then querying every minute will not be useful because the cache will stay for 10 minutes, even if you update to the DDNS server - in fact, your script would send updates to DDNS server 9 extra times before seeing the "previous" address matches the current one.

(of course, you control the TTL value of your ddns RR, so make it something short like 5 minutes, and set your script to execute once every 5 minutes, and you won't have that problem)
Thank you. I am using Google Domains, which doesn't let me set the TTL, but it shows 1m (even though their help says the default is one hour).

That's a good reason to use something other than :resolve, which is what I was looking for. Thanks.

Although if the TTL was longer, my site would probably be unreachable until the cache had expired, so maybe setting the script schedule to half the TTL would be a good compromise. Then I'd make at most one unnecessary attempts to set it. But that makes the script less easy to implement.
 
User avatar
ZeroByte
Forum Guru
Forum Guru
Posts: 4047
Joined: Wed May 11, 2011 6:08 pm

Re: Dynamic DNS scripting and global variables

Mon Mar 30, 2015 6:53 pm

That's a good reason to use something other than :resolve, which is what I was looking for. Thanks.
I think I just thought of a good compromise on this situation.
There's really no harm in storing "previousIP" in a global environment variable, other than that it isn't set at boot time.

The script could start off like this and use :resolve to seed the environment variable-
#check if previousIP is set....
:global previousIP
:if ([:typeof $previousIP] != "ip") do={:set previousIP [:resolve "$hostName"]}

#check that previosIP = current wan IP....
Interestingly, the script behavior that is the bane of most people's existence (script halts if :resolve fails) actually helps here.
No need to put a second type=ip check ... if the resolve fails, the script bombs, and when it runs again a minute later, $previousIP will still be not properly set, so it will try to :resolve again.... until such time as that works, whreupon it will finally continue to compare this with the currentIP as normal.
 
bingo220
Member Candidate
Member Candidate
Posts: 124
Joined: Sun Sep 22, 2013 9:30 pm
Location: Ukraine

Re: Dynamic DNS scripting and global variables

Mon Mar 30, 2015 8:41 pm

I once showed my scripts for "no-ip" service, it may interest you.
http://forum.mikrotik.com/viewtopic.php ... 44#p419745
 
User avatar
ZeroByte
Forum Guru
Forum Guru
Posts: 4047
Joined: Wed May 11, 2011 6:08 pm

Re: Dynamic DNS scripting and global variables

Tue Mar 31, 2015 5:00 am

I fixed my own script to be able to run automatically. It will find the correct wan IP even after reboot, using only a :global environment variable.

However, during the re-write, I noticed that the ddns update tool doesn't seem to have any way to specify AAAA record.
I have IPv6 live at my house, and would like to include at least AAAA records in my ddns as well.

I guess I should go put this in the feature requests. (my /60 prefix has changed MANY times in the month I've been using native v6 from Comcast)

p.s. I wish Comcast would support PTR delegation. grrrr.

Who is online

Users browsing this forum: Pilo2710 and 57 guests