Recently I had a case where for a couple of tests was needed to configure one RHEL 8 host with 2 network cards (vNICs, it was a VM) and each of those two cards needed its own default gateway and I had to configure them to route network traffic such that the packets go out via the same interface they came in
Normally, we only have one default gateway on a host. In that case, it would lead to asynchronous routing and cause us a problem, because a different interface is used for sending traffic than is used to receive traffic.
The flows are considered to be unusual because traffic from one end of the connection (A→B) travels over a different set of links than does traffic moving in the opposite direction (B→A).

Thanks to iproute2, an open-source project, which can be found in almost all Linux distros we can resolve that problem I had. RHEL and CentOS as all Linux systems only have one routing table with a single default gateway. I am going to set up an additional routing table and allow this table to be used by the system based on rules for an eth1.

In my case I had two interfaces, let’s say eth0 and eth1. Both networks to be used are 172.16.0.0/24 and 192.168.0.0/24,
whereby the first IP address in each network should be the gateway. Under RHEL/CentOS, the initial configuration can be shown with the following commands:

less /etc/sysconfig/network-scripts/ifcfg-eth0

Output:

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes




DEVICE=eth0
ONBOOT=yes
IPADDR=172.16.xxx.xx
PREFIX=24
GATEWAY=172.16.xxx.1
DNS1=172.16.xxx.x
DOMAIN=virtualinca.lab

 and:

less /etc/sysconfig/network-scripts/ifcfg-eth1

Output:

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes




DEVICE=eth1
ONBOOT=yes
IPADDR=192.168.0.100
PREFIX=24
GATEWAY=192.168.0.1

and existing routes can be shown with the following command:

ip route show

Output:

default via 172.16.xxx.1 dev eth0 proto static metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
172.18.0.0/16 dev docker_gwbridge proto kernel scope link src 172.18.0.1
172.16.xxx.0/24 dev eth0 proto kernel scope link src 172.16.xxx.xx metric 100

To add a new custom routing table, I edited the /etc/iproute2/rt_tables file manually but you can use following command:

echo "1 lab2" >> /etc/iproute2/rt_tables

I named my new routing table “lab2” with preference 1. Check edited file with the following command:

less /etc/iproute2/rt_tables

Edited file output should be similar to this:

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

 

Now the new routing table needs to be populated with the following commands:

#allow network 192.168.0.0/24 to be reached through the eth1 interface
ip route add 192.168.0.0/24 dev eth1 src 192.168.0.100 table lab2

#set the default gateway
ip route add default via 192.168.0.1 dev eth1 table lab2

To specify the conditions when my system is to use the new routing table, two rules must be configured with the following commands:

ip rule add from 192.168.0.100/24 table lab2
ip rule add to 192.168.0.100/24 table lab2

Afterward, I was able to conduct my tests, but be aware that the ip rule and ip route commands will be invalid after a reboot so if you want your changes to be permanent you should create a script or
create files with routing tables parameters.

How it can be done, please check the following Red Hat KB -> How to make routing rules persistent, when I want packets to leave the same interface they came in?