openwrt / netifd

[MIRROR] OpenWrt Network interface configuration daemon
https://git.openwrt.org/?p=project/netifd.git;
17 stars 19 forks source link

network_find_wan returns interfaces with non-default ip4table #5

Open gentoo-root opened 1 year ago

gentoo-root commented 1 year ago

Describe the bug

The network_find_wan function uses the following query to find the WAN interface: [@.route[@.target='0.0.0.0' && !@.table]].interface. If I parse it correctly, it's supposed to find the interfaces that have a route to 0.0.0.0, and this route is in the main table (i.e. no table override is set), which makes sense to me.

However, the !@.table part of the query seems to be a no-op, because table is missing even for routes of the interfaces that use option ip4table in /etc/config/network. That means, network_find_wan will find such interfaces, although their 0.0.0.0 route is not in the main routing table. Many packages use network_find_wan to find the actual WAN interface, and they will misbehave if network_find_wan returns a VPN interface instead of WAN.

The same issue affects network_find_wan6.

OpenWrt version

r23246-d85013460d

OpenWrt target/subtarget

mediatek/mt7622

Device

Linksys E8450 (UBI) (actually Belkin RT3200)

Image kind

Self-built image

Steps to reproduce

Configuration (mind the ...):

/etc/iproute2/rt_tables:

...
1 vpn

/etc/config/network:

...
config interface 'vpn'
        option proto 'wireguard'
        option private_key '...'
        list addresses '...'
        list addresses '...'
        option ip4table 'vpn'
        option ip6table 'vpn'
        option nohostroute '1'

config wireguard_vpn
        option public_key '...'
        option preshared_key '...'
        option endpoint_host '...'
        option endpoint_port '...'
        option route_allowed_ips '1'
        option persistent_keepalive '25'
        list allowed_ips '0.0.0.0/0'
        list allowed_ips '::/0'
...

Check that the routes don't have the table field:

$ ifstatus vpn | jsonfilter -e "@.route[@]"
{ "target": "::", "mask": 0, "nexthop": "::", "source": "::\/0" }
{ "target": "0.0.0.0", "mask": 0, "nexthop": "0.0.0.0", "source": "0.0.0.0\/0" }

Check that the default route of vpn is not in the main routing table:

$ ip route | grep '^default '
default via ... dev wan ...

Check that the default route of vpn is in the vpn routing table:

$ ip route show table vpn | grep '^default '
default dev vpn proto static scope link

Check that network_find_wan returns vpn instead of wan:

$ . /lib/functions/network.sh
$ network_find_wan wan; echo "$wan"
vpn

Actual behaviour

network_find_wan returns vpn, although the vpn interface doesn't have a default route in the main table.

Expected behaviour

network_find_wan should return wan. ifstatus vpn should return the "table": "vpn" field for each route.

Additional info

I believe the root cause might be in netifd, because it generates data for the ifstatus output, but I didn't dig into netifd's sources.

Diffconfig

No response

Terms