Here is the usual way new routing tables and rules are added, which the OP doesn't want:
- create a new routing table that includes "exceptions", called
FOO - add a rule with a condition that selects this table
FOO - because the rule gets a lower (better) priority the new table
FOO is read first, thus usually entirely bypassing the main table. To "correct" this problem, routes from the main table are copied to table FOO.
Rules would look like this:
# ip rule 0: from all lookup local 32765: from 192.168.1.0/24 lookup FOO 32766: from all lookup main 32767: from all lookup default
OP doesn't wish to have to do 3., because it increases administration burden when routes are changed.
From what I understand this is what OP is wishing:
- every local traffic should be handled with the usual routes from table
main - if the traffic is coming from
192.168.1.0/24 its default route should be taken from table FOO (here dev eth0) - else, the traffic will use the "usual" default route.
Let's implement it in this order instead of the usual order. The result might not be exactly what was described in the question, but should be what was wished. Without the actual problem to solve and the proper configuration given from OP, some things might seem awkward (like reusing the output of ip route to move the default route from table main to table default).
Starting from usual rules:
# ip rule 0: from all lookup local 32766: from all lookup main 32767: from all lookup default
Note that the default table is empty (by default) and free to use.
# ip route show table default #
move the rule looking up main to a lower priority
# ip rule add priority 32000 from all lookup main # ip rule del priority 32766
implement exceptions
# ip route add default dev eth0 table FOO # ip rule add priority 32100 from 192.168.1.0/24 lookup FOO
move the "usual" default route from table main to table default, to allow exceptions to trigger at rule 32100. Rule 32767 will still be giving the default route from the default table if no match was found before, there's no connectivity loss.
# ip route add $(ip route show 0.0.0.0/0) table default # ip route del default
Rules will now look like this:
# ip rule 0: from all lookup local 32000: from all lookup main 32100: from 192.168.1.0/24 lookup FOO 32767: from all lookup default
A few examples in a container (that won't make much sense, that's just to see the tables involved):
# ip -br link lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP> eth0@if12 UP 66:d4:11:94:49:5f <BROADCAST,MULTICAST,UP,LOWER_UP> local0@if9 UP 00:16:3e:6a:c1:e9 <BROADCAST,MULTICAST,UP,LOWER_UP> # ip -4 -br a lo UNKNOWN 127.0.0.1/8 local0@if9 UP 10.0.3.66/24 # ip route 10.0.3.0/24 dev local0 proto kernel scope link src 10.0.3.66 # ip route show table FOO default dev eth0 scope link # ip route show table default default via 10.0.3.1 dev local0 # ip -o route get 10.0.3.2 10.0.3.2 dev local0 src 10.0.3.66 \ cache # ip -o route get 8.8.8.8 8.8.8.8 via 10.0.3.1 dev local0 table default src 10.0.3.66 \ cache # ip -o route get 8.8.8.8 from 192.168.1.2 iif local0 8.8.8.8 from 192.168.1.2 dev eth0 table FOO \ cache iif local0
That's it. The only usage difference is that the "usual" default route has now to be set in table default (253) instead of table main (254). Boot scripts have to be adapted to handle it: settings should not state a default route or gateway but should run an additional custom script which will do ip route add default ... table default. For Debian this can be done with post-up commands (eg post-up ip route add default via xxx table default || :) in /etc/network/interfaces. For RHEL7 this should be done with route-XXX files. For systemd's new network methods, I have no idea.
ip -br link; ip -4 -br addr(or without -br if it fails)ip -4 route)? It would help understanding what you're trying to solve. I got it that you want to avoid having to copy almost all routes from main to FOO. I think I have an idea that would be interesting but I'd like to check if it "works" first