Policy-Based-Routing (pbr) package discussion

I have a device with a static IP configured to be routed via VPN.
On this device, there is an app that connects to a specific remote host: foobar.com. If I route foobar.com via WAN, which policy takes precedence over the other? Is it the device policy or the domain policy?

Anything unclear about https://docs.openwrt.melmac.net/pbr/#PoliciesPriorities ?

1 Like

Occasionally PBR crashes after a reload from my firewall (probably caused by my VPN switching)..when this happens I lose connectivity with the IP addresses I have set within PBR and have to manually restart it to get connectivity working again.

You can try to upgrade to the latest PBR 1.1.7-61 and increase the boot and reload delays, if you are using things like OpenVPN you often need delays > 30 sec to wait for the OpenVPN to come up again.
WireGuard usually works better in this department

1 Like

A couple of days ago, pbr stopped working all of a sudden. After a few hours of unsuccessful troubleshooting, I've decided to flash a clean snapshot and install the latest pbr 1.1.7-61 on it. I've chosen snapshot because rc1 lacks some important packages.

Once again, I'm having troubles with domain-based policies. IP-based policy works, yet domain-based policy doesn't. Can't identify a problem and need help.

ubus call system board

{
"kernel": "6.6.63",
"hostname": "OpenWrt",
"system": "ARMv8 Processor rev 0",
"model": "FriendlyElec NanoPi R6S",
"board_name": "friendlyarm,nanopi-r6s",
"rootfs_type": "squashfs",
"release": {
"distribution": "OpenWrt",
"version": "SNAPSHOT",
"revision": "r28243-41f7322853",
"target": "rockchip/armv8",
"description": "OpenWrt SNAPSHOT r28243-41f7322853",
"builddate": "1733167822"
}
}

uci export dhcp

package dhcp

config dnsmasq
option domainneeded '1'
option boguspriv '1'
option filterwin2k '0'
option localise_queries '1'
option rebind_protection '1'
option rebind_localhost '1'
option local '/lan/'
option domain 'lan'
option expandhosts '1'
option nonegcache '0'
option cachesize '1000'
option authoritative '1'
option readethers '1'
option leasefile '/tmp/dhcp.leases'
option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
option nonwildcard '1'
option localservice '1'
option ednspacket_max '1232'
option filter_aaaa '0'
option filter_a '0'
list server '/.themoviedb.org/9.9.9.9'
list server '/.tmdb.org/9.9.9.9'
list server '/tmdb-image-prod.b-cdn.net/9.9.9.9'

config dhcp 'lan'
option interface 'lan'
option start '100'
option limit '150'
option leasetime '12h'
option dhcpv4 'server'
option dhcpv6 'server'
option ra 'server'
option ra_slaac '1'
list ra_flags 'managed-config'
list ra_flags 'other-config'
option force '1'

config dhcp 'wan'
option interface 'wan'
option ignore '1'

config odhcpd 'odhcpd'
option maindhcp '0'
option leasefile '/tmp/hosts/odhcpd'
option leasetrigger '/usr/sbin/odhcpd-update'
option loglevel '4'

uci export firewall

package firewall

config defaults
option syn_flood '1'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'

config zone
option name 'lan'
list network 'lan'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'

config zone
option name 'wan'
list network 'wan'
list network 'wan6'
option input 'REJECT'
option output 'ACCEPT'
option forward 'REJECT'
option masq '1'
option mtu_fix '1'

config forwarding
option src 'lan'
option dest 'wan'

config rule
option name 'Allow-DHCP-Renew'
option src 'wan'
option proto 'udp'
option dest_port '68'
option target 'ACCEPT'
option family 'ipv4'

config rule
option name 'Allow-Ping'
option src 'wan'
option proto 'icmp'
option icmp_type 'echo-request'
option family 'ipv4'
option target 'ACCEPT'

config rule
option name 'Allow-IGMP'
option src 'wan'
option proto 'igmp'
option family 'ipv4'
option target 'ACCEPT'

config rule
option name 'Allow-DHCPv6'
option src 'wan'
option proto 'udp'
option dest_port '546'
option family 'ipv6'
option target 'ACCEPT'

config rule
option name 'Allow-MLD'
option src 'wan'
option proto 'icmp'
option src_ip 'fe80::/10'
list icmp_type '130/0'
list icmp_type '131/0'
list icmp_type '132/0'
list icmp_type '143/0'
option family 'ipv6'
option target 'ACCEPT'

config rule
option name 'Allow-ICMPv6-Input'
option src 'wan'
option proto 'icmp'
list icmp_type 'echo-request'
list icmp_type 'echo-reply'
list icmp_type 'destination-unreachable'
list icmp_type 'packet-too-big'
list icmp_type 'time-exceeded'
list icmp_type 'bad-header'
list icmp_type 'unknown-header-type'
list icmp_type 'router-solicitation'
list icmp_type 'neighbour-solicitation'
list icmp_type 'router-advertisement'
list icmp_type 'neighbour-advertisement'
option limit '1000/sec'
option family 'ipv6'
option target 'ACCEPT'

config rule
option name 'Allow-ICMPv6-Forward'
option src 'wan'
option dest '*'
option proto 'icmp'
list icmp_type 'echo-request'
list icmp_type 'echo-reply'
list icmp_type 'destination-unreachable'
list icmp_type 'packet-too-big'
list icmp_type 'time-exceeded'
list icmp_type 'bad-header'
list icmp_type 'unknown-header-type'
option limit '1000/sec'
option family 'ipv6'
option target 'ACCEPT'

config rule
option name 'Allow-IPSec-ESP'
option src 'wan'
option dest 'lan'
option proto 'esp'
option target 'ACCEPT'

config rule
option name 'Allow-ISAKMP'
option src 'wan'
option dest 'lan'
option dest_port '500'
option proto 'udp'
option target 'ACCEPT'

config zone
option name 'singbox'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
option masq '1'
list network 'sb0'
list network 'sb1'

config forwarding
option src 'lan'
option dest 'singbox'

config include 'pbr'
option fw4_compatible '1'
option type 'script'
option path '/usr/share/pbr/firewall.include'

uci export network

package network

config interface 'loopback'
option device 'lo'
option proto 'static'
option ipaddr '127.0.0.1'
option netmask '255.0.0.0'

config globals 'globals'
option ula_prefix 'fd3f:3d54:ab27::/48'

config device
option name 'br-lan'
option type 'bridge'
list ports 'eth0'
list ports 'eth2'

config device
option name 'eth0'
option macaddr 'xx:xx:xx:xx:xx:xx'

config device
option name 'eth2'
option macaddr 'xx:xx:xx:xx:xx:xx'

config interface 'lan'
option device 'br-lan'
option proto 'static'
option ipaddr '10.10.1.1'
option netmask '255.255.255.0'
option ip6assign '60'

config device
option name 'eth1'
option macaddr 'xx:xx:xx:xx:xx:xx'

config interface 'wan'
option device 'eth1'
option proto 'dhcp'
option peerdns '0'
option dns '1.1.1.1 8.8.8.8 9.9.9.9'

config interface 'wan6'
option device 'eth1'
option proto 'dhcpv6'

config interface 'sb0'
option proto 'none'
option device 'sb0'

config interface 'sb1'
option proto 'none'
option device 'sb1'

uci export pbr

package pbr

config pbr 'config'
option enabled '1'
option verbosity '2'
option strict_enforcement '1'
option resolver_set 'dnsmasq.nftset'
list resolver_instance '*'
option ipv6_enabled '0'
list ignored_interface 'vpnserver'
option boot_timeout '30'
option rule_create_option 'add'
option procd_boot_delay '0'
option procd_reload_delay '1'
option webui_show_ignore_target '0'
option nft_rule_counter '1'
option nft_set_auto_merge '1'
option nft_set_counter '1'
option nft_set_flags_interval '1'
option nft_set_flags_timeout '0'
option nft_set_policy 'performance'
list webui_supported_protocol 'all'
list webui_supported_protocol 'tcp'
list webui_supported_protocol 'udp'
list webui_supported_protocol 'tcp udp'
list webui_supported_protocol 'icmp'

config include
option path '/usr/share/pbr/pbr.user.aws'
option enabled '0'

config include
option path '/usr/share/pbr/pbr.user.netflix'
option enabled '0'

config dns_policy
option name 'Redirect Local IP DNS'
option src_addr '192.168.1.5'
option dest_dns '1.1.1.1'
option enabled '0'

config policy
option name 'DOMAIN'
option dest_addr 'myip.is'
option interface 'sb0'

config policy
option name 'ADDRESS'
option dest_addr '89.36.33.33'
option interface 'sb0'
option enabled '0'

/etc/init.d/pbr status

pbr - environment
pbr 1.1.7-61 running on OpenWrt SNAPSHOT.

Dnsmasq version 2.90 Copyright (c) 2000-2024 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus UBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP conntrack no-ipset nftset auth cryptohash DNSSEC no-ID loop-detect inotify dumpfile

pbr fw4 nft file: /usr/share/nftables.d/ruleset-post/30-pbr.nft
add chain inet fw4 pbr_mark_0x010000
add rule inet fw4 pbr_mark_0x010000 counter mark set mark and 0xff00ffff xor 0x010000
add rule inet fw4 pbr_mark_0x010000 return
add chain inet fw4 pbr_mark_0x020000
add rule inet fw4 pbr_mark_0x020000 counter mark set mark and 0xff00ffff xor 0x020000
add rule inet fw4 pbr_mark_0x020000 return
add chain inet fw4 pbr_mark_0x030000
add rule inet fw4 pbr_mark_0x030000 counter mark set mark and 0xff00ffff xor 0x030000
add rule inet fw4 pbr_mark_0x030000 return
add set inet fw4 pbr_sb0_4_dst_ip_cfg056ff5 { type ipv4_addr; auto-merge; counter; flags interval; policy performance; comment "DOMAIN";}
add rule inet fw4 pbr_prerouting ip daddr @pbr_sb0_4_dst_ip_cfg056ff5 counter goto pbr_mark_0x020000 comment "DOMAIN"

pbr chains - policies
chain pbr_forward { # handle 228
}
chain pbr_input { # handle 229
}
chain pbr_output { # handle 230
}
chain pbr_postrouting { # handle 232
}
chain pbr_prerouting { # handle 231
ip daddr @pbr_sb0_4_dst_ip_cfg056ff5 counter packets 0 bytes 0 goto pbr_mark_0x020000 comment "DOMAIN" # handle 1634
}
chain pbr_dstnat { # handle 227
}

pbr chains - marking
chain pbr_mark_0x010000 { # handle 1624
counter packets 0 bytes 0 meta mark set meta mark & 0xff01ffff | 0x00010000 # handle 1625
return # handle 1626
}
chain pbr_mark_0x020000 { # handle 1627
counter packets 0 bytes 0 meta mark set meta mark & 0xff02ffff | 0x00020000 # handle 1628
return # handle 1629
}
chain pbr_mark_0x030000 { # handle 1630
counter packets 0 bytes 0 meta mark set meta mark & 0xff03ffff | 0x00030000 # handle 1631
return # handle 1632
}

pbr nft sets
set pbr_sb0_4_dst_ip_cfg056ff5 { # handle 1633
type ipv4_addr
flags interval
counter
auto-merge
comment "DOMAIN"
}

dnsmasq sets
nftset=/myip.is/4#inet#fw4#pbr_sb0_4_dst_ip_cfg056ff5 # DOMAIN

IPv4 table 256 pbr_wan route:
default via xx.xx.xx.xx dev eth1
IPv4 table 256 pbr_wan rule(s):
30000: from all fwmark 0x10000/0xff0000 lookup pbr_wan

IPv4 table 257 pbr_sb0 route:
default via 172.16.250.1 dev sb0
IPv4 table 257 pbr_sb0 rule(s):
29998: from all fwmark 0x20000/0xff0000 lookup pbr_sb0

IPv4 table 258 pbr_sb1 route:
default via 172.16.251.1 dev sb1
IPv4 table 258 pbr_sb1 rule(s):
29996: from all fwmark 0x30000/0xff0000 lookup pbr_sb1

/etc/init.d/pbr reload

Using wan interface (on_start): wan
Found wan gateway (on_start): xx.xx.xx.xx
Setting up routing for 'wan/eth1/xx.xx.xx.xx' [โœ“]
Setting up routing for 'sb0/172.16.250.1' [โœ“]
Setting up routing for 'sb1/172.16.251.1' [โœ“]
Routing 'DOMAIN' via sb0 [โœ“]
Installing fw4 nft file [โœ“]
pbr 1.1.7-61 monitoring interfaces: wan sb0 sb1
pbr 1.1.7-61 (fw4 nft file mode) started with gateways:
wan/eth1/xx.xx.xx.xx [โœ“]
sb0/172.16.250.1
sb1/172.16.251.1

/etc/init.d/pbr status

pbr - environment
pbr 1.1.7-61 running on OpenWrt SNAPSHOT.

Dnsmasq version 2.90 Copyright (c) 2000-2024 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus UBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP conntrack no-ipset nftset auth cryptohash DNSSEC no-ID loop-detect inotify dumpfile

pbr fw4 nft file: /usr/share/nftables.d/ruleset-post/30-pbr.nft
add chain inet fw4 pbr_mark_0x010000
add rule inet fw4 pbr_mark_0x010000 counter mark set mark and 0xff00ffff xor 0x010000
add rule inet fw4 pbr_mark_0x010000 return
add chain inet fw4 pbr_mark_0x020000
add rule inet fw4 pbr_mark_0x020000 counter mark set mark and 0xff00ffff xor 0x020000
add rule inet fw4 pbr_mark_0x020000 return
add chain inet fw4 pbr_mark_0x030000
add rule inet fw4 pbr_mark_0x030000 counter mark set mark and 0xff00ffff xor 0x030000
add rule inet fw4 pbr_mark_0x030000 return
add set inet fw4 pbr_sb0_4_dst_ip_cfg056ff5 { type ipv4_addr; auto-merge; counter; flags interval; policy performance; comment "DOMAIN";}
add rule inet fw4 pbr_prerouting ip daddr @pbr_sb0_4_dst_ip_cfg056ff5 counter goto pbr_mark_0x020000 comment "DOMAIN"

pbr chains - policies
chain pbr_forward { # handle 228
}
chain pbr_input { # handle 229
}
chain pbr_output { # handle 230
}
chain pbr_postrouting { # handle 232
}
chain pbr_prerouting { # handle 231
ip daddr @pbr_sb0_4_dst_ip_cfg056ff5 counter packets 0 bytes 0 goto pbr_mark_0x020000 comment "DOMAIN" # handle 1736
}
chain pbr_dstnat { # handle 227
}

pbr chains - marking
chain pbr_mark_0x010000 { # handle 1726
counter packets 0 bytes 0 meta mark set meta mark & 0xff01ffff | 0x00010000 # handle 1727
return # handle 1728
}
chain pbr_mark_0x020000 { # handle 1729
counter packets 0 bytes 0 meta mark set meta mark & 0xff02ffff | 0x00020000 # handle 1730
return # handle 1731
}
chain pbr_mark_0x030000 { # handle 1732
counter packets 0 bytes 0 meta mark set meta mark & 0xff03ffff | 0x00030000 # handle 1733
return # handle 1734
}

pbr nft sets
set pbr_sb0_4_dst_ip_cfg056ff5 { # handle 1735
type ipv4_addr
flags interval
counter
auto-merge
comment "DOMAIN"
}

dnsmasq sets
nftset=/myip.is/4#inet#fw4#pbr_sb0_4_dst_ip_cfg056ff5 # DOMAIN

IPv4 table 256 pbr_wan route:
default via xx.xx.xx.xx dev eth1
IPv4 table 256 pbr_wan rule(s):
30000: from all fwmark 0x10000/0xff0000 lookup pbr_wan

IPv4 table 257 pbr_sb0 route:
default via 172.16.250.1 dev sb0
IPv4 table 257 pbr_sb0 rule(s):
29998: from all fwmark 0x20000/0xff0000 lookup pbr_sb0

IPv4 table 258 pbr_sb1 route:
default via 172.16.251.1 dev sb1
IPv4 table 258 pbr_sb1 rule(s):
29996: from all fwmark 0x30000/0xff0000 lookup pbr_sb1

EDIT: fixed it after I saw this by setting confdir to the old path. Never would have though to check it myself!

A few things to check, if you use nftset make sure you reboot the router to make sure DNS cache is flushed or do

service pbr stop && service pbr start && killall -HUP dnsmasq

Also reboot the client.

You can check if the ip addresses are added to the firewall with: nft list ruleset

Furthermore DNSMasq has been update to make multiple config directories possible so check the DNSmasq default directory

FWIW it works on my DL-WRX36 running latest snapshot

Edit: our posts crossed I saw you already found it :+1:

The most recent versions of pbr use nft files and are not even ran when firewall is reloaded.

PSA: DO NOT USE SNAPSHOTS NOR 24.10.0-rc1 IF YOU ARE USING DOMAIN POLICIES IN PBR.

2 Likes

I've been using this package for over a year, and even though the GUI tells me the service is not running, everything works as expected. After upgrading from 23.05.3 to 23.05.5, pbr will no longer start, and traffic that should be routed over VPN isn't routed. Is this a known problem?

Recently, having worked perfectly after the fixes to the problems I was having a while ago with strict enforcement turned off, I am suddenly seeing my DNS policies not working. The only thing I can think of that has changed in my config from earlier in the thread, is that my isp changed my static ip address and has also started supporting ipv6 and as such in luci, my wan6 interface has been replaced with a virtual dynamic interface (DHCPv6 client) labelled wan_6. Could these changes have caused DNS policies not to work anymore?

How did you test?

It is possible that your LAN clients also get an IPv6 DNS if so they will use that and you can have a DNS leak.
You can check your LAN clients, for Windows: ipconfig /all
This is my Windows PC with both IPv4 and IPv6 DNS server (the routers address)

   DNS Servers . . . . . . . . . . . : 2001:3a02:xxxx:xxxx::1
                                       192.168.0.1

For Linux: nmcli dev show

See my notes: https://github.com/egc112/OpenWRT-egc-add-on/tree/main/stop-dns-leak#pbr-dns-policies

I think this is probably what is happening. NordVPN don't have ipv6 dns servers so would I just be better off disabling ipv6?

One more reason to say goodbye to NordVPN (the other lack of WireGuard support on the router)

If you do not use IPv6 you can disable it (make a backup before disabling so that you can enable it again if desired).
I have IPv6 but my VPN provider supports IPv6 and that works well also for PBR.

This should work to disable it:
Disable IPv6

uci set 'network.lan.ipv6=0'
uci set 'network.wan.ipv6=0'
uci set 'dhcp.lan.dhcpv6=disabled'

# Disable RA and DHCPv6 so no IPv6 IPs are handed out
uci -q delete dhcp.lan.dhcpv6
uci -q delete dhcp.lan.ra

# Disable the LAN delegation
uci set network.lan.delegate="0"

# Delete the IPv6 ULA Prefix
uci -q delete network.globals.ula_prefix

# Disable odhcpd
/etc/init.d/odhcpd disable
/etc/init.d/odhcpd stop

# Save changes
uci commit
/etc/init.d/network restart
1 Like

No it isn't.

Can someone help me? My pbr fails to start ans I fail to find the reason:

Errors:
Service Status
Version 1.1.7-61 - Running (fw4 nft file mode).
Service Gateways
digi/pppoe-digi/10.0.15.57 โœ“
The โœ“ indicates default gateway. See the README for details.
Please donate to support development of this project.

Service Errors
Unknown error!
Failed to set up 'SPProton/0.0.0.0'!
Unknown error!
Failed to set up 'ProtonUS/10.2.0.2'!
Unknown error!
Failed to set up 'openvpn/tun0/0.0.0.0'!
Errors encountered, please check the README!

Someone else already had this issue? I have two wireguard interfaces and on OpenVPN. Ping works in all of them using "ping -I "interface" 8.8.8.8"

The 0.0.0.0 indicate the tunnels are not up or not found.

I also have multiple WG and OpenVPN tunnels and that works for me

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:

ubus call system board
cat /etc/config/network
cat /etc/config/firewall
ip route show
ip rule show
wg show
cat /etc/config/pbr
/etc/init.d/pbr reload
/etc/init.d/pbr status
cat /var/run/pbr.nft
nft -c -f /var/run/pbr.nft

egc I appreciatte your time to help me on this.
I started changing some IPs but some of them are internal so nevermind some being different of the others. It wwas just me losing track of it.

ubus call system board

{
        "kernel": "6.6.61",
        "hostname": "OpenWrt",
        "system": "ARMv8 Processor rev 4",
        "model": "GL.iNet GL-MT6000",
        "board_name": "glinet,gl-mt6000",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "SNAPSHOT",
                "revision": "r28320-e01af5e8d6",
                "target": "mediatek/filogic",
                "description": "OpenWrt SNAPSHOT r28320-e01af5e8d6",
                "builddate": "1732212090"
        }
}

cat /etc/config/network

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix 'fd4f:5cc5:2e34::/48'

config device
        option name 'br-lan'
        option type 'bridge'
        list ports 'lan1'
        list ports 'lan2'
        list ports 'lan3'
        list ports 'lan4'
        list ports 'lan5'

config interface 'lan'
        option device 'br-lan'
        option proto 'static'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'
        option ip6assign '60'

config device
        option type '8021q'
        option ifname 'eth1'
        option vid '20'
        option name 'eth1.20'
        option mtu '1508'
        option mtu6 '1508'

config device
        option name 'eth1'
        option mtu '1512'
        option mtu6 '1512'

config interface 'digi'
        option proto 'pppoe'
        option device 'eth1.20'
        option username '123@123'
        option password '123'
        option ipv6 'auto'
        option mtu '1500'

config interface 'tailscale'
        option proto 'none'
        option device 'tailscale0'

config interface 'SPProton'
        option proto 'wireguard'
        option private_key 'qredtfyguhijokpl+รงยด3q7'
        list addresses '10.12.3.21/32'
        list dns '10.2.0.1'

config wireguard_SPProton
        option description 'Imported peer configuration'
        option public_key 'qredtfyguhijokpl+รงยด3q7'
        option endpoint_host '10.72.91.112'
        option endpoint_port '51820'
        list allowed_ips '0.0.0.0/0'

config interface 'ProtonUS'
        option proto 'wireguard'
        option private_key 'qredtfyguhijokpl+รงยด3q7'
        list addresses '10.2.0.2/32'
        list dns '10.2.0.1'

config wireguard_ProtonUS
        option description 'Imported peer configuration'
        option public_key 'qredtfyguhijokpl+รงยด3q7'
        list allowed_ips '0.0.0.0/0'
        option endpoint_host '10.12.19.26'
        option endpoint_port '51820'

config interface 'openvpn'
        option proto 'none'
        option device 'tun0'

cat /etc/config/firewall

config defaults
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'
        option flow_offloading '1'
        option flow_offloading_hw '1'

config zone
        option name 'lan'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'lan'

config zone
        option name 'wan'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        option mtu_fix '1'
        list network 'digi'

config forwarding
        option src 'lan'
        option dest 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

config zone
        option name 'tailscale'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        option masq '1'
        option mtu_fix '1'
        list network 'tailscale'

config forwarding
        option src 'tailscale'
        option dest 'wan'

config forwarding
        option src 'lan'
        option dest 'tailscale'

config forwarding
        option src 'tailscale'
        option dest 'lan'

config forwarding
        option src 'wan'
        option dest 'tailscale'

config include 'pbr'
        option fw4_compatible '1'
        option type 'script'
        option path '/usr/share/pbr/firewall.include'

config zone
        option name 'Vpnzone'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option masq '1'
        list network 'ProtonUS'
        list network 'SPProton'
        list network 'openvpn'

config forwarding
        option src 'Vpnzone'
        option dest 'lan'

config forwarding
        option src 'lan'
        option dest 'Vpnzone'

ip route show

default via 10.0.15.57 dev pppoe-digi proto static
10.0.15.57 dev pppoe-digi proto kernel scope link src 100.64.129.104
10.96.0.0/16 dev tun0 proto kernel scope link src 10.96.0.15
31.13.189.226 via 10.0.15.57 dev pppoe-digi proto static
146.70.98.162 via 10.0.15.57 dev pppoe-digi proto static
192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.1

ip rule show

0:      from all lookup local
1:      from all fwmark 0x10000/0xff0000 lookup pbr_digi
5210:   from all fwmark 0x80000/0xff0000 lookup main
5230:   from all fwmark 0x80000/0xff0000 lookup default
5250:   from all fwmark 0x80000/0xff0000 unreachable
5270:   from all lookup 52
32766:  from all lookup main
32767:  from all lookup default

wg show

interface: ProtonUS
  public key: awwaesrdftgyuhjiok,lp.รง567
  private key: (hidden)
  listening port: 5194

peer: awwaesrdftgyuhjiok,lp.รง567
  endpoint: 31.123.119.26:51820
  allowed ips: 0.0.0.0/0

interface: SPProton
  public key: awwaesrdftgyuhjiok,lp.รง567
  private key: (hidden)
  listening port: 5441

peer: awwaesrdftgyuhjiok,lp.รง567
  endpoint: 146.74.92.12:51820
  allowed ips: 0.0.0.0/0

cat /etc/config/pbr

config pbr 'config'
        option enabled '1'
        option verbosity '2'
        option strict_enforcement '1'
        option resolver_set 'dnsmasq.nftset'
        list resolver_instance '*'
        option ipv6_enabled '0'
        option boot_timeout '30'
        option rule_create_option 'add'
        option procd_boot_delay '0'
        option procd_reload_delay '1'
        option webui_show_ignore_target '0'
        option nft_rule_counter '0'
        option nft_set_auto_merge '1'
        option nft_set_counter '0'
        option nft_set_flags_interval '1'
        option nft_set_flags_timeout '0'
        option nft_set_policy 'performance'
        list webui_supported_protocol 'all'
        list webui_supported_protocol 'tcp'
        list webui_supported_protocol 'udp'
        list webui_supported_protocol 'tcp udp'
        list webui_supported_protocol 'icmp'
        list ignored_interface 'tailscale'
        option wan_ip_rules_priority '1'
        list supported_interface 'pppoe-digi'

config include
        option path '/usr/share/pbr/pbr.user.aws'
        option enabled '0'

config include
        option path '/usr/share/pbr/pbr.user.netflix'
        option enabled '0'

config dns_policy
        option name 'Redirect Local IP DNS'
        option src_addr '192.168.1.206'
        option dest_dns '1.1.1.1'
        option enabled '0'

config policy
        option name 'pingtest'
        option dest_addr '8.8.8.8'
        option interface 'ProtonUS'
        option src_addr '192.168.1.206'

config policy
        option name 'Ignore Local Requests'
        option interface 'ignore'
        option dest_addr '10.0.0.0/24 10.0.1.0/24 192.168.100.0/24 192.168.1.0/24'
        option enabled '0'

config policy
        option name 'Plex/Emby Local Server'
        option interface 'digi'
        option src_port '8096 8920 32400'
        option enabled '0'

config policy
        option name 'Plex/Emby Remote Servers'
        option interface 'digi'
        option dest_addr 'plex.tv my.plexapp.com emby.media app.emby.media tv.emby.media'
        option enabled '0'

/etc/init.d/pbr reload

Using wan interface (on_start): wan
Setting up routing for 'digi/pppoe-digi/10.0.15.57' [โœ“]
Setting up routing for 'SPProton/10.2.0.2' [โœ—]
Setting up routing for 'ProtonUS/10.2.0.2' [โœ—]
Setting up routing for 'openvpn/tun0/10.96.0.15' [โœ—]
Routing 'pingtest' via ProtonUS [โœ“]
Installing fw4 nft file [โœ“]
pbr 1.1.7-61 monitoring interfaces: digi SPProton ProtonUS openvpn
pbr 1.1.7-61 (fw4 nft file mode) started with gateways:
digi/pppoe-digi/10.0.15.57 [โœ“]
ERROR:
ip -4 rule add fwmark 0x020000/0xff0000 table 257 priority -1
ERROR: Failed to set up 'SPProton/10.2.0.2'!
ERROR:
ip -4 rule add fwmark 0x030000/0xff0000 table 258 priority -3
ERROR: Failed to set up 'ProtonUS/10.2.0.2'!
ERROR:
ip -4 rule add fwmark 0x040000/0xff0000 table 259 priority -5
ERROR: Failed to set up 'openvpn/tun0/10.96.0.15'!

/etc/init.d/pbr status

pbr - environment
pbr 1.1.7-61 running on OpenWrt SNAPSHOT.

Dnsmasq version 2.90  Copyright (c) 2000-2024 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus UBus no-i18n no-IDN DHCP no-DHCPv6 no-Lua TFTP conntrack no-ipset nftset auth cryptohash DNSSEC no-ID loop-detect inotify dumpfile

pbr fw4 nft file: /usr/share/nftables.d/ruleset-post/30-pbr.nft
add chain inet fw4 pbr_mark_0x010000
add rule inet fw4 pbr_mark_0x010000  mark set mark and 0xff00ffff xor 0x010000
add rule inet fw4 pbr_mark_0x010000 return
add chain inet fw4 pbr_mark_0x020000
add rule inet fw4 pbr_mark_0x020000  mark set mark and 0xff00ffff xor 0x020000
add rule inet fw4 pbr_mark_0x020000 return
add chain inet fw4 pbr_mark_0x030000
add rule inet fw4 pbr_mark_0x030000  mark set mark and 0xff00ffff xor 0x030000
add rule inet fw4 pbr_mark_0x030000 return
add chain inet fw4 pbr_mark_0x040000
add rule inet fw4 pbr_mark_0x040000  mark set mark and 0xff00ffff xor 0x040000
add rule inet fw4 pbr_mark_0x040000 return
add rule inet fw4 pbr_prerouting ip saddr { 192.168.1.206 } ip daddr { 8.8.8.8 }  goto pbr_mark_0x030000 comment "pingtest"

pbr chains - policies
        chain pbr_forward { # handle 36
        }
        chain pbr_input { # handle 37
        }
        chain pbr_output { # handle 38
        }
        chain pbr_postrouting { # handle 40
        }
        chain pbr_prerouting { # handle 39
                ip saddr 192.168.1.206 ip daddr 8.8.8.8 goto pbr_mark_0x030000 comment "pingtest" # handle 7989
        }
        chain pbr_dstnat { # handle 35
        }

pbr chains - marking
        chain pbr_mark_0x010000 { # handle 7977
                meta mark set meta mark & 0xff01ffff | 0x00010000 # handle 7978
                return # handle 7979
        }
        chain pbr_mark_0x020000 { # handle 7980
                meta mark set meta mark & 0xff02ffff | 0x00020000 # handle 7981
                return # handle 7982
        }
        chain pbr_mark_0x030000 { # handle 7983
                meta mark set meta mark & 0xff03ffff | 0x00030000 # handle 7984
                return # handle 7985
        }
        chain pbr_mark_0x040000 { # handle 7986
                meta mark set meta mark & 0xff04ffff | 0x00040000 # handle 7987
                return # handle 7988
        }

pbr nft sets

IPv4 table 256 pbr_digi route:
default via 10.0.15.57 dev pppoe-digi
IPv4 table 256 pbr_digi rule(s):
1:      from all fwmark 0x10000/0xff0000 lookup pbr_digi

IPv4 table 257 pbr_SPProton route:
default via 10.2.0.2 dev SPProton
IPv4 table 257 pbr_SPProton rule(s):

IPv4 table 258 pbr_ProtonUS route:
default via 10.2.0.2 dev ProtonUS
IPv4 table 258 pbr_ProtonUS rule(s):

IPv4 table 259 pbr_openvpn route:
default via 10.96.0.15 dev tun0
IPv4 table 259 pbr_openvpn rule(s):

cat /var/run/pbr.nft

#!/usr/sbin/nft -f

add chain inet fw4 pbr_mark_0x010000
add rule inet fw4 pbr_mark_0x010000  mark set mark and 0xff00ffff xor 0x010000
add rule inet fw4 pbr_mark_0x010000 return
add chain inet fw4 pbr_mark_0x020000
add rule inet fw4 pbr_mark_0x020000  mark set mark and 0xff00ffff xor 0x020000
add rule inet fw4 pbr_mark_0x020000 return
add chain inet fw4 pbr_mark_0x030000
add rule inet fw4 pbr_mark_0x030000  mark set mark and 0xff00ffff xor 0x030000
add rule inet fw4 pbr_mark_0x030000 return
add chain inet fw4 pbr_mark_0x040000
add rule inet fw4 pbr_mark_0x040000  mark set mark and 0xff00ffff xor 0x040000
add rule inet fw4 pbr_mark_0x040000 return
add rule inet fw4 pbr_prerouting ip saddr { 192.168.1.206 } ip daddr { 8.8.8.8 }  goto pbr_mark_0x030000 comment "pingtest"

nft -c -f /var/run/pbr.nft

blank

EDIT:

option endpoint_host '10.72.91.112'

Both endpoint hosts are wrong that needs to be the Proton url or public IP address.
Correct that, reboot and check with wg show that you have a connection with both WG clients

It looks like there is no wan interface, well there is but it is renamed.
In the pbr config you have to specify your new wan name (digi)

Remove this you are opening up your network from the outside, this is really dangerous!

Furthermore you are running tailscale, I have no experience with it but it might be interfering so disable it for now while testing WireGuard and PBR.
After disabling reboot the router

Last thing your OpenVPN might not to be running, we will save that for later first get the WireGuard running with PBR

this is where I got confused. Endpoints for Wireguard are correct.

config wireguard_SPProton
        option description 'Imported peer configuration'
        option public_key 'C3LgiID8tKOhXsu4Tyu8NMz5/WOWZoeZAY41Bybp5gM='
        option endpoint_host '146.70.98.162'
        option endpoint_port '51820'
        list allowed_ips '0.0.0.0/0'

config wireguard_ProtonUS
        option description 'Imported peer configuration'
        option public_key 'PXtm4zWbqySH2QGaI/5ivRVGXPwztXfzMbtoT9Ad0jE='
        list allowed_ips '0.0.0.0/0'
        option endpoint_host '31.13.189.226'
        option endpoint_port '51820'

Interfaces fo wg are indeed working:

root@OpenWrt:~# wg show
interface: ProtonUS
  public key: feZ6/91oo944V83pxk/2VgYvNd6c71yggknS33KSrjs=
  private key: (hidden)
  listening port: 51919

peer: PXtm4zWbqySH2QGaI/5ivRVGXPwztXfzMbtoT9Ad0jE=
  endpoint: 31.13.189.226:51820
  allowed ips: 0.0.0.0/0
  latest handshake: 31 seconds ago
  transfer: 732 B received, 1.30 KiB sent

interface: SPProton
  public key: INSbdbDWXO9L/XWs5mmOru/2BsZK5NHfKbHmWZ9+mis=
  private key: (hidden)
  listening port: 59744

peer: C3LgiID8tKOhXsu4Tyu8NMz5/WOWZoeZAY41Bybp5gM=
  endpoint: 146.70.98.162:51820
  allowed ips: 0.0.0.0/0
  latest handshake: 15 seconds ago
  transfer: 988 B received, 1.52 KiB sent

I have changed the wan name on pbr config:

root@OpenWrt:~# service pbr start
Using wan interface (on_start): digi
Found wan gateway (on_start): 10.0.15.57
Setting up routing for 'digi/pppoe-digi/10.0.15.57' [โœ“]
Setting up routing for 'SPProton/10.2.0.2' [โœ—]
Setting up routing for 'ProtonUS/10.2.0.2' [โœ—]
Setting up routing for 'openvpn/tun0/10.96.0.15' [โœ—]
Routing 'pingtest' via ProtonUS [โœ“]
Installing fw4 nft file [โœ“]
pbr 1.1.7-61 monitoring interfaces: digi SPProton ProtonUS openvpn
pbr 1.1.7-61 (fw4 nft file mode) started with gateways:
digi/pppoe-digi/10.0.15.57 [โœ“]
ERROR:
ip -4 rule add fwmark 0x020000/0xff0000 table 257 priority -1
ERROR: Failed to set up 'SPProton/10.2.0.2'!
ERROR:
ip -4 rule add fwmark 0x030000/0xff0000 table 258 priority -3
ERROR: Failed to set up 'ProtonUS/10.2.0.2'!
ERROR:
ip -4 rule add fwmark 0x040000/0xff0000 table 259 priority -5
ERROR: Failed to set up 'openvpn/tun0/10.96.0.15'!

Wireguard looks OK :+1:

The problem is that something else seems to be setup on your router which interferes with PBR maybe tailscale or something else see: