Policy-Based-Routing (pbr) package discussion

Thanks.

I suggest to embed this script. It works good.

Thanks a lot guys!

Wed Sep 3 20:35:35 2025 user.notice pbr-dns-prefetch: Prefetching domain names from /var/run/pbr.dnsmasq
Wed Sep 3 20:35:36 2025 user.notice pbr-dns-prefetch: Finished prefetching 98 entries

2 Likes

I have been pondering on the interface setup part lately and @egc has previously looked into using the netifd support that OpenWrt provides, so if you have any ideas on how to implement the failover/balancing aspect, please lmk.

1 Like

I’m not sure I can be of any help with under-the-hood details. But, on the UI/UX side, I’d start with separating the concepts of a policy and a rule (like in mwan3). This would allow for bulk management of a large set of rules and provide a framework for policies more flexible than just setting the destination interface (e.g., tun0 → wan → blackhole in order of priority), which could later be expanded to balancing and route health-based failover.

Hi, regarding sleep function on script:

I suggest to add this:

first_domain="$(awk -F'/' 'NF>=2 && $2 != "" {print $2; exit}' "$nftset")"

if [ -n "$first_domain" ]; then
	logger -t pbr-dns-prefetch "Waiting for dnsmasq to resolve $first_domain..."
	for i in $(seq 1 20); do
		if nslookup "$first_domain" 127.0.0.1 >/dev/null 2>&1; then
			logger -t pbr-dns-prefetch "dnsmasq resolved $first_domain after $i s"
			break
		fi
		sleep 1
	done
else
	logger -t pbr-dns-prefetch "No domain found in $nftset, skipping wait"
fi

instead of sleep 3

Actually, I’m not sure waiting after dnsmasq restart was even necessary in the first place. When the dnsmasq.dns object has been added to ubus, it stands to reason that dnsmasq is ready to serve DNS queries too. With or without sleep 3, the prefetching begins after the following line has appeared in syslog:

Sat Sep 6 22:03:35 2025 daemon.info dnsmasq[1]: using nameserver 127.0.0.1#5054

So, I dropped the sleep 3. + Some cleanup in gist.

Yes, but if there isn’t internet connection because delay of DSL (example) it fail to resolve, it is better to wait…

Ah, but for cases like that there is the boot_timeout option in the pbr config. And when restarting pbr manually, interfaces don’t reset. BTW, good idea to check nslookup’s exit code, I borrowed it.

I have switched to SNAPSHOT today and I’m having two dumb questions.
First of all, this is because on the SNAPHOT, I am stuck on Version 1.1.8-r36.
And there is nothing about the tunnel details below the service status.
`echo '``https://apk.openwrt.melmac.ca/packages.adb``' > /etc/apk/repositories.d/apk.openwrt.melmac.ca.list
wget ``https://apk.openwrt.melmac.ca/apk.openwrt.melmac.ca.pem`` -O /etc/apk/keys/apk.openwrt.melmac.ca.pem
``

When I run the installation command

root@DL-WRX36:~# apk update
[https://apk.openwrt.melmac.ca/packages.adb][https://downloads.openwrt.org/snapshots/targets/qualcommax/ipq807x/packages/packages.adb][https://downloads.openwrt.org/snapshots/packages/aarch64_cortex-a53/base/packages.adb][https://downloads.openwrt.org/snapshots/targets/qualcommax/ipq807x/kmods/6.12.44-1-f303594233a88b3642072fcd51ae8a8a/packages.adb][https://downloads.openwrt.org/snapshots/packages/aarch64_cortex-a53/luci/packages.adb][https://downloads.openwrt.org/snapshots/packages/aarch64_cortex-a53/packages/packages.adb][https://downloads.openwrt.org/snapshots/packages/aarch64_cortex-a53/routing/packages.adb][https://downloads.openwrt.org/snapshots/packages/aarch64_cortex-a53/telephony/packages.adb][https://downloads.openwrt.org/snapshots/packages/aarch64_cortex-a53/video/packages.adb]
OK: 10300 distinct packages available
root@DL-WRX36:~# apk add pbr luci-app-pbr
OK: 459 MiB in 435 packages
root@DL-WRX36:~#

Why am I not getting 1.1.9-r23 ??

Try this:

cd /tmp
wget https://dev.melmac.ca/apk/pbr-1.1.9-r23.apk
wget https://dev.melmac.ca/apk/luci-app-pbr-1.1.9-r23.apk
service pbr stop
apk del luci-app-pbr pbrapk add --allow-untrusted ./*.apk
service pbr start
1 Like

Thank you for this. I was hoping for an automated way to achieve the same - so all I have to do is run
``
apk add pbr luci-app-pbr
``

BTW, I tried to understand your script and how I can use it, but I am still floating.
How do I install and use it?

Put it in any persistent directory (like /opt or /etc), then add the path to the script to the list at the bottom of the luci-app-pbr page and enable it. It should run automatically whenever pbr is restarted.

P.S. Take the updated revision from gist. I had to bring back the wait period before nslookup until a better solution is found to make sure the nft sets are ready.

2 Likes

Hi all, I was wondering if someone could help me out with something. I want to be able to have a sort of “kill switch” when either PBR isn’t up or when my Wireguard client has failed. I’ve had an information leak recently and I realized that I want to make sure I can stop gap it. The first thing I tried was setting Wireguard to be the default route, however this had unexpected consequences as it broke my Homelab being able to recieve WAN communication, and broke the ability for external IPs to ping my OpenWrt router. Is some sort of VPN killswitch dependant on if PBR isn’t running and/or if Wireguard is down? It feels like it may not be currently but I may be overcomplicating the solution.

Thanks!

You can set default route via WireGuard and have access to your homelab if you use PBR to route the correct port out of the WAN.
For WireGuard the PBR app will do this automatically it takes the listen port of the WG interface and routes this via the WAN.

For a simple killswitch with default route via the WAN you just remove the firewall forwarding from lan firewall zone to wan zone and only have forwarding between lan and VPN zone.

For connection from outside you have to make traffic rules to allow that specific traffic to go out via the wan

1 Like

How would I go about routing ports out of WAN in PBR? Would I use something like CIDR to set every “local” IP except the ones that are routing to the VPN? I apologize in advance if that’s a dumb question, I’m just not sure how to go about it.

Also, for the firewall zones, just so I’m understanding you mean a layout that would be like this:
Zones → Forwards
LAN → VPN
VPN → WAN
and then PBR would route the domains I want bypassed to WAN? (For example, let’s say I want to visit openwrt.org from my home IP address instead of the VPN due to a block, this zone configuration would work?)

And the last one, I’ve currently got my homelab set up in dual-stack (IPv4/IPv6) mode. Instead of port forwarding for IPv4 and traffic rules for IPv6, would I set up traffic rules for both IPv4 and IPv6?

I want to make sure I have everything correct before I start changing my config around. Thank you so much! :slight_smile:

yes

No this is not necessary

But you better start a separate thread in the Installing and using section , describe your problem and what you want to achieve and post your current config e.g.:

Please connect to your OpenWRT device using ssh and copy the output of the following commands and post it here using the "Preformatted text </> " button

Remember to redact keys, passwords, MAC addresses and any public IP addresses you may have but do not redact private RFC 1918 IP addresses as that is not needed:

ubus call system board
cat /etc/config/network
cat /etc/config/firewall
ip route show
ip -6 route show
ip route show table all
ip rule show
#if you already use the PBR app then :
cat /etc/config/pbr
service pbr status

There are several ways to deal with this

1 Like

Hi, I have an annoying issue across all versions of PBR. I have multiple WANs with static IP addresses, and one of these WANs is set up with PPPoE.

After losing/reloading the PPPoE connection, on_interface_reload is triggered, but routing no longer works. A PBR restart is required.

Thu Sep 11 09:40:07 2025 user.notice pbr [120895]: Processing environment (on_interface_reload) [✓]
Thu Sep 11 09:40:07 2025 user.notice pbr [120895]: Reloading routing for 'wan1/pppoe-wan1/x.x.x.x' [✓]
Thu Sep 11 09:40:07 2025 user.notice pbr [120895]: Setting interface trigger for wan0 [✓]
Thu Sep 11 09:40:07 2025 user.notice pbr [120895]: Setting interface trigger for wg0 [✓]
Thu Sep 11 09:40:07 2025 user.notice pbr [120895]: Setting interface trigger for wan2 [✓]
Thu Sep 11 09:40:07 2025 user.notice pbr [120895]: Setting interface trigger for wan1 [✓]

I think since the firewall trigger was fully removed this issue became more prominent. I’ll try to update the 1.1.9 tree to fully restart at on_interface_reload instead.

PS. Fixed in pbr 1.1.9-r27.

Hello!

I’ve just updated to 1.1.9-r27 and now am in a sort of a bricked state. Pbr is infinitely creating files in my /tmp/ directory named something like pbr_tmp.XX. Due to this the whole system thinks that there is no space left and I can’t even reinstall new image on the router.

I’ve disabled pbr in /etc/config/pbr and rebooted. LuCI shows that the service is disabled, but it’s still running and creating all these files. Need help to get me out of this state.

Using any service pbr anything does not help as the command just hangs indefinitely.

I think (knowing nothing about pbr or its code) that this whileloop is what's causing this:

This looks like a logic bug to me.

1 Like

I have updated to the same version and see no issues:

root@DL-WRX36:~# service pbr restart
Resetting chains and sets [✓]
Removing routing for 'wan/192.168.1.1' [✓]
Removing routing for 'wg0/10.5.0.2' [✓]
Removing routing for 'nordvpntun0/tun0/0.0.0.0' [✓]
pbr 1.1.9-r27 (fw4 nft file mode) stopped [✓]
Using uplink interface (on_start): wan [✓]
Found uplink gateway (on_start): 192.168.1.1 [✓]
Processing environment (on_start) [✓]
Setting up routing for 'wan/192.168.1.1' [✓]
Setting up routing for 'wg0/10.5.0.2' [✓]
Setting up routing for 'nordvpntun0/tun0/0.0.0.0' [✓]
Routing 'Via WAN' via wan [✓]
Routing 'Paypal' via wan [✓]
Routing 'chatgpt_via_wan' via wan [✓]
Routing 'stanbic_internet_banking' via wan [✓]
Routing 'aliexpress.com' via wan [✓]
Routing 'odoo.com' via wan [✓]
Routing 'noip.com' via wan [✓]
Routing 'Wyze' via wan [✓]
Routing 'VanessaFireTV' via wan [✓]
Routing 'Panafcon' via wan [✓]
Routing 'eCitizen' via wan [✓]
Routing 'Oraimo' via wan [✓]
Routing 'eBay' via wan [✓]
Routing 'ZA' via wan [✓]
Routing 'Mara.Cloud' via wan [✓]
Routing 'Microsoft Live' via wan [✓]
Routing 'DDNS' via wan [✓]
Routing 'CSL Sophos' via wan [✓]
Routing 'Telenet Solutions' via wan [✓]
Routing 'Sophos' via wan [✓]
Routing 'joinhoney' via wan [✓]
Routing 'Starlink' via wan [✓]
Routing 'RC.ORG' via wan [✓]
Routing 'techpowerup.com' via wan [✓]
Routing 'IAWRT' via wan [✓]
Running /usr/share/pbr/pbr.user.ke.lst [✓]
Running /usr/share/pbr/pbr.dns.prefetch [✓]
Installing fw4 nft file [✓]
Restarting dnsmasq [✓]
Setting interface trigger for wan [✓]
Setting interface trigger for wan6 [✓]
Setting interface trigger for wg0 [✓]
Setting interface trigger for nordvpntun0 [✓]
pbr 1.1.9-r27 monitoring interfaces: wan wan6 wg0 nordvpntun0
pbr 1.1.9-r27 (fw4 nft file mode) started with gateways:
wan/192.168.1.1
wg0/10.5.0.2 [✓]
nordvpntun0/tun0/0.0.0.0
tor/53->9053/80,443->9040
root@DL-WRX36:~#