- How to set up source based routing with Linux
- Environment
- Situation
- Resolution
- Additional Information
- Disclaimer
- Debian — Source Routing
- Policy Based Routing in Linux
- Setup source routing in Debian linux
- Creating a Custom Policy Routing Table
- Creating Policy Routing Rules
- Populating the Routing Table
- Permanent settings
How to set up source based routing with Linux
This document (7008874) is provided subject to the disclaimer at the end of this document.
Environment
SUSE Linux Enterprise Server 15 Service Pack 4
SUSE Linux Enterprise Server 15 Service Pack 3
SUSE Linux Enterprise Server 15 Service Pack 2
SUSE Linux Enterprise Server 15 Service Pack 1
SUSE Linux Enterprise Server 15
SUSE Linux Enterprise Server 12 Service Pack 5
SUSE Linux Enterprise Server 12 Service Pack 4
SUSE Linux Enterprise Server 12 Service Pack 3
Situation
Resolution
On standard Internet systems, when an IP packet needs to be routed, the decision of where to route the packet is made based on the destination address in the IP packet header.
This default behavior works great when a host uses only a single interface connected to a LAN segment, however, it may cause unintended issues on systems where two interfaces are configured on the same subnet.
All the traffic not in the local subnet will be routed to the default gateway of x.x.x.x. But what if the packets originating from eth1 should be routed to y.y.y.y. The following steps will help in achieving this
Please type ip route add default via y.y.y.y dev eth1 table SECONDPOA and press Enter where y.y.y.y is the IP Address of the next hop for packets originating from eth1.
To test it, please type
traceroute www.suse.com -S p.p.p.p where p.p.p.p is the IP Address of eth0 and notice the next hop. This should be x.x.x.x
traceroute www.suse.com -S s.s.s.s where s.s.s.s is the IP Address of eth1 and notice the next hop. This should be y.y.y.y
Once the above test is successful, please follow the sub steps below to make ip rule statement persistent across reboot.
Paste the following in the file. Modify the ip rule statement accordingly.
#!/bin/bash
### BEGIN INIT INFO
# Provides: rclocal
# Required-Start: $local_fs $remote_fs $network
# X-UnitedLinux-Should-Start: $ALL
# Required-Stop:
# X-UnitedLinux-Should-Stop:
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Short-Description: Simulates rc.local
# Description: Simulates redhat’s rc.local: contains
# commands to execute after system has booted (all services are already
# available)
### END INIT INFO
case «$1» in
start)
ip rule add from s.s.s.s table SECONDPOA
;;
*)
exit 0
;;
esac
Once the above test is successful, please make the ip route statement persistent. Please edit /etc/sysconfig/network/routes and type
default y.y.y.y — eth1 table SECONDPOA
where y.y.y.y is the next hop that packets originating from eth1 needs to take.
Additional Information
Background information: how Linux routes by default
In Linux, by default, packets are considered individually for routing purposes. Thus, all the routing algorithm considers is where to send a packet based on that packet itself, without taking into consideration that the packet may be a response packet of sorts. In a typical setup, this means that all outgoing traffic is going out over one interface, eth0.
If multiple NICs in Linux are configured with addresses in the same subnet, by default communication into that subnet will always be done by the first NIC in that subnet that is started.
Disclaimer
This Support Knowledgebase provides a valuable tool for SUSE customers and parties interested in our products and solutions to acquire information, ideas and learn from one another. Materials are provided for informational, personal or non-commercial use within your organization and are presented «AS IS» WITHOUT WARRANTY OF ANY KIND.
- Document ID:7008874
- Creation Date: 21-Jun-2011
- Modified Date:08-Nov-2022
-
- SUSE Linux Enterprise Server
For questions or concerns with the SUSE Knowledgebase please contact: tidfeedback[at]suse.com
Debian — Source Routing
In some circumstances we want to route packets differently depending not only on ip destination addresses, but also on other packet fields: source address, IP protocol, transport protocol ports or even packet payload. This task is called policy based routing — PBR.
When a router receives a packet it normally decides where to forward it based on the destination address in the packet, which is then used to look up an entry in a routing table. However, in some cases, there may be a need to forward the packet based on other criteria. For example, a network administrator might want to forward a packet based on the source address, not the destination address. This permits routing of packets originating from different sources to different networks even when the destinations are the same and can be useful when interconnecting several private networks.
In the Cisco IOS, PBR is implemented using route maps. Linux supports multiple routing tables since version 2.2. FreeBSD supports PBR using either IPFW, IPFilter or OpenBSD’s PF.
Policy Based Routing in Linux
Policy Based Routing — PBR in linux is based on routing tables and routing rules
Policy routing tables: When the linux kernel needs to make a routing decision, it finds out which table needs to be consulted. By default, there are three tables.
- local — which cannot be modified or deleted
- main — where routes is added when routing table is not specified
- default
Routes added to the linux system without a routing table specified go to the main table, not the default or local table.
Policy routing rules: Again, Linux comes with default three rules, one for each of the default routing tables.
debian@router:~] ip rule show 0: from all lookup local 32766: from all lookup main 32767: from all lookup default
This lists the priority of all rules. We see that all rules apply to all packets (‘from all’). Rule with smaller number has greater priority.
When you want see routes in another routing table than main:
debian@router:~] ip route show table local broadcast 127.0.0.0 dev lo proto kernel scope link src 127.0.0.1 local 127.0.0.0/8 dev lo proto kernel scope host src 127.0.0.1 local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1 broadcast 127.255.255.255 dev lo proto kernel scope link src 127.0.0.1 broadcast 192.168.221.0 dev ens192 proto kernel scope link src 192.168.221.221 local 192.168.221.221 dev ens192 proto kernel scope host src 192.168.221.221 broadcast 192.168.221.255 dev ens192 proto kernel scope link src 192.168.221.221 broadcast 192.168.222.0 dev ens224 proto kernel scope link src 192.168.222.222 local 192.168.222.222 dev ens224 proto kernel scope host src 192.168.222.222 broadcast 192.168.222.255 dev ens224 proto kernel scope link src 192.168.222.222
Rule with smaller ID number has greater priority than rule with greater number ID. Rule with ID 0 has greatest priority.
Setup source routing in Debian linux
We have this network topology with two customer’s networks and two internet service providers. Our goal is configure debian/ubuntu router this way:
We have multiple network interfaces in debian router. But 2 interfaces are connected to ISP:
debian@router:~] ip addr show . 2: ens192: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:50:56:8f:77:f5 brd ff:ff:ff:ff:ff:ff inet 192.168.221.221/24 brd 192.168.221.255 scope global ens192 valid_lft forever preferred_lft forever inet6 fe80::250:56ff:fe8f:77f5/64 scope link valid_lft forever preferred_lft forever 3: ens224: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:50:56:8f:65:d2 brd ff:ff:ff:ff:ff:ff inet 192.168.222.222/24 brd 192.168.222.255 scope global ens224 valid_lft forever preferred_lft forever inet6 fe80::250:56ff:fe8f:65d2/64 scope link valid_lft forever preferred_lft forever .
Creating a Custom Policy Routing Table
The first step is to create a custom policy routing table. Each table is represented by an entry in the file /etc/iproute2/rt_tables, so creating a new table is generally accomplished using a command like this:
echo 200 my_table >> /etc/iproute2/rt_tables
This creates the table with the ID 200 and the name my_table. You’ll reference this name later as you create the rules and populate the table with routes, so make note of it. Because this entry is contained in the rt_tables file, it will be persistent across reboots.
For our goal, we need create two new tables — one table for each for our customers.
debian@router:~] echo 100 customer1 >> /etc/iproute2/rt_tables debian@router:~] echo 101 customer2 >> /etc/iproute2/rt_tables
The content of rt_tables file now:
# # reserved values # 255 local 254 main 253 default 0 unspec # # local # #1 inr.ruhep 100 customer1 101 customer2
Creating Policy Routing Rules
The next step is to create the policy routing rules that will tell the system which table to use to determine the correct route. In this particular case, I’m going to use the source address (i.e., the originating address for the traffic) as the determining factor in the rule. This is a common application of policy routing, and for that reason it’s often referred to as source routing.
To create the policy routing rule,we can use this command:
But I recommend using a ip command containing a rule priority:
ip rule add prio from lookup
debian@router:~] ip rule add prio 100 from 172.32.1.0/24 lookup customer1 debian@router:~] ip rule add prio 100 from 172.32.2.0/24 lookup customer1
You can see all the policy routing rules that are currently in effect using this command:
debian@router:~] ip rule show 0: from all lookup local 100: from 172.32.1.0/24 lookup customer1 100: from 172.32.2.0/24 lookup customer1 32766: from all lookup main 32767: from all lookup default
Populating the Routing Table
Once we have the custom policy routing table created and a rule defined that directs the system to use it, we need to populate the table with the correct routes. The generic command to do this is the ip route add command, but with a specific table parameter added.
For our goal we must populate two routes:
debian@router:~] ip route add 0.0.0.0/0 via 192.168.221.1 table customer1 debian@router:~] ip route add 0.0.0.0/0 via 192.168.222.1 table customer2
Check the execution of previous commands:
debian@router:~] ip route show table customer1 default via 192.168.221.1 dev ens192
debian@router:~] ip route show table customer2 default via 192.168.222.1 dev ens224
Permanent settings
IP packets from customer1 are served with ip rule with ID 100 (from 172.32.1.0/24 lookup customer1) and not with ip rule with ID 32766 (from all lookup main). It is because rule with ID 100 has higher priority that rule with ID 32766. And table customer1 has route that says: default route is via next hop with ip address 192.168.221.1.
The same applies to customer 2.
But we have a small problem. Routes and Rules added this way with ip command are not persistent. How make ip rules persistent you can learn in my previous article Debian Permanent Static Routes