Dynamic DNS Update Script for DNSoMatic.com behind NAT

From MikroTik Wiki
Revision as of 20:54, 18 January 2012 by Hjoelr (talk | contribs) (Removed unused variable from the script.)
Jump to: navigation, search

This script is a solution made of others solutions (nothing new). The goal is to update your account on DNSoMatic.com. The main advantage on this solution is that DNSoMatic offers the possibility of propagating DNS updates to thirth party DNSlike systems like OpenDNS, DynDNS, Change IP and other 27 more.

Current Version

This new version is tested and working on RouterOS Version 5.11. Here are some of the features this script supports.

  • Works behind a NAT
  • Supports multiple DNS-O-Matic host update

The first time this script runs, it will not go through a full update to DNS-O-Matic. Subsequent runs, however, will work. This appears to be a limitation in RouterOS where it will not find a file that was created in the same script instance.

The following permissions are required for this script to run:

  • write
  • test
  • read
# DNSoMatic automatic DNS updates

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

# User account info of DNSoMatic

:local maticuser "dnsomatic-username"
:local maticpass "dnsomatic-password"

# Set the hostname or label of network to be updated. This is the part after the double colon (::) on the DNSoMatic services page.
# Hostnames with spaces are unsupported. Replace the value in the quotations below with your host names.
# To specify multiple hosts, separate them with commas. 
# Use "all.dnsomatic.com" for the matichost to update all items in dnsomatic with this IP.

:local matichost "hostname1,hostname2"


# No more changes need

:global previousIP;

:log info "Fetching current IP"

# Get the current public IP using DNS-O-Matic service.
/tool fetch url="http://myip.dnsomatic.com/" mode=http dst-path=mypublicip.txt

# Read the current public IP into the currentIP variable.
:local currentIP [/file get mypublicip.txt contents]

:log info "Fetched current IP as $currentIP"
:if ($currentIP != $previousIP) do={
    :log info "DNSoMatic: 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://updates.dnsomatic.com/nic/update\3Fmyip=$currentIP&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG"
    :local matichostarray;
    :set matichostarray [:toarray $matichost];
    :foreach host in=$matichostarray do={
        :log info "DNSoMatic: Sending update for $host"
        /tool fetch url=($url . "&hostname=$host") user=$maticuser password=$maticpass mode=http dst-path=("dnsomaticupdate-" . $host . ".txt")
        :log info "DNSoMatic: Host $host updated on DNSoMatic with IP $currentIP"
}  else={
    :log info "DNSoMatic: Previous IP $previousIP and current IP equal, no update need"

This will also need you to configure scheduler entry for periodical runs (maybe every 5 minutes or so). You will probably want a second scheduler event run this script upon RouterOS startup.

If for whatever reason the update fails, the script will not update DNSoMatic until the IP address changes again. This is rare, but could happen. It would be recommended to set up a third scheduler with longer intervals (maybe 1 hour) to run a script with the following code:

:global previousIP;
:set previousIP ""

:log info "Cleared previousIP to force DNS-O-Matic update on next run."

There are no permissions required for this script to work.

hjoelr 18/Jan/2012

Deprecated Version

Thanks all for your solutions... with this solution DNS filtering option from OpenDNS gets open without client software.

Note: The script below is RouterOS 4.2 Tested! It should also work on 3.x series RouterOS.

# DNSoMatic automatic DNS updates
# User account info of DNSoMatic
:global maticuser "user"
:global maticpass "password"
:global matichost "Yourhost"
# No more changes need

:global previousIP

# Print values for debug
:log info "DNSoMatic: Updating dynamic IP on DNS for host $matichost"
:log info "DNSoMatic: User $maticuser y Pass $maticpass"
:log info "DNSoMatic: Last IP $previousIP"

# get the current IP address from the internet (in case of double-nat)
/tool fetch mode=http address="checkip.dyndns.org" src-path="/" dst-path="/dyndns.checkip.html"
:local result [/file get dyndns.checkip.html contents]

# parse the current IP result
:local resultLen [:len $result]
:local startLoc [:find $result ": " -1]
:set startLoc ($startLoc + 2)
:local endLoc [:find $result "</body>" -1]
:global currentIP [:pick $result $startLoc $endLoc]
:log info "DNSoMatic: IP actual $currentIP"

# Touching the string passed to fetch command on "src-path" option
:local str "/nic/update?hostname=$matichost&myip=$currentIP&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG"

:if ($currentIP != $previousIP) do={
:log info "DNSoMatic: Update need"
:set previousIP $currentIP
:log info "DNSoMatic: Sending update $currentIP"
:log info [ :put [/tool fetch host=MT user=$maticuser password=$maticpass mode=http address="updates.dnsomatic.com" src-path=$str dst-path=$matichost]]
:log info "DNSoMatic: Host $matichost updated on DNSoMatic with IP $currentIP"
}  else={
:log info "DNSoMatic: Previous IP $previousIP and current $currentIP equal, no update need"
This will also need you to configure scheduler entry for periodical runs.

gwicon 28/nov/2009