MikroTik Script: No-IP.com DDNS Update

I’ve been using No-IP.com as my Dynamic DNS service for the past year. I was keeping my DDNS address updated via No-IP’s  Dynamic Update Client for Windows. Using No-IP’s client to keep the DDNS address and IP current worked well, but I wanted to move the update functionality from my home PC to my MikroTik. There was already a script for this on the MikroTik Wiki that was created by riverron, which I had tried, but I wanted to make a few minor modifications to the script. I converted the scope of the variable $previousIP from global to local and assigned the value to this variable via DNS resolution. I also added a variable to set the log destination, which is fetched from No-IP’s DDNS service when an update occurs.

Marthur's No-IP.com Dynamic DNS Update Script v1.0

#---------------------------------------------------SCRIPT INFORMATION----------------------------------------------------
#
# Script:  Marthur's No-IP.com Dynamic DNS Update Script
# Version: 1.0
# Updated: 07/30/2018
# Created: 10/21/2017
# Author:  Marthur Jones
# Website: https://www.marthur.com
#
# This script is to be used in conjunction with No-IP.com's Dynamic DNS Service. It is to be scheduled/ran on a Mikrotik 
# router as replacement for No-IP's Dynamic Update Client for Windows. There are many versions of this script. However, 
# I've made my own modifications to the original script that was created on March 13, 2012 by riverron and published on
# the MikroTik Wiki here:
#
# https://wiki.mikrotik.com/wiki/Dynamic_DNS_Update_Script_for_No-IP_DNS
#
# - Changed the scope of the variable that stores the previous IP address from global to local. The local variable's value 
#   (IP address) is now assigned via MikroTik's DNS resolution. The script compares the previous IP with the current IP 
#   that is assigned to the WAN interface, if the IP addresses do not match, the script will update the No-IP hostname
#   with the IP assigned to the WAN interface.
#
# - Added variable to define the log destination path that the script pulls from No-IP.com after a DDNS IP update.
#
# - Made variable name changes.
#
#-----------------------------------------------TESTED USING THE FOLLOWING------------------------------------------------
#
# Hardware: CCR1009-7G-1C-1S+
# Firmware: v3.41
# RouterOS: v6.40.4
#
#----------------------------------------------MODIFY THIS SECTION AS NEEDED----------------------------------------------

# No-IP account credentials.
:local noipUsername "NOIP_USERNAME"
:local noipPassword "NOIP_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 noipHostname "NOIP_HOSTNAME.ddns.net"

# The interface name with the assigned dynamic IP address (usually the WAN interface).
:local wanInterface "Ether0-Gateway"

# Log destination
:local logDestination "/disk1/logs/"

#-------------------------------------------------------------------------------------------------------------------------

:log warning message="START: No-IP DDNS Update"

:if ([/interface get $wanInterface value-name=running] = true) do={

#   Get the previous IP via DNS resolution.
    :local previousIP [:resolve "$noipHostname"]

#   Get the current IP on the WAN interface.
    :local currentIP [/ip address get [find interface="$wanInterface" disabled=no] address]

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

    :log info "No-IP: DNS IP ($previousIP), interface IP ($currentIP)"
    
    :if ($currentIP != $previousIP) do={
        :log info "No-IP: Current IP $currentIP is not equal to previous IP, update needed"

#       The update URL. The "\3F" is hex for question mark (?). This is required since ? is a special character in the command.
        :local url "http://dynupdate.no-ip.com/nic/update\3Fmyip=$currentIP"
        :local noipHostnames
        :set noipHostnames [:toarray $noipHostname]
        :foreach hostname in=$noipHostnames do={
            :log info "No-IP: Sending update for $hostname"
            /tool fetch url=($url . "&hostname=$hostname") user=$noipUsername password=$noipPassword mode=http dst-path=($logDestination . "no-ip_ddns_update-" . $hostname . ".txt")
            :log info "No-IP: Host $hostname 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: $wanInterface is not currently running, unable to verify and/or update IP."
    }
    
:log warning message="END: No-IP DDNS Update"

11 thoughts on “MikroTik Script: No-IP.com DDNS Update”

    1. Tux,

      If I understand you correctly, you are correct. You will not be able to assign a DDNS address to a MikroTik behind a NAT. If you want to be able to reach a double NAT device, you could have DDNS assigned the first router and then port forward to the second (MikroTik).

  1. Hi
    Thanks for this script. Works very well. But while testing I found minor typo.
    In line 53 there should be reference to variable using $ symbol. Script fails since /interface get returns “no such item”.
    Fixed lane 53 is bellow:
    :if ([/interface get $wanInterface value-name=running] = true) do={

    Regards,
    Blaz

    1. Blaz,

      I’ve corrected the typo. Thank you for letting me know. The script is entered correctly on my MikroTik, but not the website. Probably a result of search & replace error on my part.

  2. Dimitar Angelov

    Just stopping by to say – Thank you mr. Jones.
    To whom it may concern – Don’t forget to check the “password” checkbox when adding the script.

  3. Script NO-IP BEHIND NAT, that’s WORK

    # Set needed variables
    :local username “your no-ip user login”
    :local password “your no-ip password”
    :local host “your no-ip host name”
    :global previousIP
    # print some debug info
    :log info (“Update No-IP DNS: username = $username”)
    :log info (“Update No-IP DNS: hostname = $host”)
    :log info (“Update No-IP DNS: previousIP = $previousIP”)
    #
    # behind nat – get the public address using dyndns url http://checkip.dyndns.org
    /tool fetch mode=http address=”checkip.dyndns.org” src-path=”/” dst-path=”/dyndns.checkip.html”
    :delay 2
    :local result [/file get dyndns.checkip.html contents]
    :log info “dyndns result = $result”
    # parse the current IP result
    :local resultLen [:len $result]
    :local startLoc [:find $result “: ” -1]
    :set startLoc ($startLoc + 2)
    :local endLoc [:find $result “” -1]
    :local currentIP [pick $result $startLoc $endLoc]
    :log info “No-IP DNS: currentIP = $currentIP”
    :if ($currentIP != $previousIP) do={
    :log info “No-IP: Current IP $currentIP is not equal to previous IP, update needed”
    :set previousIP $currentIP
    :local url “http://dynupdate.no-ip.com/nic/update/?myip=$currentIP&hostname=$host”
    :log info “No-IP DNS: Sending update for $host”
    /tool fetch url=$url user=$username password=$password mode=http dst-path=(“no-ip_ddns_update.txt”)
    :log info “No-IP DNS: Host $host updated on No-IP with IP $currentIP”
    :delay 2
    :local result [/file get “no-ip_ddns_update.txt” contents]
    :log info “Update Result = $result”
    } else={
    :log info “No-IP: update not needed ”
    }
    # end

    1. Anything in the script log? I’ve been short on time at home, but I’ll see if I can take a closer look at what might be going on and test it again from my end.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top