Persistent Source-Based Policy Routing Configuration in Ubuntu Linux


6 views

When configuring multi-homed Linux machines, temporary routing rules added via ip route and ip rule commands won't survive system reboots. This becomes particularly problematic when you need consistent routing behavior for services running on non-default interfaces.

For Ubuntu systems, we have three main components to make routing rules persistent:

1. /etc/iproute2/rt_tables - Defines custom routing tables
2. /etc/network/interfaces - Configures interface-specific rules
3. Network manager scripts (if needed)

Here's the full implementation for your eth3 scenario:

# First, add the custom routing table
echo "13 eth3" >> /etc/iproute2/rt_tables

# Then configure /etc/network/interfaces
auto eth3
iface eth3 inet static
    address 10.20.0.2
    netmask 255.255.255.0
    post-up ip route add default via 10.20.0.1 table eth3
    post-up ip rule add from 10.20.0.2 lookup eth3
    pre-down ip rule del from 10.20.0.2 lookup eth3
    pre-down ip route del default via 10.20.0.1 table eth3

For systems using NetworkManager, you can create a dispatcher script:

# Create /etc/NetworkManager/dispatcher.d/99eth3-routing
#!/bin/bash
INTERFACE=$1
ACTION=$2

if [[ "$INTERFACE" = "eth3" && "$ACTION" = "up" ]]; then
    ip route add default via 10.20.0.1 table eth3
    ip rule add from 10.20.0.2 lookup eth3
fi

After reboot, verify with these commands:

ip route show table eth3
ip rule list

Common issues include:
- Missing execute permission on dispatcher scripts
- Incorrect table number in rt_tables
- Interface not being auto-started

For more complex scenarios, consider:
- Using higher priority numbers (32766 and below) in rt_tables
- Implementing multiple rules for different source subnets
- Combining with firewall rules for better traffic control


When working with multi-homed Linux systems, standard routing tables often don't handle traffic originating from specific IP addresses properly. The solution lies in creating custom routing tables and policy rules that persist across reboots.

First, let's examine the basic commands to set up source-based routing:

# Add custom routing table
echo "13 eth3" >> /etc/iproute2/rt_tables

# Configure default route for the table
ip route add default via 10.20.0.1 table eth3

# Create policy rule
ip rule add from 10.20.0.2 lookup eth3

For Ubuntu/Debian systems, the most maintainable approach is to modify /etc/network/interfaces:

iface eth3 inet static
    address 10.20.0.2
    netmask 255.255.255.0
    up ip route add default via 10.20.0.1 table eth3
    up ip rule add from 10.20.0.2 lookup eth3
    down ip rule del from 10.20.0.2 lookup eth3
    down ip route del default via 10.20.0.1 table eth3

For systems using NetworkManager or those requiring more complex logic, consider these approaches:

# Method 1: Using /etc/rc.local
ip route add default via 10.20.0.1 table eth3
ip rule add from 10.20.0.2 lookup eth3

# Method 2: NetworkManager dispatcher script
#!/bin/bash
if [ "$1" == "eth3" ] && [ "$2" == "up" ]; then
    ip route add default via 10.20.0.1 table eth3
    ip rule add from 10.20.0.2 lookup eth3
fi

After configuring, verify with these commands:

# Check routing tables
ip route show table eth3

# List policy rules
ip rule list

# Test connectivity
ping -I 10.20.0.2 8.8.8.8

For complex environments, you might need additional refinements:

# Adding multiple source addresses
ip rule add from 10.20.0.3 lookup eth3

# Setting precedence for rules
ip rule add from 10.20.0.2 lookup eth3 pref 1000

# Handling multiple interfaces
ip rule add from 192.168.1.100 lookup custom_table