Description

This article shows my take on DHCP server lease script, which creates and deletes static DNS records automatically, based on creation and deletion of DHCP leases. Although, bunch of such scripts is already available, I wanted to have the features I liked merged into one universal script.

Updates

  • 2020-07-23 Fixed decision on usage of DNS domain and made according section less complex. Thanks to Wojtek and Gavin who pointed this out.

Features

  • Creates static DNS records according to assigned DHCP lease.
  • Deletes static DNS records according to unassigned DHCP lease.
  • Deletes all related static DNS records, when new DNS record is being created to prevent duplicates. This can be done by IP and by hostname.
  • DNS records hostname can use additional domain name or use short hostname – or both.
  • Hostname for DNS record can be set from:
    • Variable set from the lease ( $”lease-hostname” ) – quick solution, which uses hostname passed from client
    • Hostname from the lease ( “host-name” attribute ) – a bit more CPU intensive solution, which searches leases for related hostname, but is also more compatible, if previous option is not available
    • Comment of the static lease ( “comment” attribute ) – secure solution, which uses hostname from comment of related static DHCP lease
  • Supports separated deployment on multiple instances of DHCP server within one MikroTik device.

Script

To use the script, just copy-paste it into DHCP Server lease script field ( IP -> DHCP Server -> DHCP (tab) -> DHCP server instance -> Script (tab) -> Lease Script ) or into console editor using “/ip dhcp-server edit default lease-script” or by other means:

# When "1" all DNS entries with IP address of DHCP lease are removed
:local dnsRemoveAllByIp "1"
# When "1" all DNS entries with hostname of DHCP lease are removed
:local dnsRemoveAllByName "1"
# When "1" addition and removal of DNS entries is always done also for non-FQDN hostname
:local dnsAlwaysNonfqdn "1"
# DNS domain to add after DHCP client hostname
:local dnsDomain "dynamic.example.local"
# DNS TTL to set for DNS entries
:local dnsTtl "00:15:00"
# Source of DHCP client hostname, can be "lease-hostname" or any other lease attribute, like "host-name" or "comment"
:local leaseClientHostnameSource "lease-hostname"

:local leaseComment "dhcp-lease-script_$leaseServerName_$leaseClientHostnameSource"
:local leaseClientHostname
:if ($leaseClientHostnameSource = "lease-hostname") do={
  :set leaseClientHostname $"lease-hostname"
} else={
  :set leaseClientHostname ([:pick \
    [/ip dhcp-server lease print as-value where server="$leaseServerName" address="$leaseActIP" mac-address="$leaseActMAC"] \
    0]->"$leaseClientHostnameSource")
}
:local leaseClientHostnames "$leaseClientHostname"
:if ([:len [$dnsDomain]] > 0) do={
  :if ($dnsAlwaysNonfqdn = "1") do={
    :set leaseClientHostnames "$leaseClientHostname.$dnsDomain,$leaseClientHostname"
  } else={
    :set leaseClientHostnames "$leaseClientHostname.$dnsDomain"
  }
}
:if ($dnsRemoveAllByIp = "1") do={
  /ip dns static remove [/ip dns static find comment="$leaseComment" and address="$leaseActIP"]
}
:foreach h in=[:toarray value="$leaseClientHostnames"] do={
  :if ($dnsRemoveAllByName = "1") do={
    /ip dns static remove [/ip dns static find comment="$leaseComment" and name="$h"]
  }
  /ip dns static remove [/ip dns static find comment="$leaseComment" and address="$leaseActIP" and name="$h"]
  :if ($leaseBound = "1") do={
    :delay 1
    /ip dns static add comment="$leaseComment" address="$leaseActIP" name="$h" ttl="$dnsTtl"
  }
}

Other Scripts

As mentioned, there are also other scripts with similar functionality – each with a bit different implementation. Maybe some other script will fit your needs better if this one did not, so here are some that I stumbled upon:


21 Comments

Gavin · June 3, 2020 at 03:03

There’s a bug in this script. If you set dnsAlwaysNonfqdn to 0, then the dns entry that’s added is never a FQDN

    Pessoft · June 5, 2020 at 23:10

    Hi Gavin,

    Variable dnsAlwaysNonfqdn is used only if dnsDomain variable is also set. In such case, if dnsAlwaysNonfqdn is 0 then script adds DNS only entry with additional dnsDomain suffix. If dnsAlwaysNonfqdn is 1 then script adds DNS entry with dnsDomain suffix and also without it. What entry it really is, depends on the source of the name. If source of the name is lease-hostname, then it comes from the client itself and client decides if it send FQDN or non-FQDN hostname. Main use case of dnsAlwaysNonfqdn is that you have some hosts which send non-FQDN hostnames to DHCP and you want to register in DNS both entries – with and without DNS suffix – so they are reachable by short and also full hostname.

    Pessoft · June 23, 2020 at 00:16

    And there was a bug indeed. Thank you.

Tim · July 12, 2020 at 23:34

Thanks for the script! Where is $leaseBound set? Is this a ‘magic’ variable set for DHCP scripts?

    Pessoft · July 15, 2020 at 20:37

    Hi Tim, yes, you are right. Variables $leaseBound, $leaseServerName, $leaseActMAC, $leaseActIP, $lease-hostname and $lease-options are global variables that are pre-set with lease related information by RouterOS when lease script is called. It is easy to distinguish what each variable contains by variable name, but you can also find more specific information in lease-script property on Mikrotik Wiki.

Tom · July 14, 2020 at 03:45

Hi, Thank you for the great script! I notice some of the other dhcp to dns scripts have some kind of character checker… Does yours do that? Is it important? Thanks again!

    Pessoft · August 3, 2020 at 21:07

    Hi Tom, my script does not have a character checker. But it is a good point and I will consider that. Reason for it is that any input which is not under your control must be sanitized to prevent getting unexpected input, which could cause unintended activity. If DNS entries are created based on what client sends as hostname ( which is also default behavior of my script ), then someone can exploit it and send some unexpected input to the script. This can be prevented by mentioned character checker or by using trusted source ( like fixed hostnames in lease comments for example ).

Geeom · July 17, 2020 at 15:50

Is the script working on rOS 6.47(.1)?

I pasted the script “as is” but no entry appear in DNS Static window upon renewing client DHCP lease.

    Pessoft · September 22, 2020 at 23:37

    Hi, I did not test the script specifically on this version, but it was running on versions before and after 6.47(.1), so it should work your version too. Script is triggered on creation and deletion of DHCP lease.

Tim · August 2, 2020 at 11:04

What is the :delay 1 for in the end of the script?

The script works intermittently for me, and I fail to see why it sometimes does or doesn’t. One cause could be is that I use dns-based Adblock which heavily uses static dns entries and makes queries slow (~5s), such that the 1s delay might not be enough to do whatever it’s supposed to do.

    Pessoft · August 3, 2020 at 20:58

    It sometimes happened to me when disconnection of the client was followed by immediate re-connection of the client, script was executed twice ( as it should ), but disconnection related script execution somehow occurred after connection related script execution and this resulted in deleted DNS entries. I’ve therefore added a 1 second delay to make sure that connection run always wins.

ilium007 · September 12, 2020 at 03:52

Didn’t work on routerOS 7beta2

ilium007 · September 12, 2020 at 04:01

Just realised the script does not work for DHCP leases that are static assigned.

ilium007 · September 12, 2020 at 10:03

My bad – script works fine on routerOS 7beta2. Thanks!

    Pessoft · September 12, 2020 at 17:22

    Hi. Thank you too for feedback from 7beta2 😉

Alex22 · September 14, 2020 at 23:09

Thanks for this script; Seems to work on 6.47.3 but only for new/changed Leases. A migration path for existing systems would be fine 😉 Can i trigger the script for all existing leases?

Thanks!

    Pessoft · September 22, 2020 at 23:33

    Hello Alex, this script is intended to by used for new DHCP leases and it is being triggered by creation and deletion of DHCP leases. If there is some existing solution, which needs to be migrated, it must be done separately.

MatejK · November 29, 2020 at 23:08

First a big THANK YOU for your work! It took me to way long to figure out that MikroTik doesn’t add DHCP leases to the internal DNS…

MY QUESTION: does this adding & removing of static DNS entries also mean that every time the changes get stored in FLASH memory and so degrade it faster?

    Pessoft · November 30, 2020 at 18:31

    Hi Matejk, static DNS entries are part of the configuration, which is stored on the router’s file system. So yes, static DNS entries might affect life of your FLASH memory if such is used for configuration storage. Of course all depends on how often DNS entries are being modified.

      MatejK · November 30, 2020 at 22:15

      Thanks for confirming my thinking about the more frequent writes of the configuration to FLASH storage. Do you know of any plans (maybe in the mythical version 7) to add and entry only in RAM, a sort of “dynamic” static entry. Since it’s the routers DHCP server assigning the addresses they are only relevant with the router powered on. But maybe there are bigger issues to solve before this one 🙂

        Pessoft · December 1, 2020 at 22:10

        I’m not aware of such plans, but I do not watch Mikrotik so closely 😉 But I don’t think it will be the case anyway, because if there is a need for reliable storage medium, it is usually better to install RouterOS on non-FLASH storage.

Comments are closed.