Implementing VRF in the Linux Operating System

Virtual Routing and Forwarding (VRF) allows a single Linux host to maintain multiple, isolated Layer 3 routing tables simultaneously, enabling multi-tenancy and complex network segmentation. This article explores how modern Linux kernels natively implement VRF using Layer 3 master devices (l3mdev), the mechanics of packet path isolation, and the step-by-step process to configure and run applications inside isolated VRF domains using iproute2.

The Architectural Foundation: l3mdev

Prior to kernel version 4.3, network isolation on Linux primarily relied on network namespaces (netns). While namespaces duplicate the entire network stack—including device lists, firewall rules, and sockets—VRF implements Layer 3 isolation within a single network namespace.

The kernel achieves this through the Layer 3 Master Device (l3mdev) infrastructure. Under this model:

When an interface is enslaved to a VRF, all Layer 3 packet processing on that interface is redirected from the kernel’s default routing tables (local and main) to the routing table associated with the VRF master device.

Ingress and Egress Packet Handling

  1. Ingress: When an IP packet arrives on an enslaved interface, the kernel's core IP input function passes the packet through the l3mdev_l3_rcv hook. This hook identifies the master VRF device and selects its designated routing table for the route lookup, ensuring that destination decisions remain strictly within that VRF domain.
  2. Egress: Locally generated traffic is steered into a VRF via socket-level binding. By using the SO_BINDTODEVICE socket option, applications bind directly to the VRF master device. When the kernel performs the routing lookup for outbound packets, it selects the routing table bound to that VRF.

Configuring VRF with iproute2

Linux manages VRF instances natively through the ip link and ip route suites.

1. Create the VRF Device

Create a VRF device and map it to a designated routing table ID:

ip link add dev vrf-blue type vrf table 100
ip link set dev vrf-blue up

2. Enslave Interfaces

Assign interfaces to the VRF device. This moves Layer 3 handling of these interfaces into table 100:

ip link set dev eth1 master vrf-blue
ip link set dev eth1 up

3. Assign IP Addresses and Routes

IP addresses are assigned to the member interfaces as usual, but specific routes are added directly to the VRF’s routing table:

ip addr add 192.168.10.1/24 dev eth1
ip route add 10.0.0.0/8 via 192.168.10.254 dev eth1 table 100

Running Applications in a VRF

To run standard, unmodified network utilities and daemons inside an isolated VRF, Linux provides the ip vrf exec wrapper, which relies on cgroups and the SO_BINDTODEVICE socket option:

ip vrf exec vrf-blue ping 10.0.0.1
ip vrf exec vrf-blue ssh user@10.0.0.2

Network daemons (such as BGP/OSPF engines or SSH servers) can also be programmed natively to listen on specific VRF interfaces by utilizing the SO_BINDTODEVICE or IP_PKTINFO socket flags, allowing multi-instance routing services on a single operating system.