Dynamic DNS Script (No-IP and others)
RouterOS Scripting and API

8 posts   •   Page 1 of 1
AJStevens
newbie
 
Posts: 44
Joined: Sun Nov 08, 2009 1:55 pm
Location: Surrey, United Kingdom

Dynamic DNS Script (No-IP and others)

by AJStevens » Fri Nov 20, 2009 3:16 am

Hi all, was surprised after hunting around to find no GUI in winbox for DDNS, and after reading, come across several scripts.

So, I figured it was simple enough, and I had some code to go on already, I'd thought I'd come out with another variation.

95% of this script is from others, so big thanks to them, I did work out the No-IP stuff that "should" work, and in the process of making it a more "general" script.

It's a work in progress (DO NOT stick this in your RB yet!), as you can see, I'm trying to design it for several DDNS providers, and allow multiple DDNS accounts (one per interface basically).

Personally, I just No-IP, and I need two interfaces to update, but I like to design things generally.

It's missing a loop for the "accounts" and tieing settings to an interface (/account), ddnsip and ddnslastip also need to be interface/account specific.

I'll look around the wiki for further syntax information to see if I can work out what to do, any pointers are welcome, didn't really expect to have to learn RB scripting for DDNS, figured there would be a package or it part of the main package. I know, somehow at the back is going to shout "make one yourself", err... let's see how I go with this first!

For those curious (DON'T put this in your RB, it's unfinished and doesn't work!)

Code: Select all
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EDIT YOUR DETAILS / CONFIGURATION HERE
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Define DDNS Accounts for RB Interfaces, one per interface.

# The RB interface
:global ddnsinterface "ether1"
# The DDNS Provider (Choice of NOIP, DYNDNS or EVERYDNS)
:global ddnsprovider "NOIP"
# The Hostname to update.
:global ddnshost "NOIPHOST"
# Your Account Username
:global ddnsuser "NOIPUSER"
# Your Account Password
:global ddnspass "NOIPPASS"


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# END OF USER DEFINED CONFIGURATION
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Define Global Variables
:global ddnssystem ("mt-" . [/system package get system version] )

:global ddnsip
:global ddnslastip
:if ([ :typeof $ddnslastip ] = nil ) do={ :global ddnslastip "0" }


:if ($ddnsprovider = "NOIP") do={
  :global $ddnsprovname "NoIP"
  :global str "/nic/update?hostname=$ddnshost&myip=$ddnsip"
  :global $ddnsprovaddress "dynupdate.no-ip.com"
} elseif ($ddnsprovider = "DYNDNS") do={
  :global $ddnsprovname "DynDNS"
  :global str "/nic/update?hostname=$ddnshost&myip=$ddnsip&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG"
  :global $ddnsprovaddress "members.dyndns.org"
} elseif ($ddnsprovider = "EVERYDNS") do={
  :global $ddnsprovname "EveryDNS"
  :global str "/index.php?ver=0.1&ip=$ddnsip&domain=$ddnshost"
  :global $ddnsprovaddress "dyn.everydns.net"
}


# Grab the current IP address on that interface.
:global ddnsip [ /ip address get [/ip address find interface=$ddnsinterface ] address ]

# Did we get an IP address to compare?
:if ([ :typeof $ddnsip ] = nil ) do={
   :log info ("NoIP: No ip address present on " . $ddnsinterface . ", please check.")
} else={
  :if ($ddnsip != $ddnslastip) do={
        :log info $ddnsprovname.": Sending UPDATE!"
        /tool fetch address=$ddnsprovaddress src-path=$str mode=http user=$ddnsuser password=$ddnspass dst-path=("/DDNS-".$ddnsprovname.".".$ddnshost)
      }
    :delay 1
    :local str [/file find name="$ddnsprovider.$ddnshost"];
    /file remove $str
    :global ddnslastip $ddnsip
  }
}

strichek
just joined
 
Posts: 1
Joined: Fri Sep 15, 2006 9:27 pm

Re: Dynamic DNS Script (No-IP and others)

by strichek » Tue Feb 23, 2010 12:43 am

Nice work which needs some improvement. I tried to use this script for NO-IP but I had some problems regarding IP address format.
When you try to get IP address with command
Code: Select all
:local ddnsip [ /ip address get [/ip address find interface=net ] address ]
:log info $ddnsip
and look at the log, you will see something like:
Code: Select all
XX.XX.XX.XX/32

For NO-IP provider this suffix /32 is unacceptable (confirmed by their support).
Is there any way to filter-out this /32 suffix when sending IP address to No-IP?

fewi
Forum Guru
Forum Guru
 
Posts: 7734
Joined: Tue Aug 11, 2009 3:19 am

Re: Dynamic DNS Script (No-IP and others)

by fewi » Tue Feb 23, 2010 12:50 am

Code: Select all
[admin@MikroTik] > :local test "1.2.3.4/32"; :local ip [:pick $test 0 [:find $test "/"]]; :put $ip;
1.2.3.4

User avatar
Scream
just joined
 
Posts: 4
Joined: Tue Nov 16, 2010 12:21 am
Location: Budapest, Hungary

Re: Dynamic DNS Script (No-IP and others)

by Scream » Tue Nov 16, 2010 12:40 am

Hi AJStevens,

After a few our, I spent to debug the script for my ROS v4.13 (mipsbe). Here is the script that works for me (Tested only NoIP.)

Code: Select all
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EDIT YOUR DETAILS / CONFIGURATION HERE
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Define DDNS Accounts for RB Interfaces, one per interface.

# The RB interface
:global ddnsinterface "ether1"
# The DDNS Provider (Choice of NOIP, DYNDNS or EVERYDNS)
:global ddnsprovider "NOIP"
# The Hostname to update.
:global ddnshost "NOIPHOST"
# Your Account Username
:global ddnsuser "NOIPUSER"
# Your Account Password
:global ddnspass "NOIPPASS"


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# END OF USER DEFINED CONFIGURATION
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Define Global Variables
:global ddnssystem ("mt-" . [/system package get system version] )

:global ddnsip
:global ddnslastip
:if ([ :typeof $ddnslastip;] = "nil" ) do={ :set ddnslastip "0" }

:global ddnsprovname
:global str
:global ddnsprovaddress
:if ($ddnsprovider="NOIP") do={
  :set ddnsprovname "NoIP"
  :set str "/nic/update?hostname=$ddnshost&myip=$ddnsip"
  :set ddnsprovaddress "dynupdate.no-ip.com"
}
if ($ddnsprovider="DYNDNS") do={
  :set ddnsprovname "DynDNS"
  :set str "/nic/update?hostname=$ddnshost&myip=$ddnsip&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG"
  :set ddnsprovaddress "members.dyndns.org"
}
if ($ddnsprovider="EVERYDNS") do={
  :set ddnsprovname "EveryDNS"
  :set str "/index.php?ver=0.1&ip=$ddnsip&domain=$ddnshost"
  :set ddnsprovaddress "dyn.everydns.net"
}


# Grab the current IP address on that interface.
:global ddnsip2 [/ip address get [/ip address find interface=$ddnsinterface ] address];
:set ddnsip [:pick $ddnsip2 0 [:find $ddnsip2 "/"]];

# Did we get an IP address to compare?
:if ([ :typeof $ddnsip;] = "nil" ) do={
   :log info ("NoIP: No ip address present on " . $ddnsinterface . ", please check.")
} else={
  :if ($ddnsip != $ddnslastip) do={
        :log info "$ddnsprovname: Sending UPDATE!"
         /tool fetch address=$ddnsprovaddress src-path=$str mode=http user=$ddnsuser password=$ddnspass dst-path=("/DDNS-".$ddnsprovname.".".$ddnshost)
  }
  :delay 1
  :set str [/file find name="DDNS-$ddnsprovname.$ddnshost"];
  /file remove $str
  :set ddnslastip $ddnsip
}

#:log info "DDNS Update script executed successfully."

User avatar
SamCurtis
newbie
 
Posts: 29
Joined: Sat Nov 20, 2010 3:23 am

Re: Dynamic DNS Script (No-IP and others)

by SamCurtis » Wed Dec 22, 2010 12:59 am

this script doesnt work on RoS v3.30

I use noip all the time, it simply wont update. of course In natted too.

Roman4604
just joined
 
Posts: 7
Joined: Wed Jan 27, 2010 5:55 pm

Re: Dynamic DNS Script (No-IP and others)

by Roman4604 » Tue Dec 28, 2010 3:54 pm

Most of the dynip scripts I've seen are memory based, meaning updates will be sent after each reboot. Sometimes I want to muck about with my home network doing many reboots.

Since some providers get a bit upset if you bombard them with updates where the ip doesnt change, I wrote my own file based update script, called DIPU.

Code: Select all
### DIPU - Dynamic IP Updater V1.5 ###
#
### Define interface names ###
:global infWAN "ADSL"
:global inf6TO4 "HE6to4"
#
### Check if WAN inf is up, if not finish ###
:global infUP [/ip address find interface="$infWAN"]
:if ($infUP != "") do={
#
### Define DDNS credentials ###
:global userDDNS "your username"
:global passDDNS "your password"
:global hostDDNS "your hostname"
#
### Define 6to4 credentials ###
:global user6TO4 "your user-id"
:global pass6TO4 "your md5 password"
:global tun6TO4 "your tunnel-id"
#
### Get current IP ###
:global currentIP [/ip address get [/ip address find interface="$infWAN"] address]
:set currentIP [:pick $currentIP 0 [:find $currentIP "/"]]
#
### Define update URLs ###
:global ddnsURL ("http://$userDDNS:$passDDNS@ddns.someprovider.net/nic/update\?hostname=$hostDDNS&myip=$currentIP")
:global 6to4URL ("http://ipv4.tunnelbroker.net/ipv4_end.php\?ipv4b=$currentIP&pass=$pass6TO4&user_id=$user6TO4&tunnel_id=$tun6TO4")
#
### Check if history file is present, if not create it with current IP ###
:global ipFILE [/file find name="dipu-last-ip.txt"]
:if ($ipFILE="") do={
/file print file=dipu-last-ip.txt
:delay 1
/file set dipu-last-ip.txt contents="$currentIP"
:delay 1
}
#
### Initialise last value from history file ###
:global lastIP [/file get dipu-last-ip.txt contents]
#
### Compare current IP with last, if changes detected perform update ###
:if ( $currentIP != $lastIP ) do={
:log info "DIPU: WAN IP change detected from $lastIP to $currentIP"
#
### Perform DDNS update ###
:log info "DIPU: DDNS update being attempted"
/tool fetch dst-path=fetch-out.txt url=$ddnsURL
:delay 1
:global ddnsOUT [/file get fetch-out.txt contents]
:log info "DIPU: DDNS update result was '$ddnsOUT'"
#
### Perform 6to4 update ###
:log info "DIPU: 6to4 update being attempted"
/interface 6to4 set "$inf6TO4" local-address=$currentIP
/tool fetch dst-path=fetch-out.txt url=$6to4URL
:delay 1
:global 6to4OUT [/file get fetch-out.txt contents]
:log info "DIPU: 6to4 update result was '$6to4OUT'"
#
### Update history and cleanup output files ###
/file set dipu-last-ip.txt contents="$currentIP"
:delay 1
/file remove fetch-out.txt
:delay 1
:log info "DIPU: Update complete"
#
}
}
### End of script ###

Note the script will add some additional write cycles to your flash, and only tested on RB750G with 5.0rc6 so your milage may vary.

EDIT: Updated to v1.5. Functionally the same, just reorganised the logging to help in figuring out what it was trying to do if it hangs/aborts.

jeff2001
just joined
 
Posts: 1
Joined: Thu Feb 17, 2011 12:25 pm

Re: Dynamic DNS Script (No-IP and others)

by jeff2001 » Fri Feb 18, 2011 12:02 pm

I used the above info to make a no-ip update script that finds the default gateway (we use pppoe connection to dial out).
It doesn't save the last ip to a file instead it resolves the ip from the net. It also handles the no-ip update results by sending an email to our internal server. If there are problems it will stop the schedule so as not to flood the no-ip servers. We update a group on no-ip so I have added the bits for that. I use local variables as i only run it in the script engine and not straight from the terminal console. It works on a RB493G v5.0rc9 .

Code: Select all
### DDNS No-Ip script based on DIPU - Dynamic IP Updater V1.5 ###
:log info "DIPU: Starting"
#

:local currentIP
### Get the default route
:foreach routeId in=[/ip route find dst-address=0.0.0.0/0 active=yes ] do={
:local routeGateway [/ip route get $routeId gateway]
:local interfaceID [/ip address find network=$routeGateway ]
:set currentIP [/ip address get $interfaceID address]
}
#

###
:if ($currentIP != "") do={
#

### Define DDNS credentials ###
:local userDDNS "username for no-ip"
:local passDDNS "password for no-ip"
### hostDDNS is the host or group name
:local hostDDNS "grouporhostname"
### single host is the same as above unless updating a group where it must be any host in the group
:local singlehost "hostname"
:local providerAddress "dynupdate.no-ip.com"
:local emailAddressToNotify "notify@somedomain.com"
#

### Get current IP ###
#:local currentIP [/ip address get [/ip address find interface="$ddnsinterface"] address]
:set currentIP [:pick $currentIP 0 [:find $currentIP "/"]]
:log info "DIPU: Current gateway IP is $currentIP"
#

### Define update URLs ###
:local ddnsURL ("/nic/update\?hostname=$hostDDNS&myip=$currentIP")
#

### get the current IP address from the internet (in case of double-nat)
:log info "DIPU: Resolving Domain ip"
:local lastIP [:resolve $singlehost]
:log info "DIPU: Resolved Domain IP to $lastIP"
#

### Compare current IP with last, if changes detected perform update ###
:if ( $currentIP != $lastIP ) do={
:log info "DIPU: WAN IP change detected from $lastIP to $currentIP"
#

### Perform DDNS update ###
:log info "DIPU: DDNS built url: $ddnsURL"
:log info "DIPU: DDNS update being attempted"
/tool fetch address=$providerAddress dst-path=fetch-out.txt src-path=$ddnsURL mode=http user=$userDDNS password=$passDDNS
:delay 2
:local ddnsOUT [/file get fetch-out.txt contents]
/tool e-mail send subject="No-Ip Address Changed from $lastIP to $currentIP" to=$emailAddressToNotify body="DNS update result was '$ddnsOUT'"
:log info "DIPU: DDNS update result was '$ddnsOUT'"
#

###
:local resultString "'$ddnsOUT'"

### Email/Stop scheduler depending on the reult from no-ip
:if ([find $resultString "good" -1] != "") do={
/tool e-mail send subject="Success:DNS hostname update successful" to=$emailAddressToNotify body="Ip Address Changed from $lastIP to $currentIP , DNS update result was $resultString"
} else={
:if ([find $resultString "nochg" -1] != "") do={
/tool e-mail send subject="Success:IP address is current, no update performed" to=$emailAddressToNotify body="Ip remains $currentIP, DNS update result was $resultString"
} else={
:if ([find $resultString "nohost" -1] != "") do={
/tool e-mail send subject="Error:Hostname supplied does not exist under specified account" to=$emailAddressToNotify body="Scheduler stopped, DNS update result was $resultString"
:local scheduleId [/system scheduler find "DDNS"]
/system scheduler disable $scheduleId
} else={
:if ([find $resultString "badauth" -1] != "") do={
/tool e-mail send subject="Error:Invalid username password combination" to=$emailAddressToNotify body="Scheduler stopped, DNS update result was $resultString"
:local scheduleId [/system scheduler find "DDNS"]
/system scheduler disable $scheduleId
} else={
:if ([find $resultString "badagent" -1] != "") do={
/tool e-mail send subject="Error:Client disabled. Client should exit and not perform any more updates without user intervention." to=$emailAddressToNotify body="Scheduler stopped, DNS update result was $resultString"
:local scheduleId [/system scheduler find "DDNS"]
/system scheduler disable $scheduleId
} else={
:if ([find $resultString "donator" -1] != "") do={
/tool e-mail send subject="Error:An update request was sent including a feature that is not available to that particular user such as offline options." to=$emailAddressToNotify body="Scheduler stopped, DNS update result was $resultString"
:local scheduleId [/system scheduler find "DDNS"]
/system scheduler disable $scheduleId
} else={
:if ([find $resultString "abuse" -1] != "") do={
/tool e-mail send subject="Error:Username is blocked due to abuse. Either for not following our update specifications or disabled due to violation of the No-IP terms of service. Our terms of service can be viewed at http://www.no-ip.com/legal/tos. Client should stop sending updates." to=$emailAddressToNotify body="Scheduler stopped, DNS update result was $resultString"
:local scheduleId [/system scheduler find "DDNS"]
/system scheduler disable $scheduleId
} else={
:if ([find $resultString "911" -1] != "") do={
/tool e-mail send subject="Error:A fatal error on our side such as a database outage. Retry the update no sooner 30 minutes." to=$emailAddressToNotify body="Scheduler stopped, DNS update result was $resultString"
:local scheduleId [/system scheduler find "DDNS"]
/system scheduler disable $scheduleId
}
}
}
}
}
}
}
}
#


###
:log info "DIPU: Update complete"
#
} else={
:log info "DIPU: No update required"
}
}
### End of script ###

kadulin
just joined
 
Posts: 1
Joined: Tue Mar 13, 2012 12:03 am

Re: Dynamic DNS Script (No-IP and others)

by kadulin » Tue Mar 13, 2012 12:19 am

Scream wrote:Hi AJStevens,
:if ($ddnsprovider="NOIP") do={
:set ddnsprovname "NoIP"
:set str "/nic/update?hostname=$ddnshost&myip=$ddnsip"
:set ddnsprovaddress "dynupdate.no-ip.com"
}
#:log info "DDNS Update script executed successfully."[/code]


There needs to be fixed on the

:if ($ddnsprovider="NOIP") do={
:set ddnsprovname "NoIP"
:set str "/nic/update?hostname=$ddnshost&myip=$ddnsip"
:set ddnsprovaddress "dynupdate.no-ip.com"
}

http://www.no-ip.com/integrate/request

Then, in the no-ip service to get registered one address that we specify. Otherwise the current address of the gateway.

8 posts   •   Page 1 of 1

Who is online

Users browsing this forum: Google Feedfetcher and 10 guests

It is currently Sat Dec 20, 2014 6:47 pm