Sync Address List from DNS Lookup Results - MikroTik Script RouterOS

This script might come in handy if you're trying to use domain names in firewall rules. To use this script you might write a script like the one below and schedule it. Be sure to declare three globals first : ListName, Servers, and Done. ListName and Servers are needed so that we can simulate an argument list. Done is necessary so that independent calls of the script don't step on each other since they share the same globals.

This will work with CNAMEs and follow them until we get A Records.

:global ListName google_voice
:global Servers {"talkr.l.google.com"}
/system script run dnsToAddressList

This is the dnsToAddressList script:

:global ListName
:global Servers
:global Done
#has $Done been initialized?
:if ([:typeof $Done] != "boolean") do={
  :set Done true;
}
#make sure previous runs have finished
while (!$Done) do={
  :nothing;
}
#block any other runs
:set Done false;
#delete old address lists
:foreach aListItem in=[/ip firewall address-list find list=$ListName] do={
  /ip firewall address-list remove $aListItem;
}
:foreach aServer in=$Servers do={
#force the dns entries to be cached
  :resolve $aServer;

  :foreach dnsRecord in=[/ip dns cache all find where (name=$aServer)] do={
#if it's an A records add it directly
    :if ([/ip dns cache all get $dnsRecord type]="A") do={
       /ip firewall address-list add list=$ListName address=[/ip dns cache all get $dnsRecord data] comment=$aServer;
    }
#if it's a CNAME follow it until we get A records
    :if ([/ip dns cache all get $dnsRecord type]="CNAME") do={
      :local cname;
      :local nextCname
      :set cname [/ip dns cache all find where (name=$aServer && type="CNAME")];
      :set nextCname [/ip dns cache all find where (name=[/ip dns cache all get $cname data] && type="CNAME")];

      :while ($nextCname != "") do={
          :set cname $nextCname;
          :set nextCname [/ip dns cache all find where (name=[/ip dns cache all get $cname data] && type="CNAME")];
        }
#add the a records we found
    :foreach aRecord in=[/ip dns cache all find where (name=[/ip dns cache all get $cname data] && type="A")] do={
      /ip firewall address-list add list=$ListName address=[/ip dns cache all get $aRecord data] comment=$aServer;
      }
    }
  }
}
#allow other scripts to call this
:set Done true