Skip to main content

Setup guide

MikroTik adlist blocklist of malicious domains, fetched with your API key

RouterOS fetch sends HTTP Basic with its first request, so the router downloads the full isMalicious list itself, then loads the file as a DNS adlist. A scheduled script refreshes it.

No credit card required · Free API key

Data path
  1. isMalicious

    api.ismalicious.com

    blocklist-domains-c2.txt

    Rebuilt every 12 h

  2. MikroTik

    Step 5

    Download the list and add the adlist

  3. Make the router your clients’ resolver

    Step 4
On this page08

What you get

A DNS adlist takes plain domain files and keeps every name in the DNS cache, about 75 bytes each. The category lists below fit a router; the 2 million critical domains do not.

ListEntriesRebuiltPlans
blocklist-domains-c2.txtDefault adlist: command-and-control domains reported by C2 trackers.about 22,000every 12 hBasic, Pro, and Enterprise
blocklist-domains-ransomware.txtDomains in the ransomware category, whatever their level.about 3,600every 12 hBasic, Pro, and Enterprise
blocklist-domains-cryptomining.txtDomains in the cryptomining category, whatever their level.about 6,100every 12 hBasic, Pro, and Enterprise

Entries rounded from the build of ; each list is rebuilt every 12 hours. Today’s counts are public and need no key.

What each plan receives

  • FreeFree account, or no key: the first 10% of each list, marked X-Blocklist-Version: lite.
  • Basic, Pro, and EnterpriseBasic, Pro, and Enterprise: every list in full.
  • Pro and EnterpriseTAXII 2.1 collections, for platforms that read STIX indicators: Pro and Enterprise.

Compare plans

What a download returnsHTTP

GET https://api.ismalicious.com/blocklist/download/blocklist-domains-c2.txt

Full list or 10% sample

FieldBasic, Pro, and EnterpriseFree
X-Blocklist-Version:fulllite
X-Blocklist-Percentage:10010
Total entries:<COUNT><COUNT> (Lite Version - 10% of <TOTAL>)

First lines of the file

# IsMalicious.com Blocklist - Domains (All Levels)
# Format: Plain
# Generated: <BUILD_TIME>
# Total entries: <COUNT>
# Update frequency: every 12 hours
# Category: C2
# Threat level: All Levels
# Website: https://ismalicious.com
# © <YEAR> IsMalicious (compilation). Licensed to the downloading account under https://ismalicious.com/terms; redistribution of the compilation prohibited. Third-party entries remain under their providers' licences — see https://ismalicious.com/sources.
# Filtered by category: c2
#

Values in angle brackets are set by each build.

Prerequisites

  • RouterOS 7.16 or later: DNS adlists arrived in 7.15, and 7.16 fixed how fetch handles a 401.
  • Fetch and the scheduler allowed by the device mode: home routers that ship with RouterOS 7.17 or later come in home mode, which turns both off (step 2).
  • The router’s clock set by NTP: certificate checks compare the certificate dates with it.
  • An isMalicious API key and secret, from Account › API access.
  • Outbound HTTPS (TCP 443) over IPv4 from MikroTik to api.ismalicious.com, which has no IPv6 address.

Set it up

  1. Copy your API key and secret

    Open Account › API access and copy the API Key and the API Secret. The full list needs a Basic, Pro, or Enterprise plan; a Free key, or a lapsed plan, loads the 10% sample.
  2. Allow fetch and the scheduler

    Check the device mode with /system/device-mode/print. If fetch or scheduler is no, run /system/device-mode/update fetch=yes scheduler=yes, then press the reset or mode button, or unplug the power, within 5 minutes: the router applies the change only after that confirmation.
    Device mode (home routers, 7.17+)RouterOS
    # Home routers that ship with RouterOS 7.17 or later come in home mode,
    # which turns off fetch and the scheduler. Check:
    /system/device-mode/print
    # If fetch or scheduler shows no:
    /system/device-mode/update fetch=yes scheduler=yes
    # then press the reset or mode button, or unplug the power, within 5 minutes.
  3. Trust the Let’s Encrypt roots

    RouterOS 7.19 and later have a built-in trust store that fetch uses. Run the manual fetch under Verify first: if it ends with status: finished, skip this step; if it fails with no trusted CA certificate found, import both roots, then compare their fingerprints with the values below, since that first download cannot be verified. That is always needed on 7.15 to 7.18, and on hAP lite, hAP lite TC and hAP mini before 7.23.3.
    Let’s Encrypt roots, when the trust store lacks themRouterOS
    # Only when the manual fetch under Verify fails with "no trusted CA certificate found".
    /tool/fetch url="https://letsencrypt.org/certs/isrgrootx1.pem" dst-path=isrgrootx1.pem
    /tool/fetch url="https://letsencrypt.org/certs/isrg-root-x2.pem" dst-path=isrg-root-x2.pem
    /certificate/import file-name=isrgrootx1.pem trusted=yes
    /certificate/import file-name=isrg-root-x2.pem trusted=yes
    
    # The download above cannot be verified yet: compare the SHA-256 fingerprints.
    /certificate/print detail where common-name~"^ISRG Root X"
    # ISRG Root X1  96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6
    # ISRG Root X2  69729b8e15a86efc177a57afb7171dfc64add28c2fca8cf1507e34453ccb1470
    # If either differs: /certificate/remove [find common-name~"^ISRG Root X"]
  4. Make the router your clients’ resolver

    Allow DNS requests to the router and raise the DNS cache, which holds the adlist names: 8 MiB leaves room for the C2 list. Clients must use the router as their resolver: hand it out through DHCP (/ip/dhcp-server/network/set … dns-server= the router’s address); a client with its own resolver or DNS over HTTPS bypasses the adlist. Without the default firewall, add the rules below so the router does not answer DNS from the internet.
    ResolverRouterOS
    /ip/dns/set allow-remote-requests=yes cache-size=8192
    
    # Only without the default firewall, which already drops DNS from the WAN.
    # Put these above any rule that accepts it (place-before):
    /ip/firewall/filter/add chain=input in-interface-list=WAN protocol=udp dst-port=53 action=drop comment="drop DNS from WAN"
    /ip/firewall/filter/add chain=input in-interface-list=WAN protocol=tcp dst-port=53 action=drop comment="drop DNS from WAN"
    /ipv6/firewall/filter/add chain=input in-interface-list=WAN protocol=udp dst-port=53 action=drop comment="drop DNS from WAN"
    /ipv6/firewall/filter/add chain=input in-interface-list=WAN protocol=tcp dst-port=53 action=drop comment="drop DNS from WAN"
  5. Download the list and add the adlist

    Fetch the list into a file with the API key as user and the API secret as password, with check-certificate=yes, then add the file as an adlist. An adlist URL takes no credentials, which is why the file comes first.
    First loadRouterOS
    /tool/fetch url="https://api.ismalicious.com/blocklist/download/blocklist-domains-c2.txt" \
        user="<API_KEY>" password="<API_SECRET>" check-certificate=yes \
        dst-path=ismalicious-c2.txt
    /ip/dns/adlist/add file=ismalicious-c2.txt
  6. Refresh it on a schedule

    • Add the refresh as a script, run at startup and every 6 hours: it downloads the list again, then removes and re-adds the adlist, so the new file is read.
    • A failed download (an HTTP error, a timeout, a certificate error) stops the script before it touches the adlist.
    • A 200 answer replaces the names whatever it holds, the 10% sample included: check name-count after any plan or key change.
    • On a router with a flash folder, write the file under flash/: elsewhere it sits on a RAM disk and is lost at reboot.
    • The 90-second delay at startup may be short for a PPPoE or LTE uplink.
    Refresh script and scheduleRouterOS
    /system/script/add name=ismalicious-dns policy=ftp,read,write,test source={
    /tool/fetch url="https://api.ismalicious.com/blocklist/download/blocklist-domains-c2.txt" \
        user="<API_KEY>" password="<API_SECRET>" check-certificate=yes \
        dst-path=ismalicious-c2.txt
    /ip/dns/adlist/remove [find file="ismalicious-c2.txt"]
    /ip/dns/adlist/add file=ismalicious-c2.txt
    }
    /system/scheduler/add name=ismalicious-dns-boot start-time=startup interval=0s \
        policy=ftp,read,write,test on-event=":delay 90s; /system/script/run ismalicious-dns"
    /system/scheduler/add name=ismalicious-dns-6h start-time=00:20:00 interval=6h \
        policy=ftp,read,write,test on-event="/system/script/run ismalicious-dns"

Verify it works

  • /ip/dns/adlist/print shows name-count, the names imported, and match-count, the queries blocked.
  • name-count matches the list’s count in /blocklist/stats, give or take one rebuild. About a tenth of it is the 10% sample.
  • A manual fetch of the list ends with status: finished.
  • The fetch log topic records each download and its errors.
ChecksRouterOS
# Names imported (name-count) and queries blocked (match-count):
/ip/dns/adlist/print

# The download itself, outside the schedule, without keeping a copy:
/tool/fetch url="https://api.ismalicious.com/blocklist/download/blocklist-domains-c2.txt" \
    user="<API_KEY>" password="<API_SECRET>" check-certificate=yes \
    output=none

Troubleshooting

not allowed by device-mode

The router is in home mode, which turns off fetch and the scheduler. Run the device-mode update of step 2 and confirm it with the reset or mode button, or a power cycle, within 5 minutes.

The fetch fails with a 401

The key or the secret is wrong or incomplete. The script stops and the adlist keeps its names. The response body reads “Blocklist not found or empty”; trust the status code. Copy both values again from Account › API access: regenerating the key there invalidates the old pair.

name-count is about a tenth of the list

No credential reached the server, or the plan is Free or lapsed: past due, unpaid, canceled, incomplete or paused counts as Free. The downloaded file’s Total entries line then says Lite Version.

adlist read: max cache size reached

Raise cache-size, then remove and re-add the adlist: raising it afterwards does not complete the list.

Header lines in the adlist

The adlist ignores lines that start with #, so the header is not loaded. Never give it an -adguard or -dnsmasq file: it reads plain names or hosts lines.

no trusted CA certificate found

Set the clock first. Then import ISRG Root X1 and X2 (step 3): always on 7.15 to 7.18, and on hAP lite, hAP lite TC and hAP mini before 7.23.3. From 7.19, check that fetch still uses the built-in trust store: the setting is builtin-trust-anchors on 7.19 and 7.20, builtin-trust-store from 7.21.

not enough permissions (9)

The script or the scheduler entry lacks a policy: fetch needs ftp and test, and the adlist commands read and write.

403 from ismalicious.com

The ismalicious.com edge refuses some sources. Use api.ismalicious.com.

Limits

  • No IP address list loader is published yet. RouterOS cannot load a plain list into an address list without a script that adds each line, and the one we drafted has not been run on a router.
  • An adlist blocks the exact names only, not their subdomains, and answers A and AAAA queries only: TXT, MX and HTTPS records still resolve upstream.
  • The API secret sits in the script in clear text, and an export prints it: restrict who can read the configuration.
  • No CIDR, no .rsc and no other RouterOS format is served: the adlist reads the plain list.
  • The 10% sample is the first tenth of an unsorted file, not the riskiest tenth.

Questions

Can RouterOS fetch a blocklist with an API key?

Yes. /tool/fetch takes user and password and sends them as HTTP Basic with the first request: the API key is the user, the API secret the password. The DNS adlist itself takes no credentials, so fetch the list into a file and load the file.

Can I load the IP lists into a MikroTik address list?

Not with a published script yet. An address list needs a script that adds each line, and the loader we drafted has not been tested on a router, so this guide covers the DNS adlist only.

Does the adlist block subdomains?

No. A RouterOS adlist blocks the exact names it holds, not their subdomains.

How often should the router refresh the list?

At startup and every 6 hours, as the schedule in this guide does. The lists are rebuilt every 12 hours.

How large should the DNS cache be?

Each adlist name takes about 75 bytes of DNS cache, and the default cache is 2 MiB. The C2 list needs about 1.6 MiB on its own, so the guide raises the cache to 8 MiB.

Get Started

Ready to get started?

No credit card required · Free API key