pbr: invalid default route if gateway is not configured for interface
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
wanis the local uplink - interface
smtp_vpnis 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_ipsis configured (including0.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
- my local IP on this interface is
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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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