Skip to content
MikroTik RouterOS Docs

Routing Tables and Policy Routing

Create a routing table and add a route:

/routing table add name=ISP2 fib
/ip route add dst-address=0.0.0.0/0 gateway=192.168.2.1 routing-table=ISP2

Route specific source IP through alternate table:

/routing rule add src-address=192.168.88.100/32 action=lookup table=ISP2

Route traffic using mangle marks:

/ip firewall mangle add chain=prerouting src-address=192.168.88.0/24 \
dst-address-type=!local action=mark-routing new-routing-mark=ISP2

What this covers: Creating multiple routing tables and using policy routing to direct traffic based on source address, destination, or other criteria.

When to use this:

  • Multi-WAN setups where different traffic should use different ISPs
  • Source-based routing (specific hosts use specific gateways)
  • VPN split tunneling (route only certain traffic through VPN)
  • Load balancing across multiple internet connections
  • Separating guest and internal traffic paths

How it works:

  1. Create named routing tables (each with its own forwarding database)
  2. Add routes to specific tables (default routes, static routes)
  3. Use routing rules or mangle marks to direct traffic to tables
  4. Traffic matching the rule uses that table for routing decisions

Key concepts:

  • Main table: Default routing table used by all traffic
  • Custom tables: Additional tables for policy routing
  • Routing rules: Simple matching (source/destination) to select table
  • Mangle marks: Advanced matching (ports, protocols, address lists) to select table

Prerequisites:

  • MikroTik router running RouterOS 7.x
  • Understanding of basic IP routing
  • Multiple gateways or WAN connections (for most use cases)

In RouterOS 7.x, routing tables must be created before use:

/routing table add name=ISP2 fib

The fib flag creates a Forwarding Information Base for this table, enabling actual packet forwarding.

RouterOS 7 Requirement

Unlike RouterOS 6.x, you MUST create routing tables before referencing them in routes or mangle rules. Attempting to use an undefined table will fail.

Add a default route to the custom table:

/ip route add dst-address=0.0.0.0/0 gateway=192.168.2.1 routing-table=ISP2

You can add multiple routes to a table:

/ip route add dst-address=10.0.0.0/8 gateway=192.168.2.1 routing-table=ISP2
/ip route add dst-address=172.16.0.0/12 gateway=192.168.2.1 routing-table=ISP2

Check that the table exists:

/routing table print

Expected output:

Flags: D - DYNAMIC; X - DISABLED, I - INVALID; U - USED
# NAME FIB
0 main
1 ISP2 fib

Check routes in the table:

/ip route print where routing-table=ISP2

Routing rules provide a simple way to direct traffic to specific tables based on source or destination address.

Route all traffic from a specific host through the ISP2 table:

/routing rule add src-address=192.168.88.100/32 action=lookup table=ISP2
PropertyDescription
src-addressMatch source IP address
dst-addressMatch destination IP address
interfaceMatch incoming interface
routing-markMatch packets with this routing mark
actionWhat to do (lookup, drop, unreachable)
tableWhich table to use for lookup

Route an entire subnet through ISP2:

/routing rule add src-address=192.168.10.0/24 action=lookup table=ISP2 \
comment="Guest network via ISP2"

Route traffic to specific destinations through alternate table:

/routing rule add dst-address=203.0.113.0/24 action=lookup table=ISP2 \
comment="Route to partner network via ISP2"
/routing rule print

Expected output:

Flags: X - DISABLED, I - INVALID
# SRC-ADDRESS DST-ADDRESS ACTION TABLE
0 192.168.88.100/32 lookup ISP2
1 192.168.10.0/24 lookup ISP2

For more complex matching (ports, protocols, address lists), use mangle rules to mark traffic with a routing mark.

Mark traffic from a subnet for alternate routing:

/ip firewall mangle add chain=prerouting src-address=192.168.88.0/24 \
dst-address-type=!local action=mark-routing new-routing-mark=ISP2 \
passthrough=no comment="Route LAN via ISP2"

Exclude Local Traffic

Always include dst-address-type=!local when marking routing in prerouting chain. Without this, you may mark traffic destined for the router itself, breaking management access.

Route all HTTP/HTTPS traffic through alternate table:

/ip firewall mangle add chain=prerouting protocol=tcp dst-port=80,443 \
src-address=192.168.88.0/24 dst-address-type=!local \
action=mark-routing new-routing-mark=ISP2 passthrough=no \
comment="Route web traffic via ISP2"

Route traffic to specific destinations using an address list:

# Create address list
/ip firewall address-list add list=vpn-destinations address=10.0.0.0/8
/ip firewall address-list add list=vpn-destinations address=172.16.0.0/12
# Mark traffic to those destinations
/ip firewall mangle add chain=prerouting dst-address-list=vpn-destinations \
src-address=192.168.88.0/24 action=mark-routing new-routing-mark=VPN \
passthrough=no comment="Route to VPN destinations"
/ip firewall mangle print stats where action=mark-routing

A complete multi-WAN setup with failover and policy routing.

  • WAN1: Primary ISP via ether1 (gateway 192.168.1.1)
  • WAN2: Secondary ISP via ether2 (gateway 192.168.2.1)
  • LAN: 192.168.88.0/24 on bridge
/routing table add name=WAN1 fib
/routing table add name=WAN2 fib
# Main table - primary route
/ip route add dst-address=0.0.0.0/0 gateway=192.168.1.1 distance=1 \
comment="Primary WAN"
/ip route add dst-address=0.0.0.0/0 gateway=192.168.2.1 distance=2 \
comment="Backup WAN"
# WAN1 table
/ip route add dst-address=0.0.0.0/0 gateway=192.168.1.1 routing-table=WAN1
# WAN2 table
/ip route add dst-address=0.0.0.0/0 gateway=192.168.2.1 routing-table=WAN2
/ip firewall nat add chain=srcnat out-interface=ether1 action=masquerade \
comment="NAT via WAN1"
/ip firewall nat add chain=srcnat out-interface=ether2 action=masquerade \
comment="NAT via WAN2"

Route a specific workstation through WAN2:

/routing rule add src-address=192.168.88.100/32 action=lookup table=WAN2 \
comment="Workstation via WAN2"

Or using mangle for more control:

/ip firewall mangle add chain=prerouting src-address=192.168.88.100 \
dst-address-type=!local action=mark-routing new-routing-mark=WAN2 \
passthrough=no comment="Workstation via WAN2"

Use Netwatch to check WAN availability:

/tool netwatch add host=8.8.8.8 interval=10s down-script={
/ip route set [find comment="Primary WAN"] disabled=yes
} up-script={
/ip route set [find comment="Primary WAN"] disabled=no
}

Per-Connection Classifier (PCC) distributes connections across multiple WANs.

/routing table add name=WAN1 fib
/routing table add name=WAN2 fib
/ip route add dst-address=0.0.0.0/0 gateway=192.168.1.1 routing-table=WAN1 \
check-gateway=ping
/ip route add dst-address=0.0.0.0/0 gateway=192.168.2.1 routing-table=WAN2 \
check-gateway=ping
# Mark new connections - 50/50 split
/ip firewall mangle add chain=prerouting in-interface=bridge \
dst-address-type=!local connection-state=new \
per-connection-classifier=both-addresses:2/0 \
action=mark-connection new-connection-mark=WAN1_conn passthrough=yes
/ip firewall mangle add chain=prerouting in-interface=bridge \
dst-address-type=!local connection-state=new \
per-connection-classifier=both-addresses:2/1 \
action=mark-connection new-connection-mark=WAN2_conn passthrough=yes
/ip firewall mangle add chain=prerouting in-interface=bridge \
connection-mark=WAN1_conn action=mark-routing new-routing-mark=WAN1 \
passthrough=no
/ip firewall mangle add chain=prerouting in-interface=bridge \
connection-mark=WAN2_conn action=mark-routing new-routing-mark=WAN2 \
passthrough=no

Ensure return traffic uses the correct WAN:

/ip firewall mangle add chain=output connection-mark=WAN1_conn \
action=mark-routing new-routing-mark=WAN1 passthrough=no
/ip firewall mangle add chain=output connection-mark=WAN2_conn \
action=mark-routing new-routing-mark=WAN2 passthrough=no

Symptom: Error “routing table not found” when adding route.

Cause: RouterOS 7 requires tables to be created first.

Solution:

/routing table add name=MyTable fib

Symptoms: Traffic still uses main table despite routing rule.

Checks:

/routing rule print
/ip firewall mangle print stats where action=mark-routing

Solutions:

  1. Verify rule/mangle is matching traffic (check counters)
  2. Check rule order - more specific rules first
  3. Ensure mangle includes dst-address-type=!local
  4. Verify the routing table has a valid route

Symptom: Can’t access router after adding mangle rules.

Cause: Routing mark applied to traffic destined for router.

Solution: Always exclude local traffic:

/ip firewall mangle set [find action=mark-routing] dst-address-type=!local

Symptoms: Connections fail or are slow; traffic goes out one WAN, returns via another.

Cause: Return traffic not using same path as outbound.

Solutions:

  1. Mark connections, not just packets
  2. Add output chain mangle rules for return traffic
  3. Ensure NAT is configured on both WANs

Symptoms: PCC load balancing inconsistent; same connection uses different WANs.

Checks:

/ip firewall connection tracking print
/ip firewall connection print where connection-mark!=

Solutions:

  1. Ensure connection tracking is enabled
  2. Check connection table isn’t full
  3. Verify mangle rules match connection-state=new for marking

Symptom: Mangle rules show hits initially but traffic reverts to main table.

Cause: FastTrack bypasses mangle for established connections.

Solution: Disable FastTrack or accept that FastTracked connections use main table:

/ip firewall filter disable [find action=fasttrack-connection]

# List routing tables
/routing table print
# Show routes in specific table
/ip route print where routing-table=ISP2
# List routing rules
/routing rule print
# Check mangle rules with stats
/ip firewall mangle print stats where action=mark-routing
# View marked connections
/ip firewall connection print where connection-mark!=
# Test which route a destination uses
/ip route print where dst-address in 8.8.8.8
# Routing Tables (v7)
/routing table add name=X fib
/routing table print
/routing table remove [find name=X]
# Routes with Tables
/ip route add dst-address=0.0.0.0/0 gateway=X routing-table=Y
/ip route print where routing-table=Y
# Routing Rules (v7)
/routing rule add src-address=X action=lookup table=Y
/routing rule print
/routing rule move [numbers] destination=N
# Mangle Mark Routing
/ip firewall mangle add chain=prerouting src-address=X \
dst-address-type=!local action=mark-routing new-routing-mark=Y

Routing tables enable policy-based routing for:

  1. Multi-WAN setups - Different traffic through different ISPs
  2. Source-based routing - Specific hosts use specific gateways
  3. Destination-based routing - Traffic to certain destinations via alternate paths
  4. Load balancing - PCC distributes connections across WANs

Key points:

  • RouterOS 7 requires pre-creating tables with /routing table add name=X fib
  • Use routing rules for simple source/destination matching
  • Use mangle marks for complex matching (ports, protocols, address lists)
  • Always exclude local traffic (dst-address-type=!local) in mangle
  • Mark connections (not just packets) for consistent routing
  • Mangle has higher priority than routing rules