RouterOS v7: Route Clients Through Multiple WANs with Routing Rules
TABLE OF CONTENTS (Nhấn để xem)
This article uses a real RouterOS 7.21.5 configuration to demonstrate how individual clients can be routed through multiple WANs. The IP addresses and interface names are kept in the examples so they can be compared with WinBox.
Do not copy the complete configuration to another router. Check interface names, gateways, routing tables, and IP ranges first.
Configuration goal
The goal is to select a WAN for each LAN client:
- Client
10.0.0.10usesVNPT1. - Client
10.0.0.11usesVT2. - Client
10.0.0.12uses themaintable. - Client
10.0.0.15usesVNPT1. - Client
10.0.1.25usesVNPT1.
This is commonly called policy routing or source-based routing: the router selects a path based on the source address instead of using only one shared default route.1

Interfaces in the real configuration
| Interface | Role |
|---|---|
bridgeLAN | Main LAN |
LAN2 | Physical port carrying PPPoE macvlan interfaces |
LAN3 | Physical port carrying VLAN 597-VNPT-LAN3 |
597-VNPT-LAN3-MACVLAN1 | MACVLAN for PPPoE VNPT1 |
LAN2-MACVLAN1 | MACVLAN for PPPoE VT2 |
LAN2-MACVLAN2 | MACVLAN for PPPoE VT1 |
VNPT1 | VNPT PPPoE client |
VT2 | Viettel/VT2 PPPoE client |
VT1 | Other main PPPoE client |
The PPPoE clients are:
/interface pppoe-client
add add-default-route=yes default-route-distance=3 \
interface=597-VNPT-LAN3-MACVLAN1 name=VNPT1
add add-default-route=yes default-route-distance=2 \
interface=LAN2-MACVLAN1 name=VT2
add add-default-route=yes interface=LAN2-MACVLAN2 name=VT1
The PPPoE username has been removed from this public tutorial. Never publish usernames, passwords, or secrets.
What is a routing table?
RouterOS v7 can create multiple routing tables. Each table can contain a different default route.1
/routing table
add disabled=no fib name=VNPT1
add disabled=no fib name=VT2
The fib parameter makes a table available for lookup and forwarding. A table is useful only when it contains suitable routes.

Default routes for each WAN
The VNPT1 table uses the VNPT1 PPPoE interface:
/ip route
add disabled=no dst-address=0.0.0.0/0 \
gateway=VNPT1 routing-table=VNPT1
The VT2 table uses the VT2 PPPoE interface:
/ip route
add disabled=no dst-address=0.0.0.0/0 \
gateway=VT2 routing-table=VT2
Therefore:
- Lookups in
VNPT1use WANVNPT1. - Lookups in
VT2use WANVT2. - Lookups in
mainuse the router’s primary routes.
Inspect the routes:
/ip route print detail where routing-table=VNPT1
/ip route print detail where routing-table=VT2
/ip route print detail where routing-table=main

Routing Rules
Internal-network rules are placed before client-specific rules:
/routing rule
add action=lookup-only-in-table \
comment="LAN IPv4 -> main" \
dst-address=10.0.0.0/23 table=main
add action=lookup-only-in-table \
comment="WG IPv4 -> main" \
dst-address=10.0.2.0/24 table=main
add action=lookup-only-in-table \
comment="VLAN10 IPv4 -> main" \
dst-address=10.0.3.0/24 table=main
These rules keep internal traffic in main instead of sending it through a WAN. This is important for access to Proxmox, OpenHAB, AdGuard Home, and other LAN devices.
Client-specific WAN rules come after them:
add action=lookup-only-in-table \
comment="Socks5_1 -> VNPT1" \
src-address=10.0.0.10/32 table=VNPT1
add action=lookup-only-in-table \
comment="Socks5_2 -> VT2" \
src-address=10.0.0.11/32 table=VT2
add action=lookup-only-in-table \
comment="Socks5_3 -> main" \
src-address=10.0.0.12/32 table=main
add action=lookup-only-in-table \
comment="HTTPS Proxy -> VNPT1" \
src-address=10.0.0.15/32 table=VNPT1
add action=lookup-only-in-table \
comment="PC LINUX -> VNPT1" \
src-address=10.0.1.25/32 table=VNPT1
lookup-only-in-table restricts the lookup to the selected table. If no suitable route exists, the packet may be dropped instead of falling back to another table. This differs from lookup.2



Why must internal rules come first?
Suppose 10.0.0.10 is routed through VNPT1. When it accesses 10.0.0.4, the AdGuard Home server, the router must evaluate this rule first:
dst-address=10.0.0.0/23 table=main
Without the internal rule, the request may be looked up in VNPT1 and sent to the WAN instead of the LAN server.
The conceptual order is:
1. Internal networks → main
2. WireGuard/VLAN internal networks → main
3. Specific client → desired WAN table
4. Other routes → main/default route
Add a new client
Route 10.0.0.20 through VNPT1:
/routing rule
add action=lookup-only-in-table \
comment="New client -> VNPT1" \
src-address=10.0.0.20/32 table=VNPT1
Route it through VT2 instead:
/routing rule
add action=lookup-only-in-table \
comment="New client -> VT2" \
src-address=10.0.0.20/32 table=VT2
Use /32 for one host. For a subnet, use the appropriate CIDR such as 10.0.1.0/24.
Inspect rules and routes
Print all rules in order:
/routing rule print detail
Inspect policy-table routes:
/ip route print detail where routing-table=VNPT1
/ip route print detail where routing-table=VT2
From a client, check the public address:
curl -4 https://ifconfig.me
Expected routing in this example:
10.0.0.10 → public IP of VNPT1
10.0.0.11 → public IP of VT2
10.0.0.12 → public IP selected by main
10.0.0.15 → public IP of VNPT1
10.0.1.25 → public IP of VNPT1
The public address can change, so this is a relative routing test rather than a permanent value.
When a client cannot reach the LAN
If a client can access the Internet but cannot reach 10.0.0.4, 10.0.0.2, or OpenHAB, inspect:
/routing rule print detail
/ip route print detail where routing-table=main
/ip firewall filter print stats
/ip firewall nat print stats
The internal networks in the example are:
10.0.0.0/23 → bridgeLAN
10.0.2.0/24 → WireGuard1
10.0.3.0/24 → VLAN10_Guest
Ensure their dst-address rules appear before client src-address rules.
IPv6 considerations
The export also contains IPv6 rules, such as fd00:10::10/128 and fd00:10::25/128. Test IPv4 and IPv6 separately:
/routing rule print detail
/ipv6 route print detail
A client can use VNPT1 for IPv4 while IPv6 follows another route. If both protocols must use the same WAN, configure and test both rule sets.
The export contains this example:
comment="Socks5_2 v6 -> VT1" \
src-address=fd00:10::11/128 table=main
The comment says VT1, but the actual table is main. Verify such discrepancies on the device before publishing a configuration.
Roll back a rule
Export the rules before editing:
/routing rule export file=routing-rules-before-change
Disable a rule by number:
/routing rule disable <rule-number>
Or remove it after confirming the number:
/routing rule remove <rule-number>
Do not rely on an old number after adding or removing several rules. Use print detail to confirm the comment and src-address first.
Summary
The policy-routing flow is:
Client source address
↓
/routing rule
↓
VNPT1 or VT2 routing table
↓
Default route through the matching PPPoE interface
↓
Selected WAN
The difficult part is not adding one more rule; it is ensuring that traffic to internal networks is sent to main before the client-specific WAN rule is applied.
Sources
Mikrotik
- RouterOS v7: Route Clients Through Multiple WANs with Routing Rules Reading
- MikroTik Firewall Filter Rules for Better Security
- Manually Install AdGuard Home in a MikroTik Container (Method 2)
- Tips for Optimizing Ping and Bufferbloat on MikroTik
- How to Install AdGuard Home Directly on a MikroTik Router
Discussion & Feedback 0
Share your questions, feedback or insights with the community