openwrt / openwrt/packages

pbr: invalid default route if gateway is not configured for interface

Open
#26,083 12 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Makefile
Stars
4.6k
Forks
4k
Avg merge
3d 12h
Merged PRs (30d)
134

Description

I am using pbr for routing outgoing SMTP traffic via a wireguard connection instead of the WAN interface.

My Setup

  • interface wan is the local uplink
  • interface smtp_vpn is the wireguard interface
    • my local IP on this interface is 10.90.12.1
    • a single peer is configured (and connected) with a few allowed_ips is configured (including 0.0.0.0/0)
    • resulting default route for the wireguard interface:
      root@router:~# ip r | grep -w default | grep smtp_vpn
      default dev smtp_vpn proto static scope link metric 20
      

Problem

The default route configured in the dynamically generated routing table pbr_smtp_vpn is wrong:

root@router:~# ip r show table pbr_smtp_vpn | grep -w default
default via 10.90.12.1 dev smtp_vpn

Here the local IP address (10.90.12.1) is used as a default gateway.
This obviously does not work.
Instead the original link-level route should have been applied (see "My Setup" above).

Workaround

In order to let the configured packets flow via the smtp_vpn interface, I configured a static route via OpenWrt for the table dynamically maintained by pbr:

network.cfg21c8b4=route
network.cfg21c8b4.interface='smtp_vpn'
network.cfg21c8b4.target='0.0.0.0/0'
network.cfg21c8b4.metric='15'
network.cfg21c8b4.table='pbr_smtp_vpn'

Probably the above is not robust enough, but it works as for now.

And now there are two default routes in this dynamic pbr table:

root@router:~# ip r show table pbr_smtp_vpn | grep -w default
default via 10.90.12.1 dev smtp_vpn
default dev smtp_vpn proto static scope link metric 15

For unknown reasons, the (unwanted) host-based route (via 10.90.12.1) is ignored by the kernel. This lets the static route handle the traffic.

Possible cause

/etc/init.d/pbr currently contains the following function:

pbr_get_gateway4() {
        local iface="$2" dev="$3" gw
        network_get_gateway gw "$iface" true
        if [ -z "$gw" ] || [ "$gw" = '0.0.0.0' ]; then
#               gw="$(ubus call "network.interface.${iface}" status | jsonfilter -e "@.route[0].nexthop")"
                gw="$(ip -4 a list dev "$dev" 2>/dev/null | grep inet | awk '{print $2}' | awk -F "/" '{print $1}')"
        fi
        eval "$1"='$gw'
}

The currently active gw= assignment picks the local IP as the gateway IP.
I cannot imagine a situation, where the local IP could be the proper choice for a default route.
Thus, the above fallback is probably of no use at all?

I would recommend one of the following changes:

  • A) do not set a route, if no default gateway is found
    • no surprises, no problems
    • a static route should be a reasonable workaround for most affected users
  • B) set a link-scope route, if no default gateway is found
    • this works for wireguard interfaces (just by accident)

Thanks for maintaining the great pbr package!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in /etc/init.d/pbr, focusing on pbr_get_gateway4 and the route-generation path that consumes its gateway value. Reproduce the reported WireGuard setup with no configured gateway, then inspect the resulting pbr_smtp_vpn table. Done means the generated default route does not use the interface's local address and follows an agreed fallback behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
linux, shell
Domain
networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.