Advanced Routing with Policy Routing and VRF

So far in this book, we have worked with the Linux routing table as if there were only one.

For example:

ip route

might show:

default via 192.168.1.1
10.0.0.0/24 dev eth0
172.16.0.0/24 dev eth1

When a packet arrives, Linux searches this routing table and decides where to send the packet.

For many systems, this is sufficient.

However, modern infrastructure often requires more advanced behavior:

  • Multiple Internet connections
  • Traffic engineering
  • Multi-tenant environments
  • VPN gateways
  • Kubernetes nodes
  • Service provider networks
  • Network virtualization platforms

In these environments, a single routing table is often not enough.

Linux provides two powerful mechanisms to solve this problem:

  • Policy Routing
  • VRF (Virtual Routing and Forwarding)

In this chapter, you will learn:

  • Why destination-based routing is sometimes insufficient
  • How Linux policy routing works
  • Routing tables and routing rules
  • Source-based routing
  • Traffic steering
  • What VRFs are
  • How VRFs provide routing isolation
  • How modern platforms use these technologies

The Limitation of Traditional Routing

Normal routing is destination-based.

Linux examines:

Destination IP

and selects the best route.

Example:

Packet:
192.168.1.10 -> 8.8.8.8

Linux searches:

ip route

and forwards according to the matching route.

Notice what Linux does not consider:

  • Source address
  • Incoming interface
  • User ID
  • Application
  • Packet markings

Only the destination matters.

For many scenarios, this is too simplistic.


Consider a server with two Internet connections:

          ISP-A
            |
         eth0
            |
         Linux
            |
         eth1
            |
          ISP-B

Addresses:

eth0 = 203.0.113.10
eth1 = 198.51.100.10

Suppose traffic arrives through ISP-A.

Responses should leave through ISP-A.

Similarly:

Traffic from ISP-B
must return via ISP-B

Traditional routing often fails here because only one default route can be preferred.

The result may be:

Request arrives on eth0
Response leaves on eth1

which can break firewalls, NAT, and upstream routing policies.


Enter Policy Routing

Policy routing allows Linux to make routing decisions based on more than just destination addresses.

Instead of:

Destination -> Route

we can define:

Source -> Route

or:

Interface -> Route

or:

Packet Mark -> Route

This provides significantly more flexibility.


Routing Tables

Most administrators are familiar with the main routing table:

ip route

Internally:

ip route show table main

Linux actually supports many routing tables.

View existing tables:

cat /etc/iproute2/rt_tables

Example:

255 local
254 main
253 default
0 unspec

Additional tables can be created.

For example:

100 isp_a
200 isp_b

Creating Custom Routing Tables

Edit:

sudo vim /etc/iproute2/rt_tables

Add:

100 isp_a
200 isp_b

Now Linux recognizes these names.

Verify:

ip route show table isp_a

Initially:

(empty)

Adding Routes to a Specific Table

Create routes for ISP-A:

sudo ip route add \
    default via 203.0.113.1 \
    table isp_a

Create routes for ISP-B:

sudo ip route add \
    default via 198.51.100.1 \
    table isp_b

Inspect:

ip route show table isp_a

Output:

default via 203.0.113.1

Routing Rules

Having multiple routing tables is not enough.

Linux also needs rules that determine:

Which table should be used?

View existing rules:

ip rule show

Example:

0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

Linux evaluates rules from top to bottom.

The first matching rule wins.


Source-Based Routing

Suppose:

203.0.113.10 -> ISP-A
198.51.100.10 -> ISP-B

Traffic sourced from:

203.0.113.10

should use:

table isp_a

Create the rule:

sudo ip rule add \
    from 203.0.113.10 \
    lookup isp_a

For ISP-B:

sudo ip rule add \
    from 198.51.100.10 \
    lookup isp_b

Verify:

ip rule show

Example:

1000: from 203.0.113.10 lookup isp_a
1001: from 198.51.100.10 lookup isp_b

Now packets are routed according to source address.


Testing Policy Routing

View route selection:

ip route get 8.8.8.8 \
    from 203.0.113.10

Example:

8.8.8.8 via 203.0.113.1

Test the second address:

ip route get 8.8.8.8 \
    from 198.51.100.10

Example:

8.8.8.8 via 198.51.100.1

This is one of the most useful troubleshooting commands in Linux networking.


Routing Based on Incoming Interface

Rules can also match interfaces.

Example:

sudo ip rule add \
    iif eth0 \
    lookup isp_a

Meaning:

Packets arriving on eth0
use table isp_a

This is commonly used on routers and VPN gateways.


Routing Based on Firewall Marks

Linux can route packets according to firewall marks.

Example:

sudo nft add rule inet filter output \
    tcp dport 443 mark set 100

Then:

sudo ip rule add \
    fwmark 100 \
    lookup isp_b

Result:

HTTPS traffic -> ISP-B
Everything else -> ISP-A

This technique is frequently used in:

  • Multi-WAN routers
  • VPN gateways
  • SD-WAN systems
  • Container networking platforms

The Problem Policy Routing Doesn't Solve

Policy routing provides flexibility.

However, all routing tables still belong to the same Linux networking stack.

Consider two customers:

Customer A
10.0.0.0/24

Customer B
10.0.0.0/24

Both use identical address space.

Traditional routing struggles because:

10.0.0.0/24

appears twice.

We need isolation.

This leads us to VRFs.


What Is a VRF?

VRF stands for:

Virtual Routing and Forwarding

A VRF creates an independent routing domain.

Think of it as:

A separate router
inside Linux

Each VRF has:

  • Its own routing table
  • Its own interfaces
  • Its own route lookups

Multiple VRFs can coexist on a single host.


Visualizing a VRF

Without VRFs:

             Linux

      +----------------+
      | Routing Table  |
      +----------------+

With VRFs:

             Linux

   +----------------------+
   | VRF Blue             |
   | Routing Table A      |
   +----------------------+

   +----------------------+
   | VRF Red              |
   | Routing Table B      |
   +----------------------+

The routing domains are isolated.


Creating a VRF

Create a VRF named blue:

sudo ip link add blue \
    type vrf \
    table 100

Bring it up:

sudo ip link set blue up

Verify:

ip link show type vrf

Example:

blue

Assigning Interfaces to a VRF

Move an interface into the VRF:

sudo ip link set eth1 master blue

Now:

eth1 belongs to VRF blue

Routes learned through this interface are stored in:

table 100

instead of the main routing table.


Viewing VRF Routes

Show routes inside the VRF:

ip route show table 100

or:

ip route show vrf blue

Example:

10.10.0.0/24 dev eth1
default via 10.10.0.1

Running Commands Inside a VRF

One of the most useful features:

ip vrf exec blue <command>

Example:

ip vrf exec blue ping 8.8.8.8

The ping uses:

VRF blue

rather than the default routing domain.

This makes testing extremely easy.


Hands-On Lab: Two Isolated Networks

Create two VRFs:

sudo ip link add red type vrf table 100
sudo ip link add blue type vrf table 200

sudo ip link set red up
sudo ip link set blue up

Create interfaces:

sudo ip link add veth-red type veth peer name veth-red-peer
sudo ip link add veth-blue type veth peer name veth-blue-peer

Attach them:

sudo ip link set veth-red master red
sudo ip link set veth-blue master blue

Assign addresses:

sudo ip addr add 10.0.0.1/24 dev veth-red
sudo ip addr add 10.0.0.1/24 dev veth-blue

Notice:

Same subnet
Same IP address
Different VRFs

This is possible because each VRF has its own routing domain.


Where You Will Encounter VRFs

VRFs are heavily used in:

  • Service provider networks
  • MPLS environments
  • Multi-tenant platforms
  • Cloud infrastructure
  • Kubernetes networking implementations
  • Data center fabrics

Even if you never configure a VRF manually, many modern networking platforms use them internally.


Policy Routing vs VRF

FeaturePolicy RoutingVRF
Multiple TablesYesYes
Routing Decisions Based on RulesYesYes
Interface IsolationNoYes
Overlapping IP SpaceDifficultEasy
Multi-Tenant DesignLimitedExcellent
Acts Like Separate RouterNoYes

Policy routing controls how traffic is routed.

VRFs control where routing occurs.

Many advanced networks use both together.


Real-World Examples

You may encounter:

ISP-A -> VRF Internet
ISP-B -> VRF Backup

or:

Tenant-A -> VRF 100
Tenant-B -> VRF 200
Tenant-C -> VRF 300

or:

Management Network -> VRF mgmt
Production Network -> VRF prod
Storage Network -> VRF storage

All running on the same Linux host.


Key Takeaways

  • Traditional Linux routing is destination-based.
  • Policy routing allows routing decisions based on source addresses, interfaces, firewall marks, and other attributes.
  • Linux supports multiple routing tables.
  • Routing rules determine which table is used.
  • ip rule and ip route are the primary policy-routing tools.
  • VRFs create independent routing domains inside a single Linux system.
  • Interfaces can be assigned to specific VRFs.
  • VRFs allow overlapping address spaces and strong network isolation.
  • Modern cloud, service provider, and multi-tenant environments rely heavily on policy routing and VRFs.
  • Policy routing and VRFs are often used together to build sophisticated networking architectures.