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
- LAN clients use the MikroTik as a DNS server ;
- a DNS rule
FWDrecognizes the requested domain and, if necessary, its subdomains ; - the returned IPv4 addresses populate the list
vpn-domains; - new connections to this list receive the mark
domain-vpn; - the routing mark
via-vpn-domainselects a table whose default route goes through the tunnel.
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.
| Name | Role | To adapt |
|---|---|---|
wg-vpn | Already functional tunnel interface | Real VPN interface name |
LAN | List of client interfaces | Bridge or internal interface list |
vpn-domains | Addresses learned via DNS | Free and unique name |
domain-vpn | Mark of selected connections | Free and unique name |
via-vpn-domain | Tunnel routing table | Free and unique name |
service.example | Documentation domain | Your 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
| Situation | Consequence | Possible response |
|---|---|---|
| The client uses external DoH or DoT | The MikroTik does not see the resolution and the list remains empty | Manage device DNS via policy, MDM, or firewall |
| A CDN shares the same IP between multiple sites | Other services may follow the VPN | Use an application proxy if name-based precision is required |
| The service calls ancillary domains | The page opens partially | Identify required names in developer tools and DNS logs |
| The client cache lives longer than the list | The client keeps an IP that the router no longer classifies | Carefully adjust address-list-extra-time |
| IPv6 remains available | AAAA traffic can bypass the IPv4 policy | Create a consistent IPv6 policy or intentionally disable this path |
| QUIC uses UDP 443 | Filtering limited to TCP would be bypassed | Mark 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.
Discussion
Comments
No comment yet. Feel free to open the discussion with a question or your own experience.