Networks and Cybersecurity 16 min read

Route Certain Domains into a VPN with MikroTik

Transform DNS responses into a dynamic list of addresses, mark the corresponding connections, and forward them into a VPN table without diverting the entire network.

Routing a domain into a VPN seems simple : it would be enough to write its name in a rule. But a router does not transmit names, it transmits packets to IP addresses. The same service can change addresses, use several subdomains, or rely on a CDN shared with other sites. The configuration must therefore properly link DNS resolution to policy routing.

RouterOS can achieve this chain without an external script. A static DNS entry of type FWD can recognize a domain and its subdomains, forward the query to a resolver, and then add the obtained addresses to a dynamic address-list. The firewall then marks new connections to this list, and a dedicated table sends them into the VPN tunnel.

The principle in five steps

  1. LAN clients use the MikroTik as a DNS server ;
  2. a DNS rule FWD recognizes the requested domain and, if necessary, its subdomains ;
  3. the returned IPv4 addresses populate the list vpn-domains ;
  4. new connections to this list receive the mark domain-vpn ;
  5. the routing mark via-vpn-domain selects a table whose default route goes through the tunnel.
Diagram of the DNS, address-list, connection-mark and VPN table chain in RouterOS
The domain is not routed directly : its resolution populates an address list, then the corresponding connections are directed to the VPN table.

Prerequisites and names used

The example assumes that the WireGuard tunnel wg-vpn is already established and that its peer accepts the necessary destinations. For a tunnel used as an Internet exit, its allowed-address generally include 0.0.0.0/0. The remote server must also ensure forwarding and outbound NAT, or know a return route to the LAN.

NameRoleTo adapt
wg-vpnAlready functional tunnel interfaceReal VPN interface name
LANList of client interfacesBridge or internal interface list
vpn-domainsAddresses learned via DNSFree and unique name
domain-vpnMark of selected connectionsFree and unique name
via-vpn-domainTunnel routing tableFree and unique name
service.exampleDocumentation domainYour actual domain

The presented configuration is intentionally limited to IPv4. If clients also obtain an IPv6 address and resolve AAAA records, they can reach the service outside of this IPv4 policy. An equivalent IPv6 policy must then be designed, or this bypass path must be explicitly prevented.

Before modifying routing

Work from the LAN, enable Safe Mode with Ctrl+X, and export the configuration. Also verify that the tunnel already works to a test address before adding domain-based routing.

/export file=avant-domaines-vpn
/system backup save name=avant-domaines-vpn
/interface wireguard print detail
/interface wireguard peers print detail
/ip route print detail
/ip firewall mangle print detail

Do not use the new rule to diagnose a still inactive tunnel. DNS, the routing table, and the firewall add several layers ; VPN transport must be validated separately.

1. Create the VPN routing table

In RouterOS 7, the table must exist before being used in a mark-routing action. The fib flag allows its use for packet forwarding.

/routing table
add fib name=via-vpn-domain

Then add a default route in this table. With a point-to-point WireGuard interface, the interface can serve as the gateway.

/ip route
add dst-address=0.0.0.0/0 gateway=wg-vpn \
    routing-table=via-vpn-domain distance=1 \
    comment="Domains: exit via VPN"

For another type of tunnel, use the gateway adapted to its documentation. Check that the route has the active flag before proceeding.

/routing table print
/ip route print detail where routing-table=via-vpn-domain

2. Make clients use the MikroTik's DNS

The dynamic list only fills up if the MikroTik sees the DNS query. Enable remote requests, then advertise the router's LAN address as the DNS server in the DHCP network.

/ip dns
set allow-remote-requests=yes cache-size=8192KiB \
    address-list-extra-time=1h

/ip dhcp-server network
set [find where address="192.168.88.0/24"] dns-server=192.168.88.1

Replace the network and router address. An additional hour after the TTL reduces the risk of a client still keeping an address while the router's list has just forgotten it. However, avoid an arbitrarily long value : on a rapidly changing CDN, an old address could remain unnecessarily routed into the VPN.

When allow-remote-requests=yes is active, the firewall input must allow TCP and UDP 53 from the LAN and deny them from the WAN. The default RouterOS profile normally applies this separation, but verify it.

/ip firewall filter
add chain=input action=accept in-interface-list=LAN \
    protocol=udp dst-port=53 comment="DNS: LAN clients"
add chain=input action=accept in-interface-list=LAN \
    protocol=tcp dst-port=53 comment="DNS: LAN clients TCP"

Place these rules before the final reject in the input chain. Never add a DNS allow rule without restricting the interface or source addresses : an open resolver on the Internet can be hijacked for amplification attacks.

3. Populate the address-list with DNS Static

Since RouterOS 7.16, a static entry of type FWD can be used with modern DNS forwarding and an address list. In the example, queries for service.example and its subdomains are forwarded to the resolver 9.9.9.9. The responses automatically populate vpn-domains.

/ip dns static
add name=service.example type=FWD forward-to=9.9.9.9 \
    match-subdomain=yes address-list=vpn-domains \
    disabled=no \
    comment="Domains: resolution and VPN list"

Replace the documentation domain. An exact entry with match-subdomain=yes is preferable to a very broad regular expression : it is more readable, faster, and limits accidental matches.

If the content is distributed by a CDN, the resolver may return a different address depending on where the DNS query originates. To obtain a response consistent with the VPN exit, you can route the chosen resolver through the tunnel, provided the VPN is already established and this does not create a circular dependency.

/ip route
add dst-address=9.9.9.9/32 gateway=wg-vpn routing-table=main \
    comment="Domain DNS via VPN"

Simple variant for a single name

For a single host without subdomains, RouterOS also accepts a DNS name directly in an address-list. The router creates the corresponding dynamic entries.

/ip firewall address-list
add list=vpn-domains address=service.example \
    comment="Single domain to VPN"

This variant is convenient for a small number of known names. It becomes less clear as soon as a service uses multiple subdomains, aliases, or a CDN chain. The FWD method with match-subdomain=yes is then more flexible, as it learns the addresses actually requested by the clients.

4. Mark the connection then the routing

Directly marking each packet by its destination works, but a connection mark makes the logic more robust and facilitates FastTrack exclusion. The first rule remembers new connections whose destination belongs to vpn-domains. The second applies the VPN table to all their packets coming from the LAN.

/ip firewall mangle
add chain=prerouting action=mark-connection \
    in-interface-list=LAN dst-address-list=vpn-domains \
    dst-address-type=!local connection-state=new \
    connection-mark=no-mark new-connection-mark=domain-vpn \
    passthrough=yes comment="Domains: mark connection"

add chain=prerouting action=mark-routing \
    in-interface-list=LAN connection-mark=domain-vpn \
    dst-address-type=!local new-routing-mark=via-vpn-domain \
    passthrough=no comment="Domains: route into VPN"

Place these rules before the general policy routing rules. The in-interface-list=LAN condition avoids marking traffic arriving from another WAN, and dst-address-type=!local protects access to the router's addresses.

5. Exclude these connections from FastTrack

FastTrack only correctly handles the main table. Add an accept rule for marked connections and place it immediately before the fasttrack-connection rule. Other connections can continue to benefit from FastTrack.

/ip firewall filter
add chain=forward action=accept connection-mark=domain-vpn \
    connection-state=established,related \
    comment="Domains: exclude from FastTrack"

Display the rule numbers and move the accept rule above FastTrack in WinBox or with move. It is not necessary to disable FastTrack for the entire network.

/ip firewall filter print where action=fasttrack-connection
/ip firewall filter print where comment~"Domains"

6. Verify outbound NAT

In a properly routed site-to-site VPN, the remote network may have a return route to the LAN and no additional NAT is necessary. For a tunnel used as an Internet exit, the remote peer often expects a tunnel source address. Then add a targeted masquerade, and only if the architecture requires it.

/ip firewall nat
add chain=srcnat action=masquerade out-interface=wg-vpn \
    comment="Domains: NAT to VPN exit"

Local NAT is not enough to turn a WireGuard peer into an Internet gateway : the remote system must also allow forwarding and ensure its own exit. Check both ends.

Test the complete chain

Clear the DNS cache of the client workstation, then resolve the domain by explicitly querying the MikroTik. The list must populate before the mangle counters can increase.

/ip dns cache flush
/ip dns cache all print where name~"service.example"
/ip firewall address-list print where list=vpn-domains
/ip firewall mangle print stats where comment~"Domains"
/ip firewall connection print detail where connection-mark=domain-vpn
/ip route print detail where routing-table=via-vpn-domain

From a client, then open the service and observe the tunnel.

/interface monitor-traffic wg-vpn
/tool torch interface=wg-vpn

Also check an unselected destination : it must continue to use the normal Internet access. The test is incomplete if all traffic accidentally goes through the VPN.

Why some domains remain difficult

SituationConsequencePossible response
The client uses external DoH or DoTThe MikroTik does not see the resolution and the list remains emptyManage device DNS via policy, MDM, or firewall
A CDN shares the same IP between multiple sitesOther services may follow the VPNUse an application proxy if name-based precision is required
The service calls ancillary domainsThe page opens partiallyIdentify required names in developer tools and DNS logs
The client cache lives longer than the listThe client keeps an IP that the router no longer classifiesCarefully adjust address-list-extra-time
IPv6 remains availableAAAA traffic can bypass the IPv4 policyCreate a consistent IPv6 policy or intentionally disable this path
QUIC uses UDP 443Filtering limited to TCP would be bypassedMark all IP connections in the list, as in this guide

An address learned via DNS does not prove that it belongs exclusively to the domain. Conversely, if an application directly contacts an IP address without a visible DNS query, it will never be added to the list. Domain-based routing is therefore a useful dynamic association, not a TLS content inspection.

Remove the configuration

Comments and unique names allow removal without relying on rule numbers.

/ip firewall filter remove [find where comment="Domains: exclude from FastTrack"]
/ip firewall mangle remove [find where comment~"Domains:"]
/ip firewall nat remove [find where comment="Domains: NAT to VPN exit"]
/ip dns static remove [find where comment="Domains: resolution and VPN list"]
/ip firewall address-list remove [find where comment="Single domain to VPN"]
/ip route remove [find where comment="Domain DNS via VPN"]
/ip route remove [find where comment="Domains: exit via VPN"]
/routing table remove [find where name=via-vpn-domain]

Also restore the DNS server advertised by DHCP and the previous value of address-list-extra-time if they were modified solely for this function.

Conclusion

RouterOS can send a domain and its subdomains into a VPN without manually maintaining an address list. The resolver turns DNS responses into address-list, the connection mark remembers the decision, and the via-vpn-domain table selects the tunnel. The rest of the network keeps its usual route.

Success depends on three checks : clients must actually query the MikroTik, marked connections must stay out of FastTrack, and the VPN exit must have appropriate return routing or NAT. For complex, shared, or highly distributed services, an application proxy remains more precise than a decision based solely on IP addresses.

Technical references

About the author

Jeremy Kraft runs the infrastructure and the self-hosted services of the IBCSC. These guides describe configurations that were actually deployed and re-checked before publication.

Discussion

Comments

0

No comment yet. Feel free to open the discussion with a question or your own experience.

Have an account? Sign in

Plain text, 2 000 characters maximum. New comments are moderated. Your name is shown with the comment. No e-mail address is asked; only a non-reversible fingerprint of your IP address is kept to fight spam.