Back to blog

MikroTik / RouterOS  ·  Security  ·  October 2026

MikroTik DNS
DoH & FQDN Filtering

Unlike a Cisco router, RouterOS is a genuinely capable DNS server: a caching resolver, static entries with regex and split-horizon, native DNS-over-HTTPS, and the thing no one else has quite like this — FQDN firewall address-lists that resolve names into live filter rules. It's also one allow-remote-requests away from being an open DDoS amplifier. The Cisco twin is Cisco IOS: DNS & Name Services.

MikroTik DNS DoH FQDN Security

RouterOS ships a real caching resolver, and with RouterOS 7 it does DNS-over-HTTPS natively, keeps static records with regex matching, and can forward specific zones to internal servers (split-horizon). That makes a MikroTik edge box a legitimate DNS layer for a small site — not the branch-only compromise a Cisco router's ip dns server is.

Two RouterOS-specific superpowers are worth the post on their own: FQDN address-lists, where the firewall resolves a domain name and tracks its IPs so you can filter by name; and adlist (7.15+), DNS-level ad/tracker blocking built into the resolver. Both lean security, which is how this post is framed. First, the mistake that undoes all of it: turning the resolver on without a firewall.

Prerequisites
CLIENT query ROUTEROS DNS adlist → block static → answer cache → answer miss → DoH DoH UPSTREAM https:// resolver FIREWALL FQDN address-list :53 (inside only) TLS resolved IPs

01

The Caching Resolver — And the Open-Resolver Trap

Enabling the resolver is one line. Enabling it for the whole internet is the same line with one wrong flag — and it makes you a DNS reflection amplifier. Turn it on, then immediately close port 53 to the outside.

RouterOS — resolver + the firewall rule that must come with it
# Cache resolver. allow-remote-requests=yes lets LAN clients use it...
[admin@edge] > /ip/dns/set servers=1.1.1.1,9.9.9.9 allow-remote-requests=yes \
     cache-size=4096KiB cache-max-ttl=1d

# ...but that same flag answers the WAN too. Close 53 from outside NOW.
[admin@edge] > /ip/firewall/filter add chain=input in-interface-list=WAN \
     protocol=udp dst-port=53 action=drop comment="no open resolver"
[admin@edge] > /ip/firewall/filter add chain=input in-interface-list=WAN \
     protocol=tcp dst-port=53 action=drop
⚠ Gotcha — allow-remote-requests Without a Firewall = Amplifier

This is the single most common MikroTik misconfiguration on the public internet. allow-remote-requests=yes doesn't mean "LAN only" — it means "answer anyone who can reach UDP 53". A short query returns a large answer, so an attacker spoofs a victim's source IP and your router floods them: classic DNS reflection/amplification. Your box ends up in abuse feeds and shunned. The flag is fine; it must always ship with an input-chain rule dropping 53 from the WAN interface list. Verify from outside with dig @your-public-ip google.com — it should time out.

02

Static Records, Regex & Split-Horizon

RouterOS static DNS does more than A records: CNAME, TXT, regex-matched wildcards, and FWD entries that forward a specific zone to an internal server — split-horizon without a second box.

RouterOS — static entries and conditional forwarding
# Plain A record, and an AAAA.
[admin@edge] > /ip/dns/static add name=nas.lab.lan address=10.0.0.20
[admin@edge] > /ip/dns/static add name=nas.lab.lan type=AAAA address=2001:db8::20

# Regex wildcard: everything under internal.lab.lan to one host.
[admin@edge] > /ip/dns/static add regexp=".*\\.internal\\.lab\\.lan" address=10.0.0.10

# Split-horizon: forward one zone to the internal AD/DNS server,
# everything else still goes to the normal upstream.
[admin@edge] > /ip/dns/static add name=corp.lan type=FWD forward-to=10.0.0.5 \
     match-subdomain=yes
⚠ Gotcha — Regex Entries Are Evaluated on Every Query

A regexp= static entry is tested against every name the resolver sees, in order, before the cache answers. A handful is fine; dozens of greedy patterns measurably add latency to all resolution. Prefer exact name= entries and match-subdomain=yes where you can, and keep regex for the cases that genuinely need it. Anchor your patterns (\\.lab\\.lan$) so they don't match more than you meant — the same unanchored-regex trap that bites RouterOS scripting.

03

DNS-over-HTTPS — Done So It Actually Validates

DoH encrypts the router's own upstream lookups so the ISP can't see or tamper with them. The trap is that it silently works without certificate validation — which defeats the point. Import the CA and verify.

RouterOS — DoH with real certificate validation
# Fetch the CA bundle Mozilla publishes and import it, so the router can
# actually verify the DoH endpoint's certificate.
[admin@edge] > /tool/fetch url="https://curl.se/ca/cacert.pem" mode=https
[admin@edge] > /certificate/import file-name=cacert.pem passphrase=""

# Point DoH at a resolver and REQUIRE cert verification.
[admin@edge] > /ip/dns/set use-doh-server="https://cloudflare-dns.com/dns-query" \
     verify-doh-cert=yes
⚠ Gotcha — DoH Needs the Clock, and the Chicken-and-Egg It Creates

Certificate validation checks the cert's validity dates, so a router with a wrong clock rejects a perfectly good DoH cert — or, worse, you disable verify-doh-cert to "make it work" and now you have unauthenticated DoH, which is theatre. But NTP often resolves its server by name, which needs DNS, which you've just moved to DoH. Break the loop: set NTP by IP address (or use a static DNS entry for the NTP host), let the clock sync over plain DNS, then enable DoH. See the hardening post for the boot-order discipline.

04

FQDN Address-Lists & Adlist Blocking

Two RouterOS features that only exist because DNS and the firewall live in the same box: filter traffic by domain name, and block ads/trackers at resolution time.

An FQDN address-list entry stores a name instead of an IP. The router resolves it and keeps the address-list populated with whatever that name currently points at — so a firewall rule matching that list follows the domain as its IPs change. Useful for allowing a SaaS endpoint or blocking a known-bad host by name.

RouterOS — filter by domain name
# The firewall resolves this name and tracks its IPs automatically.
[admin@edge] > /ip/firewall/address-list add list=blocked address=tracker.example.com

# Drop forward traffic to anything that name resolves to.
[admin@edge] > /ip/firewall/filter add chain=forward dst-address-list=blocked \
     action=drop comment="FQDN-based block"
RouterOS 7.15+ — DNS-level ad/tracker blocking
# Load a hosts-format blocklist; matching names resolve to 0.0.0.0.
[admin@edge] > /ip/dns/adlist add url="https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" \
     ssl-verify=yes
[admin@edge] > /ip/dns/adlist/reload
[admin@edge] > /ip/dns/adlist/print          # shows match-count per list
💡 Pro Tip — Where Adlist Belongs (and Doesn't)

Adlist is a real win for a guest or family network — fewer trackers, less malware-adjacent traffic, no client agent. But it eats RAM proportional to list size, so don't load a million-entry list onto a 16 MB hEX. On small boxes, keep lists modest or push blocking to a dedicated Pi-hole/AdGuard and let the router just forward. And remember clients can bypass it by hard-coding their own DoH (8.8.8.8, 1.1.1.1 in the browser) — if you need enforcement, also redirect or block outbound 53/443-to-known-DoH, covered in the firewall post.

05

Verify Safe to Run

RouterOS — read the cache and confirm behaviour
[admin@edge] > /ip/dns/print                    # servers, DoH, cache-used
[admin@edge] > /ip/dns/cache/print              # live cached records
[admin@edge] > /ip/dns/cache/flush              # clear when testing
[admin@edge] > /ip/firewall/address-list/print where list=blocked  # FQDN → IPs
[admin@edge] > /log/print where topics~"dns"
SettingWhy it matters
allow-remote-requests=yesNeeded for LAN clients — must pair with a WAN drop on 53
verify-doh-cert=yesWithout it, DoH is encrypted but unauthenticated — no integrity
type=FWD + match-subdomainSplit-horizon: send one zone to the internal server
address-list = FQDNFirewall follows a domain's live IPs
adlist (7.15+)Resolver-level blocking; RAM-bound, bypassable by client DoH

Takeaways

  1. allow-remote-requests=yes always ships with a firewall rule dropping 53 from the WAN — the open-resolver mistake makes you a DDoS amplifier.
  2. Prefer exact and match-subdomain static entries over regex; anchor any regex you must use, because it runs on every query.
  3. DoH only counts with verify-doh-cert=yes and an imported CA — and set NTP by IP first to escape the clock/DNS boot loop.
  4. FQDN address-lists let the firewall follow a domain's IPs — allow a SaaS endpoint or block a host by name.
  5. Adlist is great for guest/family nets but RAM-bound and client-bypassable; offload to Pi-hole on small boxes.

Want DNS that filters, encrypts, and can't be abused?

A resolver layer done properly — DoH upstream, ad/tracker blocking, FQDN firewalling, and no open-resolver exposure — makes a network quieter and safer without touching a single endpoint. I deploy this across MikroTik and Cisco sites. Let's design yours.

Book a Discovery Call →