How to do source-based IP Routing in Linux

Our company has two upstreams for internet access. Assume that the upstreams are ISP1 and ISP2. The router is using Linux running BGP (Quagga) for dynamic routing between the two upstreams. See the image below for the sample of source-based IP routing topology.

By default the uplink traffic is going through ISP1 for both Cust A and Cust B networks. I would like to set the traffic coming from network is going through ISP2. I have set the local preference to make it going to ISP2 but it seems it doesn’t work in Quagga. In Cisco it works well.

Source-based IP Routing

To solve this issue, in Linux we can use iproute2 to set source-based IP routing. Here is the step-by-step:

1. Add a custom policy routing table in /etc/iproute2/rt_tables file

echo "200	isp2" >> /etc/iproute2/rt_tables

So the /etc/iproute2/rt_tables file is like below:

# reserved values
255	local
254	main
253	default
0	unspec
# local
#1	inr.ruhep
200	isp2

2. Create an IP policy rule for all traffics coming from

ip rule add from lookup isp2

3. Add an ip route to populate the routing table.
According to the image above, the ISP2 IP address is reachable via eth1, so we need to add route as below:

ip route add default via dev eth1 table isp2

Verify the uplink traffics from using ‘traceroute’.

4. To make it active on boot, add the ip rule and ip route above in /etc/rc.local file as below:

#!/bin/sh -e
# rc.local
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
# In order to enable or disable this script just change the execution
# bits.
# By default this script does nothing.

# force customer uplink traffic via ISP2
/sbin/ip rule add from lookup isp2
/sbin/ip route add default via dev eth1 table isp2

exit 0

Hopefully this post helps you understanding on how to configure source-based IP routing in Linux