How to Implement Linux VRF (Virtual Routing and Forwarding) for Network Tenant Isolation

In complex Linux-based networking environments—such as hypervisors, VPN gateways, or BGP routers—a single global routing table is often insufficient. If multiple tenants or interfaces operate on overlapping IP subnets, or if you need to strictly isolate management traffic from production data traffic, relying purely on iptables or policy routing (ip rule) becomes incredibly brittle and difficult to scale.

The enterprise solution is Virtual Routing and Forwarding (VRF). Originally a staple of proprietary hardware routers (like Cisco or Juniper), VRF is now a mature, native capability within the Linux kernel. VRF allows a single Linux system to maintain multiple, completely independent routing tables. Interfaces bound to one VRF cannot communicate with interfaces in another VRF without explicit firewall rules or inter-VRF routing.

This guide explains how to architect, deploy, and test Linux VRFs using the modern iproute2 toolset to achieve total Layer 3 network isolation.

Understanding Linux VRF Architecture

In the Linux kernel, a VRF is implemented as a master network device (similar to a bridge). When physical or virtual network interfaces (e.g., eth1, vlan20, wg0) are enslaved to this VRF master device, all packets entering those interfaces are forced into the specific routing table associated with that VRF.

Because the routing tables are completely isolated, you can have 192.168.1.0/24 configured on an interface in VRF-A, and the exact same 192.168.1.0/24 subnet configured on an interface in VRF-B, with zero conflict.

Step 1: Enabling VRF Support in the Kernel

Before configuring a VRF, ensure that your Linux kernel supports the VRF module and that the necessary sysctl parameters are enabled to allow proper forwarding.

Load the VRF kernel module (if it is not compiled statically):

sudo modprobe vrf

To ensure VRFs behave correctly with TCP/UDP sockets (allowing services like SSH or NGINX to bind specifically to a VRF), you must enable the tcp_l3mdev_accept parameter:

sudo sysctl -w net.ipv4.tcp_l3mdev_accept=1
sudo sysctl -w net.ipv4.conf.all.forwarding=1

(Persist these settings by adding them to /etc/sysctl.d/99-vrf.conf).

Step 2: Creating the VRF Device and Routing Table

We will create a VRF named vrf-tenant1 and associate it with an isolated routing table ID. In Linux, routing tables are identified by integers (1-252).

Create the VRF master device and map it to routing table 100:

sudo ip link add dev vrf-tenant1 type vrf table 100

Bring the VRF master device online:

sudo ip link set dev vrf-tenant1 up

Step 3: Enslaving Network Interfaces to the VRF

With the VRF created, we must bind physical or virtual interfaces to it. For this example, we will assume eth1 and eth2 are dedicated to Tenant 1.

Warning: When you enslave an interface to a VRF, the kernel will immediately flush all existing IP addresses from that interface. You must re-add them afterwards.

Enslave the interfaces to the VRF master:

sudo ip link set dev eth1 master vrf-tenant1
sudo ip link set dev eth2 master vrf-tenant1

Re-assign IP addresses to the interfaces:

sudo ip addr add 10.0.1.10/24 dev eth1
sudo ip addr add 192.168.50.1/24 dev eth2

Bring the interfaces up:

sudo ip link set dev eth1 up
sudo ip link set dev eth2 up

Step 4: Managing VRF Routing

Any routing configuration for Tenant 1 must now explicitly target the VRF routing table. If you simply run ip route add, the route goes into the global routing table and will not affect the VRF.

To view the routing table specifically for vrf-tenant1:

sudo ip route show table 100
# Alternatively:
sudo ip route show vrf vrf-tenant1

To add a default gateway specifically for this VRF (e.g., routing traffic out via eth2):

sudo ip route add default via 192.168.50.254 vrf vrf-tenant1

Step 5: Testing and Executing Commands inside the VRF

Because the VRF is isolated from the global routing table, attempting to ping a host within the VRF from the standard terminal will fail. The ping command will look at the global routing table and find no route.

To execute a command within the context of a specific VRF, you use the ip vrf exec command. This utilizes Linux cgroups to bind the process to the VRF.

Ping a host inside the VRF:

sudo ip vrf exec vrf-tenant1 ping 10.0.1.20

If you need to troubleshoot extensively, you can spawn an entire Bash shell bound to the VRF. Any command executed in this shell (ping, curl, tcpdump) will inherently be restricted to the VRF’s routing table.

sudo ip vrf exec vrf-tenant1 bash

Conclusion

Linux Virtual Routing and Forwarding (VRF) provides a highly performant, kernel-native mechanism for segmenting network traffic. By binding interfaces to VRF master devices and utilizing isolated routing tables, network engineers can transform a standard Linux server into a multi-tenant router, ensuring absolute cryptographic-like isolation between disparate network topologies.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.