[Solved] Network route rule not working

I am trying to configure a very simple routing rule.
I used luci, that created the following configuration for me in /etc/network:

config route
	option target '0.0.0.0/0'
	option gateway '192.168.14.9'
	option table '100'

however this route does not show when I query:

# ip route show table 100
<empty reply>

but if I add the rule manually with:

# ip route add default via 192.168.14.9 table 100

and then

# ip route show table 100
default via 192.168.14.9 dev wg0

I am setting up also a rule via luci that looks up table 100 and that works fine:

---
config rule
    option src '192.168.160.0/24'
    option dest '0.0.0.0/0'
    option lookup '100'
---
# ip rule show table 100
1:	from 192.168.160.0/24 lookup 100

Why adding the rule with luci does not work? What am I doing wrong?

Missing the interface?

2 Likes

The example above is simplified, but I tried with and without, with both luci and ip route command, no change. Luci config is ineffective, whilst the ip route command always works.
It is a shame because I can revert back to using scripts, but what is the point of having luci/uci configuration if it does not work?

Please do try my config above and let me know if it works for you or if you find anything wrong with it. It is quite simple, it takes a couple of minutes.

config route
	option interface 'wg_mullv_se'
	option target '0.0.0.0/0'
	option gateway '10.69.78.222'
	option table '11'

Works for me I have an existing WireGuard interface with address 10.69.78.222.

root@DL-WRX36:~# ip route show table 11
default via 10.69.78.222 dev wg_mullv_se proto static

To be honest a WireGuard interface is a point to point link and does not need a gateway , IPv4 ignores the gateway but for IPv6 you cannot (and do not have to) specify a gateway

EDIT:
Maybe your gateway is wrong, although not necessary and ignored it has to be in the subnet of the interface to be accepted by netifd

I am trying to understand why, what works manually, does not work at all with Luci configuration.

@egc I understand it works for you, but not in my case.

If needed only one wg point to point vpn on this router then I would not need ip routes and ip rules. If would be sufficient to tick the "Route Allowed IPs" box in the client side of the peer that has the 0.0.0.0/0 in Allowed IPs, and all will be good.

But I need 3 subnets, each with the default route going through Wireguard to a different remote VPS in different countries. Hence the need to configure different default routes.

I have not configured yet all 3 WG tunnels and subnets on this router. I am keeping it simple as a POC. I have already a setup working on a different router that uses PBS. But I am finding PBS too unreliable, often (when the wireguard interface reconnects after an IP change) I have to restart PBS manually to re-establish the route because it stops (see my other post on PBS), so I was looking to simplify the configuration using just ip rule and ip route. Which I found works fine, but only manually.

It would be nice to make it work through Luci. Is this buggy too?

Question: in Luci->routing->static IPv4 route--> new route, what does "interface" refer to? Is it the incoming interface or outgoing interface? Not clear, and no documentation found.
Also, in "Advanced settings" tab, what does "on-link" do?

It is the device where the gateway sits.
As it is the way with routing since over 50? Years.

You can specifi a route where you know that the network is on link on that device.
Let's call it some kind of direct route.

"Normally" a network is only reachable through a next hop or a router or as it is called in this, a gateway.

See for instance a route entry for a network where your interface has an address. This route is on link.

Ps. With PBS, you mean PBR? Policy based routing or what do I have missed?

1 Like

PBR, I meant PBR.

1 Like

I found the problem! It was PBR. PBR was inactive not started, not configured, but it was present in the image. I thought...why not remove it? I did not need it anyway. Removed PBR, image rebuilt. Router re-flashed.
Automagically the route appeared exactly like in @egc post.

1 Like

@_bernd already explained it well

You have to choose an interface in LuCi, that is the name you have set on the Interface, netifd then uses the device corresponding with that interface that is the dev in the route
I think LuCi/netifd only makes the table if the device is present which makes sense of course

Thus my Luci rule for an existing WireGuard interface wg_mullv_se is:

config route
	option interface 'wg_mullv_se'
	option target '0.0.0.0/0'
	option table '11'

Which makes a default route in table 11 via my WG interface

You can also use option4table and option6table (Override IPv4 routing table on Advanced tab) set a table number there and everything is made for you.
Note that in this case you have to enable route Allowed IPs as a default route is created but that is moved to your table of choice.

Setup as many tunnel with this as you want of course different table numbers and then make a rule for each subnet targeting the tunnel of your choice:
Example of rules:

config rule
	# for ip source:
	option src '192.168.30.0/24'
	# destination e.g. from all to dest
	option dest '25.52.71.40/32'
	# for interface
	#option in 'lan'
	# for proto
	option ipproto 'icmp`
	# for source port
	option sport '116'
    #table number to use for lookup
	option lookup '11'

Source port (sport) is not implemented yet , I have made a PR for that but that is still pending, the netifd maintainers are busy elsewhere

1 Like

Addon.
There are maybe at least 2 topics someone can mix up...
First. There is this dangerous asymmetrical routing which is no issue if you set your reverse path filter and ensure how to trust route updates.
Second. There is source specific routing, which if I recall correctly only makes decisions based on the source address but not on the incoming interface.
Third. On Linux the net filter module used by nftables can drop really early a packet on an interface if it does not suite you.

I hope this helps....

1 Like

Thank you all for your help.

I bumped into another problem now that PBR was handling correctly, but my route+rule isn't.

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.100.9'
        option netmask '255.255.255.0'
        option delegate '0'
        option gateway '192.168.100.1'

config interface v160
      option proto 'static'
      option device 'br-v160'
      option ipaddr '192.168.160.1'
 
config route
	option interface 'wg_v160'
	option target '0.0.0.0/0'
	option gateway '192.168.14.9'
	option table '100'

config rule
	option src '192.168.160.0/24'
	option dest '0.0.0.0/0'
	option lookup '100'
	option priority '30000'

The configuration above routes the packets from 192.168.160.0/24 through the wireguard VPN correctly, however, although the firewall configuration allows forward from interface v160 to lan, I cannot ping lan addresses. A traceroute shows that packets are directed to 192.168.14.1 (the remote wireguard gateway), which means the now default route for 192.168.160.0/24 takes priority over the local route to 192.168.100.0/24.
If I change the rule (above) priority to 40000, I can now reach the lan from v160, but the default route through 192.168.100.1 takes priority over also for v160.

How do I prevent packets destined for local subnets from going through the VPN? Is it necessary to set specific routes to each subnets, despite the fact they are already there? Or is there a better way to handle this case?

There are two problems i can think off:
You are missing the local route for 192.168.160.0 subnet because you forget to add option netmask 255.255.255.0 to the interface

But that is not what your problem seems to be (but should be resolved).
The problem is that table 100 only has a default route. the PBR app also copies all local routes to the table and you did not do that yet.

This is an example of a script I have used in the past:

It also adds all the local routes from the main table

# add local routes can be enabled if needed
			ip route show | grep -Ev '^default |^0.0.0.0/1 |^128.0.0.0/1 ' | while read route; do
				 ip route add $route table $TID >/dev/null 2>&1
			done

So add also the local routes to table 100 :slight_smile:

1 Like

@egc, thank you!

I tried adding the following rule:

config rule
        option priority '29000'
        option src '192.168.160.0/24'
        option dest '192.168.100.0/24'
        option lookup 'main'

and it worked.

Looking to keep the configuration simple...

To summarize, here is a working configuration:

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.100.9'
        option netmask '255.255.255.0'
        option delegate '0'
        option gateway '192.168.100.1'

config interface v160
      option proto 'static'
      option device 'br-v160'
      option ipaddr '192.168.160.1'
 
config route
	option interface 'wg_v160'
	option target '0.0.0.0/0'
	option gateway '192.168.14.9'
	option table '100'

config rule
        option priority '29000'
        option src '192.168.160.0/24'
        option dest '192.168.100.0/24'
        option lookup 'main'

config rule
	option src '192.168.160.0/24'
	option dest '0.0.0.0/0'
	option lookup '100'
	option priority '30000'

1 Like

If you are satisfied with your current status then please consider marking this topic as [Solved]. See How to mark a topic as [Solved] for a short how-to.
Thanks! :slight_smile:

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.