# Sync Address List with DNS Cache - MikroTik Script RouterOS

    This script will update an address list from a given DNS cache search. This address list can then be used for example in Firewall settings.

    # Sync an address list with DNS cache
    # Version: 1.0.0
    # This script currently only works with type A and non-static DNS records.
    # If no matching DNS records are found:
    # the address list is removed.
    # If matching DNS records are found:
    # if an address list entry is NOT found in search result, it is removed.
    # if an address list entry IS found in search result, is not modified.
    # if a search result is NOT found in address list, it is added.
    #
    # Search string format:
    # "(:|=|~)"
    # :   match string anywhere
    # =  match string exactly (case sensitive)
    # ~  match string using regular expression (requires ROS >= v3.23)
    #
    # Example:  To search all records containing 'google.com':
    # :local search ":google.com"
    #
    # To search all records ending with 'microsoft.com':
    # :local search "~microsoft\\.com\$"
    :local search ":google.com"
    # The prefix of address list ("" = none)
    :local listprefix "DNSCache_"
    # Internal processing...
    :local IPs ""
    :local Names ""
    :local sop [:pick [:tostr $search] 0 1]
    :set search [:pick [:tostr $search] 1 [:len [:tostr $search]]]
    /ip dns cache all {
       :local findex; :local property; :local value; :local name; :local type; :local data
       :local sfound 0
       :foreach rule in=[print detail as-value where static=no] do={
          :set name ""; :set type ""; :set data ""

          :foreach item in=$rule do={
             :set findex [:find [:tostr $item] "="]
             :set property [:pick [:tostr $item] 0 $findex]
             :set value [:pick [:tostr $item] ($findex + 1) [:len [:tostr $item]]]

             :if ($property = "name") do={ :set name $value }
             :if ($property = "type") do={ :set type $value }
             :if ($property = "data") do={ :set data $value }
          }
    # Search DNS cache name using specified operator
          :set sfound 0
          :if ($sop = ":") do={
             :if ([:find [:tostr $name] [:tostr $search]] != "" && $type = "A") do={ :set sfound 1 }
          }
          :if ($sop = "=") do={
             :if ([:tostr $name] = [:tostr $search] && $type = "A") do={ :set sfound 1 }
          }
          :if ($sop = "~") do={
             :if ([:tostr $name] ~ [:tostr $search] && $type = "A") do={ :set sfound 1 }
          }
          :if ($sfound = 1) do={
    #         :put ("Found " . $name . " -> " . $data)
             :set IPs ($IPs . $data . ",")
             :set Names ($Names . $name . ",")
          }
       }
    # /ip dns cache all
    }
    :put ("DNS cache search found " . [:len [:toarray $IPs]] . " match(es) for '" . $search . "'")
    # Search through IPs and add to address list
    /ip firewall address-list {
       :local findex; :local listaddr; :local IPsFound ""

       :put ("Searching address list '" . ($listprefix . [:tostr $search]) . "'...")
       :foreach l in=[find list=($listprefix . [:tostr $search])] do={
          :set listaddr [get $l address]
          :if ([:len [:find [:toarray $IPs] [:toip $listaddr]]] = 0) do={
             :put ("   " . $listaddr . " not found in search, removing...")
             remove $l
          } else={
    #         :put ($listaddr . " found address in IPs")
             :set IPsFound ($IPsFound . $listaddr . ",")
          }
       }
    # Add remaining records to address list
       :set findex 0
       :foreach ip in=[:toarray $IPs] do={
          :if ([:len [:find [:toarray $IPsFound] [:toip $ip]]] = 0) do={
             :put ("   Adding address " . $ip)
             add list=($listprefix . $search) address=[:toip $ip] comment=([:pick [:toarray $Names] $findex]) disabled=no
          }
          :set findex ($findex + 1)
       }
    # /ip firewall address-list
    }
    Credit: wiki.mikrotik.com