I've setup source policy routing on a Linux "router" using :

ip rule add from table FOO
ip route add default dev eth0 table FOO

Packets forwarded from that subnet reach Internet destinations.

Issue is that table FOO does not inherit locally-connected routes from table main.
I could add locally connected routes manually, but obviously that's fragile and requires more maintenance.

I would like table FOO to inherit all routes of table main, and then instead of "ip route add default ...", I could use an "ip route change default".

The default route of table main must stay in place for other subnets.

How can I do this ?

  • Would you mind sharing your actual settings before this ( 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 – A.B Mar 24 '18 at 18:28

Here is the usual way new routing tables and rules are added, which the OP doesn't want:

  1. create a new routing table that includes "exceptions", called FOO
  2. add a rule with a condition that selects this table FOO
  3. 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 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:

  1. every local traffic should be handled with the usual routes from table main
  2. if the traffic is coming from its default route should be taken from table FOO (here dev eth0)
  3. 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
  1. move the rule looking up main to a lower priority

    # ip rule add priority 32000 from all lookup main
    # ip rule del priority 32766
  2. implement exceptions

    # ip route add default dev eth0 table FOO
    # ip rule add priority 32100 from lookup FOO
  3. 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 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 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 
local0@if9       UP    
# ip route dev local0 proto kernel scope link src 
# ip route show table FOO
default dev eth0 scope link 
# ip route show table default
default via dev local0 

# ip -o route get dev local0 src \    cache 
# ip -o route get via dev local0 table default src \    cache 
# ip -o route get from iif local0 from 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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.