VPN Policy-Based Routing + Web UI -- Discussion

EDITED TO ADD MORE INFORMATION

Having a weird issue that any VPN policies with dest_addr seem not to work. Source address policies seem to work fine.

DHCP

config dnsmasq
	option domainneeded '1'
	option localise_queries '1'
	option rebind_protection '1'
	option rebind_localhost '1'
	option local '/lan/'
	option domain 'lan'
	option expandhosts '1'
	option authoritative '1'
	option readethers '1'
	option leasefile '/tmp/dhcp.leases'
	option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
	option localservice '1'
	option ednspacket_max '1232'
	option confdir '/tmp/dnsmasq.d'

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

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'

config host
	option name 'GL-B2200-81e'
	option ip '192.168.2.123'
	option mac '94:83:C4:10:78:1E'

config host
	option name 'Living-Room'
	option ip '192.168.2.234'
	option mac 'F0:B3:EC:27:3E:48'

FIREWALL

config defaults
	option input 'ACCEPT'
	option output 'ACCEPT'
	option fullcone '1'
	option forward 'ACCEPT'
	option flow_offloading '1'
	option synflood_protect '1'

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 fullcone4 '1'
	option fullcone6 '1'
	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 'TGzone'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	option masq '1'
	option mtu_fix '1'
	list network 'TorGuard'

config forwarding
	option src 'TGzone'
	option dest 'lan'

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

config include 'miniupnpd'
	option type 'script'
	option path '/usr/share/miniupnpd/firewall.include'

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 'fd00:ab:cd::/48'

config device
	option name 'eth0'
	option macaddr '36:b7:a8:3f:fd:ea'

config interface 'wan'
	option device 'eth0'
	option proto 'dhcp'

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

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

config device
	option name 'eth1'
	option macaddr '36:b7:a8:3f:fd:eb'

config device
	option name 'eth2'
	option macaddr '36:b7:a8:3f:fd:eb'

config interface 'lan'
	option device 'br-lan'
	option proto 'static'
	option ipaddr '192.168.2.1'
	option netmask '255.255.255.0'
	option ip6assign '60'
	list dns '1.1.1.1'
	list dns '1.0.0.1'

config interface 'TorGuard'
	option proto 'wireguard'
	option private_key 'GNskgpKtfxIEbxrLR9ki/ygArrWbzmrqpwsMrChdDFg='
	option listen_port '56450'
	list addresses '10.13.128.101/24'
	option peerdns '0'
	list dns '1.1.1.1'

config wireguard_TorGuard
	option description 'Imported peer configuration'
	option public_key 'B+0xq+lfRWrsnVVfNObXy+Q8q+tMIalSRzZJpoXCxGA='
	list allowed_ips '0.0.0.0/0'
	option persistent_keepalive '25'
	option endpoint_host '71.78.219.130'
	option endpoint_port '1443'

config interface 'docker'
	option device 'docker0'
	option proto 'none'
	option auto '0'

config device
	option type 'bridge'
	option name 'docker0'

VPN-Policy-Routing

config policy
	option name 'AppleTV'
	option src_addr 'F0:B3:EC:27:3E:48'
	option interface 'TorGuard'

config policy
	option name 'iDrive'
	option interface 'TorGuard'
	option dest_addr 'idrive.com wsn7s.idrive.com'

config vpn-policy-routing 'config'
	option verbosity '2'
	option strict_enforcement '1'
	option ipv6_enabled '0'
	list ignored_interface 'vpnserver wgserver'
	option iprule_enabled '0'
	option boot_timeout '30'
	option iptables_rule_option 'append'
	option procd_reload_delay '1'
	option webui_sorting '1'
	option src_ipset '1'
	list webui_supported_protocol 'tcp'
	list webui_supported_protocol 'udp'
	list webui_supported_protocol 'tcp udp'
	list webui_supported_protocol 'icmp'
	list webui_supported_protocol 'all'
	option enabled '1'
	option webui_enable_column '1'
	option webui_protocol_column '1'
	option webui_chain_column '1'
	option webui_show_ignore_target '1'
	option resolver_ipset 'dnsmasq.ipset'
	option dest_ipset '0'

config include
	option path '/etc/vpn-policy-routing.netflix.user'
	option enabled '0'

config include
	option path '/etc/vpn-policy-routing.aws.user'
	option enabled '0'

config policy
	option name 'iDriveFW'
	option dest_addr '148.66.233.128 148.66.233.129 148.66.234.47 148.66.234.51 173.255.13.9'
	option interface 'TorGuard'

SUPPORT OUTPUT

vpn-policy-routing 0.3.4-8 running on OpenWrt 22.03.0.
============================================================
Dnsmasq version 2.86  Copyright (c) 2000-2021 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus UBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth cryptohash DNSSEC no-ID loop-detect inotify dumpfile
============================================================
Routes/IP Rules
default         88.215.96.129.d 0.0.0.0         UG    0      0        0 eth0

IPv4 Table 201: default via 88.215.96.129 dev eth0 
192.168.2.0/24 dev br-lan proto kernel scope link src 192.168.2.1 
IPv4 Table 201 Rules:
32765:	from all fwmark 0x10000/0xff0000 lookup wan

IPv4 Table 202: default via 10.13.128.101 dev TorGuard 
192.168.2.0/24 dev br-lan proto kernel scope link src 192.168.2.1 
IPv4 Table 202 Rules:
32764:	from all fwmark 0x20000/0xff0000 lookup TorGuard
============================================================
Mangle IP Table: PREROUTING
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-N VPR_PREROUTING
-A VPR_PREROUTING -m set --match-set TorGuard_mac src -c 3598 371298 -g VPR_MARK0x020000
-A VPR_PREROUTING -m set --match-set TorGuard_ip src -c 0 0 -g VPR_MARK0x020000
-A VPR_PREROUTING -m set --match-set TorGuard dst -c 0 0 -g VPR_MARK0x020000
-A VPR_PREROUTING -m set --match-set wan_mac src -c 0 0 -g VPR_MARK0x010000
-A VPR_PREROUTING -m set --match-set wan_ip src -c 0 0 -g VPR_MARK0x010000
-A VPR_PREROUTING -m set --match-set wan dst -c 0 0 -g VPR_MARK0x010000
-A VPR_PREROUTING -d 148.66.233.128/32 -m comment --comment iDriveFW -c 0 0 -g VPR_MARK0x020000
-A VPR_PREROUTING -d 148.66.233.129/32 -m comment --comment iDriveFW -c 0 0 -g VPR_MARK0x020000
-A VPR_PREROUTING -d 148.66.234.47/32 -m comment --comment iDriveFW -c 0 0 -g VPR_MARK0x020000
-A VPR_PREROUTING -d 148.66.234.51/32 -m comment --comment iDriveFW -c 0 0 -g VPR_MARK0x020000
-A VPR_PREROUTING -d 173.255.13.9/32 -m comment --comment iDriveFW -c 0 0 -g VPR_MARK0x020000
============================================================
Mangle IP Table MARK Chain: VPR_MARK0x010000
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-N VPR_MARK0x010000
-A VPR_MARK0x010000 -c 0 0 -j MARK --set-xmark 0x10000/0xff0000
-A VPR_MARK0x010000 -c 0 0 -j RETURN
============================================================
Mangle IP Table MARK Chain: VPR_MARK0x020000
# Warning: iptables-legacy tables present, use iptables-legacy to see them
-N VPR_MARK0x020000
-A VPR_MARK0x020000 -c 3598 371298 -j MARK --set-xmark 0x20000/0xff0000
-A VPR_MARK0x020000 -c 3598 371298 -j RETURN
============================================================
Current ipsets
create wan hash:net family inet hashsize 1024 maxelem 65536 comment
create wan_ip hash:net family inet hashsize 1024 maxelem 65536 comment
create wan_mac hash:mac hashsize 1024 maxelem 65536 comment
create TorGuard hash:net family inet hashsize 1024 maxelem 65536 comment
create TorGuard_ip hash:net family inet hashsize 1024 maxelem 65536 comment
create TorGuard_mac hash:mac hashsize 1024 maxelem 65536 comment
add TorGuard_mac F0:B3:EC:27:3E:48 comment "AppleTV: F0:B3:EC:27:3E:48"
============================================================
DNSMASQ ipsets
ipset=/idrive.com/TorGuard # iDrive
ipset=/wsn7s.idrive.com/TorGuard # iDrive
============================================================
Your support details have been logged to '/var/vpn-policy-routing-support'. [✓]

RESTART OUTPUT

Creating table 'wan/eth0/88.215.96.129' [✓]
Creating table 'TorGuard/10.13.128.101' [✓]
Routing 'AppleTV' via TorGuard [✓]
Routing 'iDrive' via TorGuard [✓]
Routing 'iDriveFW' via TorGuard [✓]
vpn-policy-routing 0.3.4-8 monitoring interfaces: wan TorGuard [✓]
vpn-policy-routing 0.3.4-8 started with gateways:
wan/eth0/88.215.96.129 [✓]
TorGuard/10.13.128.101

Any thoughts??

At the end I think that I understand what is the problem.
Solution of my issue:
separate the domain name on dnsmasq...

Now

config dnsmasq
	option domainneeded '1'
	option localise_queries '1'
	option rebind_protection '1'
	option rebind_localhost '1'
	option local '/lan/'
	option domain 'lan'
	option expandhosts '1'
	option authoritative '1'
	option readethers '1'
	option leasefile '/tmp/dhcp.leases'
	option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
	option localservice '1'
	option ednspacket_max '1232'
	option confdir '/tmp/dnsmasq.d'
	list interface 'br-lan'
	option cachesize '1000'
	list server '/browserleaks.com/1.1.1.1'
	list server '/browserleaks.org/1.1.1.1'
	list server '/amazonaws.com/1.1.1.1'
	list server '/llnwi.net/1.1.1.1'
	list server '/aiv-cdn.net/1.1.1.1'
	list server '/footprint.net/1.1.1.1'
	list server '/aiv-delivery.net/1.1.1.1'
	list server '/amazonvideo.com/1.1.1.1'
	list server '/amazon.com/1.1.1.1'

Before

list server '/amazonaws.com/llnwi.net/aiv-cdn.net/footprint.net/aiv-delivery.net/amazonvideo.com/amazon.com/cloudfront.net/media-amazon.com/primevideo.com/a2z.com/amazon.fr/amazon.it/paypal.com/1.1.1.1'
	

So, thanks @stangri to focus me list server entries

Ok - so I did some more troubleshooting.

If dest_addr = IP address, it routes properly to the VPN regardless of if I traceroute the IP address or the domain name.

if dest_addr = domain name, it will not route to the VPN if I traceroute the IP address or the domain name.

Your dnsmasq ipsets are properly created with the domain names you wanted (just one entry for idrive.com is enough), but the actual ipset is not being filled with the IP corresponding to the domain name, that means that dnsmasq was never queried for that domain name.

Start using dnsmasq as the resolver so it could fill the ipset and ensure correct routing.

@stangri

In any case my wan connection fail, I use wwan to have internet, so this rule, or other rule that are going trought wan don't work.

config policy
	option interface 'wan'
	option name 'WebByPass_1'
	option dest_addr 'ssl-images-amazon.com amazonaws.com

Is it necessary to duplicate rules also to wwan area or is it possible to add two interfaces?
example:

option interface 'wan wwan'

Thanks!

Hi all.
pbr 0.9.8-8 users on OpenWRT 22.03 nft. Can you confirm Custom User Files pbr.user.netflix and pbr.user.aws work?

I don't use it... So I don't know know

Not only putting two interfaces in an option for a single policy won't work, but creating duplicate rules for the interface won't work either.
Maybe mwan3 offers this functionality or would allow you to target the fallback interface, I don't know.

If you can script the fallback/recovery, maybe you can just run sed on the /etc/config/pbr file to replace the 'wan' entries to 'wwan' and back.

I rewrote those files to work properly with either iptables or nft, but I haven't tested either.

Ok thanks, I think that a script is the best solution!

My task is to route Netflix traffic through the "wg" VPN interface. To do this, I change in pbr.user.netflix TARGET_SET='pbr_wan_4_dst_ip' to TARGET_SET='pbr_wg_4_dst_ip' and TARGET_IPSET='pbr_wan_4_dst_net' to TARGET_IPSET='pbr_wg_4_dst_net'. Save the changes. And include Custom User Includes File in pbr.
After applying the changes, traffic to Netflix goes bypassing the VPN.

root@OpenWrt:~# service pbr status
============================================================
pbr - environment
pbr 0.9.8-8 running on OpenWrt 22.03.0. WAN (IPv4): wwan/wlan0/192.168.43.1.
============================================================
Dnsmasq version 2.86  Copyright (c) 2000-2021 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus UBus no-i18n no-IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth cryptohash DNSSEC no-ID loop-detect inotify dumpfile
============================================================
pbr chains - policies
        chain pbr_forward {
        }
        chain pbr_input {
        }
        chain pbr_output {
        }
        chain pbr_prerouting {
                ip daddr @pbr_wan_4_dst_ip goto pbr_mark_0x010000
                ip saddr @pbr_wan_4_src_ip goto pbr_mark_0x010000
                ether saddr @pbr_wan_4_src_mac goto pbr_mark_0x010000
                ip daddr @pbr_wwan_4_dst_ip goto pbr_mark_0x020000
                ip saddr @pbr_wwan_4_src_ip goto pbr_mark_0x020000
                ether saddr @pbr_wwan_4_src_mac goto pbr_mark_0x020000
                ip daddr @pbr_wg_4_dst_ip goto pbr_mark_0x030000
                ip saddr @pbr_wg_4_src_ip goto pbr_mark_0x030000
                ether saddr @pbr_wg_4_src_mac goto pbr_mark_0x030000
        }
        chain pbr_postrouting {
        }
============================================================
pbr chains - marking
        chain pbr_mark_0x010000 {
                counter packets 0 bytes 0 meta mark set meta mark & 0xff01ffff | 0x00010000
                return
        }
        chain pbr_mark_0x020000 {
                counter packets 0 bytes 0 meta mark set meta mark & 0xff02ffff | 0x00020000
                return
        }
        chain pbr_mark_0x030000 {
                counter packets 0 bytes 0 meta mark set meta mark & 0xff03ffff | 0x00030000
                return
        }
============================================================
pbr nft sets
        set pbr_wan_4_dst_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wan_4_src_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wan_4_src_mac {
                type ether_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wwan_4_dst_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wwan_4_src_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wwan_4_src_mac {
                type ether_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wg_4_dst_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wg_4_src_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wg_4_src_mac {
                type ether_addr
                policy memory
                flags interval
                comment ""
        }

root@OpenWrt:~# traceroute netflix.com
traceroute to netflix.com (3.251.50.149), 30 hops max, 46 byte packets
 1  192.168.43.1 (192.168.43.1)  1.960 ms  2.129 ms  2.263 ms
 2  10.17.135.122 (10.17.135.122)  26.858 ms  29.768 ms  28.299 ms

install pbr 0.9.8-10, edit the TARGET_SET variable again restart the service.

Or, you can just download the fixed scripts from https://github.com/stangri/source.openwrt.melmac.net/tree/master/pbr/files/usr/share/pbr and place them into /usr/share/pbr/ without reinstalling (but with restarting the service).

The service pbr status should show the relevant nft set filled with elements on successful run.

Replaced user scripts. Restarted the service. But it did not help. Everything remained the same.service pbr status

============================================================
pbr - environment
pbr 0.9.8-8 running on OpenWrt 22.03.0. WAN (IPv4): wwan/wlan0/192.168.43.1.
============================================================
Dnsmasq version 2.86  Copyright (c) 2000-2021 Simon Kelley
Compile time options: IPv6 GNU-getopt no-DBus UBus no-i18n no-IDN DHCP DHCPv6 no           -Lua TFTP conntrack ipset auth cryptohash DNSSEC no-ID loop-detect inotify dumpf           ile
============================================================
pbr chains - policies
        chain pbr_forward {
        }
        chain pbr_input {
        }
        chain pbr_output {
        }
        chain pbr_prerouting {
                ip daddr @pbr_wan_4_dst_ip goto pbr_mark_0x010000
                ip saddr @pbr_wan_4_src_ip goto pbr_mark_0x010000
                ether saddr @pbr_wan_4_src_mac goto pbr_mark_0x010000
                ip daddr @pbr_wwan_4_dst_ip goto pbr_mark_0x020000
                ip saddr @pbr_wwan_4_src_ip goto pbr_mark_0x020000
                ether saddr @pbr_wwan_4_src_mac goto pbr_mark_0x020000
                ip daddr @pbr_wg_4_dst_ip goto pbr_mark_0x030000
                ip saddr @pbr_wg_4_src_ip goto pbr_mark_0x030000
                ether saddr @pbr_wg_4_src_mac goto pbr_mark_0x030000
        }
        chain pbr_postrouting {
        }
============================================================
pbr chains - marking
        chain pbr_mark_0x010000 {
                counter packets 0 bytes 0 meta mark set meta mark & 0xff01ffff |            0x00010000
                return
        }
        chain pbr_mark_0x020000 {
                counter packets 0 bytes 0 meta mark set meta mark & 0xff02ffff |            0x00020000
                return
        }
        chain pbr_mark_0x030000 {
                counter packets 0 bytes 0 meta mark set meta mark & 0xff03ffff |            0x00030000
                return
        }
============================================================
pbr nft sets
        set pbr_wan_4_dst_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wan_4_src_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wan_4_src_mac {
                type ether_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wwan_4_dst_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wwan_4_src_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wwan_4_src_mac {
                type ether_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wg_4_dst_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wg_4_src_ip {
                type ipv4_addr
                policy memory
                flags interval
                comment ""
        }
        set pbr_wg_4_src_mac {
                type ether_addr
                policy memory
                flags interval
                comment ""
        }

I've implemented some fixes in pbr 0.9.8-12, however nft is very picky on overlapping nft sets so if you have some domains/other ip addresses in the nft set which will overlap with addresses from the user files it will still fail.

I noticed such a bug. When you enable custom rules in luci , this action is not processed in config.
This is one of the reasons why rules are not created. I included them manually by editing config. I see that the rules have appeared. But the traffic still goes through wan.

Forgot to mention -- as per README, the prerouting chain does not affect the traffic from the router itself.

You ignored my error message when using custom rules. Therefore, I am writing again.
When I enable a custom rule in LUCI it doesn't make a change to etc/config/pbr after applying it.

etc/config/pbr

config pbr 'config'
	option verbosity '2'
	option strict_enforcement '1'
	option resolver_set 'none'
	option ipv6_enabled '0'
	list ignored_interface 'vpnserver'
	list ignored_interface 'wgserver'
	option boot_timeout '30'
	option rule_create_option 'add'
	option procd_reload_delay '1'
	option webui_enable_column '1'
	option webui_protocol_column '1'
	option webui_chain_column '1'
	option webui_show_ignore_target '1'
	option webui_sorting '1'
	list webui_supported_protocol 'tcp'
	list webui_supported_protocol 'udp'
	list webui_supported_protocol 'tcp udp'
	list webui_supported_protocol 'icmp'
	list webui_supported_protocol 'all'
	option enabled '1'

config include
	option path '/usr/share/pbr/pbr.user.rkn'

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

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

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

config policy
	option name 'WireGuard Server'
	option interface 'wan'
	option src_port '51820'
	option chain 'OUTPUT'
	option proto 'udp'
	option enabled '0'

/etc/init.d/pbr reload confirms that the rule is not active

Activating Traffic Killswitch [✓]
Deactivating Traffic Killswitch [✓]
pbr 0.9.8-12 (nft) started with gateways:
wan/0.0.0.0
wwan/wlan0/192.168.43.1 [✓]
wg/172.16.0.2

after editing etc/config/pbr option enabled '1'

config include
	option path '/usr/share/pbr/pbr.user.rkn'
	option enabled '1'

everything is working

root@OpenWrt:~# /etc/init.d/pbr reload
Activating Traffic Killswitch [✓]
Running /usr/share/pbr/pbr.user.rkn [✓]
Deactivating Traffic Killswitch [✓]
pbr 0.9.8-12 (nft) started with gateways:
wan/0.0.0.0
wwan/wlan0/192.168.43.1 [✓]
wg/172.16.0.2

Thanks for providing details this time. It's been fixed in luci app in my repo, I didn't bump the version number, so you could either reinstall luci-app-pbr or fix the lua file on your router: https://github.com/stangri/source.openwrt.melmac.net/commit/39a4e52b7d14262d056f07c5309e5899af6a5133

How did you test? Ideally you should post your user file, the output of service pbr status after it ran and step-by-step on how you're testing and again service pbr status after you tested to see if the counters changed.

Will this limitation ever be fixed?
Your latest fixes are working. Thank you.