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