Feature Request: DNS-Linked Firewall Enforcement (Resolve-or-Block Mode)

Overview

I’d like to request a new RouterOS feature that allows traffic enforcement based on successful DNS resolution.

In essence, the firewall should allow forwarding only to destinations that have been successfully resolved via the router’s DNS cache or internal resolver.

If a domain cannot be resolved (NXDOMAIN, timeout, or blocked entry), the associated traffic should be automatically dropped.

This would give administrators complete DNS-level control over outbound traffic—an important capability for ISPs, enterprise networks, and secure environments where name resolution directly governs allowed destinations.

Proposed Functionality

1. Concept

  • The router acts as the authoritative DNS resolver for the LAN.

  • If a hostname resolves successfully, its IP (A/AAAA record) is added to a special dynamic address list (e.g., `resolved-list`).

  • Firewall rules can then reference this list:

    /ip firewall filter
    add chain=forward dst-address-list=resolved-list action=accept
    add chain=forward action=drop

  • If DNS resolution fails or is blocked, the IP never enters the list, so packets are dropped.

2. Optional Mode
/ip dns
set resolve-enforcement=yes

  • When enabled, RouterOS only allows outbound connections to IPs associated with successful DNS lookups made through the router.

  • This mode can be per-interface or global.

3. Internal Implementation

  • RouterOS already maintains a full DNS cache table.

  • The feature could simply expose the cache-linked IPs to a dynamic address list at kernel level.

  • Optionally, use a new `/ip firewall match=dns-resolved` condition integrated into nftables/ipset (as RouterOS v7 already runs on Linux kernel 5.x+).

  • Suggested kernel-level approach:

  • For every DNS cache entry, push resolved IPs to a kernel-managed nftables set (type `ipv4_addr`/`ipv6_addr`).

  • TTL synchronization = DNS TTL (automatic removal upon expiry).

  • Hook existing DNS resolver process to maintain this set.

  • This avoids user-space scripts and leverages existing nftables mechanisms for high performance.

4. Implementation Options

Option 1: Address-List Synchronization (Simple Implementation)

  • Mirror `/ip dns cache` entries to a dynamic `resolved-list`.

  • TTL synchronization ensures entries expire naturally.

  • Advantage: straightforward to implement using existing address-list logic.

  • Limitation: large address-lists may increase memory usage and CPU cost on busy gateways.

Option 2: New Firewall Option — `match-dns` (Preferred)

To minimize address-list overhead, add a direct DNS verification flag to the firewall filter:

/ip firewall filter
add chain=forward action=accept match-dns=yes

5. Possible CLI Design

/ip dns control
add name="resolved" list=resolved-list ttl-sync=yes

/ip firewall filter
add chain=forward dst-address-list=resolved-list action=accept
add chain=forward action=drop

or a new match condition:

/ip firewall filter
add chain=forward match-dns=yes action=accept

Use Cases

  • Strict outbound policy – Prevents any host from connecting to IPs that haven’t passed DNS validation.

  • DNS-driven allowlists/denylists – Allows micro-segmentation and per-domain policy enforcement.

  • Malware and data exfiltration prevention – Stops direct IP-based connections to C2 servers.

  • ISP / corporate gateway control – Enforces “if you can’t resolve, you can’t connect,” eliminating leaks via hardcoded IPs.

Why This Matters

  • Competing platforms (Linux + dnsmasq + nftables) already achieve this natively using `ipset=/#/setname`.

  • MikroTik could integrate similar logic internally, without external scripts or schedulers.

  • It would greatly simplify compliance, auditing, and threat-mitigation for MikroTik-based ISP and enterprise deployments.

Summary

Requested Feature:

Add native RouterOS support for DNS-to-firewall synchronization—allowing traffic only to successfully resolved IPs (resolve-or-block mode).

Technical Suggestion:

Expose `/ip dns cache` IPs as a dynamic address list or nftables set; TTL-synchronized and directly usable in `/ip firewall filter`.

Thank you for considering this feature. This enhancement aligns perfectly with MikroTik’s firewall philosophy—lightweight, deterministic, and controllable directly from RouterOS, without needing custom scripts.

While I agree that this could be an useful feature ... you are aware that this would be a fight against DoH ... which is s feature backed by largest IT corporations and endorsed by many users (for various reasons and I personally don't agree with many of them).

You can already replicate the functionality with the address list using static FWD record. Here is an example using Cloudflare DoH as upstream resolver:

/ip dns forwarders
add doh-servers=https://cloudflare-dns.com/dns-query name="Cloudflare DoH"
/ip dns
set address-list-extra-time=1m allow-remote-requests=yes
/ip dns static
add address-list=RESOLVED forward-to="Cloudflare DoH" regexp="[a-zA-Z0-9-]+\\.[a-zA-Z]+" type=FWD
add address=2606:4700::6810:f8f9 name=cloudflare-dns.com type=AAAA
add address=2606:4700::6810:f9f9 name=cloudflare-dns.com type=AAAA
add address=104.16.248.249 name=cloudflare-dns.com type=A
add address=104.16.249.249 name=cloudflare-dns.com type=A

And here is a test with ping to some domains. As you can see the RESOLVED address list is correctly populated for IPv4 and IPv6:

Can you do the same when ROS is using traditional DNS forwarders?

But IMO it doesn't help when client device (or even user-land software running on client device) uses its own DoH connection ... which is what my previous post is about.

Yes, I agree that it doesn't help when the client devices use DoH / DoT (I always turn on Private DNS on my Android devices, for example). Of course, the admin can try to block port 853 as well as use this list to block some known DoH providers.

Currently, it only works when the forwarder is using DoH. It's probably a bug in RouterOS though:

Thanks guys, it really helps a lot, Its working!!! Good bye hackers. I will be using an external secure DNS with this one so finally i manage the domains that are allowed. A powerful blocker without expensive firewall/ software solutions.

/ip dns static
add address-list=RESOLVED regexp="[a-zA-Z0-9-]+\.[a-zA-Z]+" type=FWD

/ip firewall filter
add action=fasttrack-connection chain=forward comment="allow established related connections" connection-state=established,related disabled=yes hw-offload=yes
add action=accept chain=forward comment="allow established related connections" connection-state=established,related
add action=drop chain=forward comment="drop invalid connections" connection-state=invalid
add action=accept chain=forward dst-address-list=ROUTER src-address-list=MGMT
add action=accept chain=forward dst-address-list=CCTV src-address-list=CCTV-ALLOWED
add action=drop chain=forward dst-address-list=bogons
add action=drop chain=forward dst-port=53 protocol=udp
add action=drop chain=forward dst-port=53 protocol=tcp
add action=accept chain=forward connection-state=new dst-address-list=RESOLVED out-interface-list=WAN protocol=tcp src-address-list=NAT
add action=accept chain=forward connection-state=new dst-address-list=RESOLVED out-interface-list=WAN protocol=icmp src-address-list=NAT
add action=accept chain=forward connection-state=new dst-address-list=RESOLVED out-interface-list=WAN protocol=udp src-address-list=NAT
add action=drop chain=forward comment="DROP everything"