Policy-Based-Routing (pbr) package discussion

Thank you! Seems like all errors are gone now after the update.

1 Like

If i set a domain to be routed thru wireguard iface, why tracerouting on the router still routed thru WAN and not WG iface ?

If you set it on the default chain (prerouting) that works for forwarded traffic so for your LAN clients.

For the router itself you use the output chain.

Should be in the PBR read.me I think

1 Like

Hi, I tried the r30 version.

Added the config you mentioned:

config pbr 'config'
        option enabled '1'
        option verbosity '2'
        option strict_enforcement '1'
        option resolver_set 'dnsmasq.nftset'
        option ipv6_enabled '1'
        option boot_timeout '30'
        option procd_boot_trigger_delay '9000'
...

Still the same, just a lot of "service is stopped", and pbr does not run after reboot.

If you add the following to system >startup > local startup (/etc/rc.local):

sleep 30 && service pbr restart

Does it start then?

Note you might need more or less than 30 depending on the services you have running

I didn't use rc.local, I just waited some time and manually restarted pbr and it did work.

But obviously not ideal, even with a rc.local automation.

I think I will just stick with r6 for now.

Sure you can do that but chances are we will not get to the root cause.

But if you can spare some time stay on r30 and send the following information about 6 minutes after a reboot
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 -6 route show
cat /etc/config/pbr
service pbr status
nft list ruleset

Then show the output of the following:

service pbr restart
service pbr status
nft list ruleset

But I can understand if you want to stay at r6

Don't get me wrong, I am happy to help you guys debug.

I am running it as a VM in PVE, so I can update to r30 and revert back to r6 without too much trouble. I will make some time later today and get back to you with the information you need.

r29 and r30 in my case works ok. Thanks

1 Like

Hey look can I send it via email?

Also I spent 40 minute redacting the information, and I have only finished everything except nft ruleset, the 2 nft rule sets are about 80k lines each so I really don't want to do them.

Please first check the other files first and if it is really necessary to provide nft ruleset, I will spend some more time on this.

Sure you can send me a personal message

PM sent.

I don't think 80k lines of nft ruleset in and of itself is a problem. I have assigned 4 cores of 12th gen intel i3 and 1GB RAM to openwrt, and in general it runs fairly stably. In fact, it was running flawlessly with pbr 1.18 r6. I wouldn't say I am an expert, but I do try to use best practice when I can, it is just I do have the need for a complex topology and security measures.

1 Like

Thanks for @egc for helping with debug. However it didn't work out.

Tried option procd_boot_trigger_delay '90000', and waited about 15 minutes, pbr is still not started.

The log has 1 line of this

OpenWrt pbr [3913]: Setting trigger (on_boot) [โœ“]

And a dozen of these:

OpenWrt pbr: Sending reload signal to pbr due to firewall action: includes
OpenWrt pbr: Reload on firewall action aborted: service is stopped.

Of course, using rc.local to restart pbr service after some time works. But it feels like a hack.

Did a bit more testing, now I have essentially emptied my pbr config, removed all supported interface, removed all user script, disabled IPv6 support and nft set support:

config pbr 'config'
	option enabled '1'
	option verbosity '2'
	option strict_enforcement '0'
	option resolver_set 'none'
	option ipv6_enabled '0'
	option boot_timeout '30'
	option rule_create_option 'add'
	option procd_reload_delay '1'
	option webui_show_ignore_target '1'
	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'
	option wireguard_dscp '4'

pbr is still not starting on boot.

Is there some kind of check pbr does before booting? I'm utterly confused.

I've been running r31 for the past four days...It's solved the non-starting issue I had with r16 on my Flint 2 router. (The non-starting issue with r16 did not happen at first but after several upgrades of the Kernel as well as other things it began to happen. But the r31 version resolved it with the lastest snapshot builds. Just feedback for egc.

1 Like

Hi, do I need to upgrade to 24.10.2 to install the latest version of PBR?

Although it might be a good idea to upgrade to 24.10.2 anyway, it is not necessary for PBR.
You can upgrade PBR separately.

Instructions are in the PBR guide, see: https://docs.openwrt.melmac.net/#Howtouse

1 Like

Hi! Could you please add option to keep nft sets with already resolved domains' ips between PBR restarts?

I understand that saving them theoretically can lead to issues on long distance, when ip in the set is no longer owned by the domain it was resolved from originally. But right now I have more actual issue - when I'm adding new domains to pass them to vpn, PBR restarts, nft becomes empty and for the next 30-60 minutes I have LOTS of lags while accessing PBR domains while it resolves domains from scratch and populates nft set.

So I think an option to choose to keep nft sets between restarts could be very useful!

(I've tried to inject nft sets list > backup && nft -f backup into the init-script but on 2400 loc my bash-fu failed completely))

Hi, I have a PBR + AirVPN Wireguard setup that seems to work, but all my requests to the PBR domains timed out.
Not sure what went wrong because I have another site that has almost identical configuration and the issue doesn't happen there.

It could be a Wireguard setup issue, but I tried the Wireguard config on a Fedora machine and it works. I can DM you the Wireguard config if needed.

Not sure if this is relevant, but I also use http-dns-proxy and adblock-fast.

ubus call system board
{
	"kernel": "6.6.93",
	"hostname": "OpenWrt-2406",
	"system": "Intel(R) N100",
	"model": "Default string Default string",
	"board_name": "default-string-default-string",
	"rootfs_type": "squashfs",
	"release": {
		"distribution": "OpenWrt",
		"version": "24.10.2",
		"revision": "r28739-d9340319c6",
		"target": "x86/64",
		"description": "OpenWrt 24.10.2 r28739-d9340319c6",
		"builddate": "1750711236"
	}
}
uci export dhcp
package dhcp

config dnsmasq
	option domainneeded '1'
	option localise_queries '1'
	option rebind_protection '1'
	option rebind_localhost '1'
	option local '/internal/'
	option domain 'internal'
	option expandhosts '1'
	option cachesize '1000'
	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'
	list rebind_domain 'eleung.me'
	list interface 'guest'
	list interface 'iot'
	list interface 'lan'
	list interface 'pikvm'
	list server '/mask.icloud.com/'
	list server '/mask-h2.icloud.com/'
	list server '/use-application-dns.net/'
	list server '127.0.0.1#5053'
	list server '127.0.0.1#5054'
	list server '127.0.0.1#5055'
	list server '127.0.0.1#5056'
	option serversfile '/var/run/adblock-fast/dnsmasq.servers'
	option doh_backup_noresolv '-1'
	option noresolv '1'
	list doh_backup_server '/mask.icloud.com/'
	list doh_backup_server '/mask-h2.icloud.com/'
	list doh_backup_server '/use-application-dns.net/'
	list doh_backup_server '127.0.0.1#5053'
	list doh_backup_server '127.0.0.1#5054'
	list doh_server '127.0.0.1#5053'
	list doh_server '127.0.0.1#5054'
	list doh_server '127.0.0.1#5055'
	list doh_server '127.0.0.1#5056'

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 dhcp 'lan'
	option interface 'lan'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option force '1'

config dhcp 'iot'
	option interface 'iot'
	option start '100'
	option limit '150'
	option leasetime '12h'

config dhcp 'guest'
	option interface 'guest'
	option start '100'
	option limit '150'
	option leasetime '12h'
	option force '1'

config dhcp 'pikvm'
	option interface 'pikvm'
	option start '100'
	option limit '150'
	option leasetime '12h'

config domain
	option name '1605.eleung.me'
	option ip '192.168.0.1'

config domain
	option name '2406.eleung.me'
	option ip '192.168.1.1'

config domain
	option name 'regunakyle.synology.me'
	option ip '192.168.0.20'
uci export firewall
package firewall

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

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

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

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 'iot'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	list network 'iot'

config forwarding
	option src 'lan'
	option dest 'iot'

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

config zone
	option name 'guest'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	list network 'guest'

config forwarding
	option src 'guest'
	option dest 'wan'

config forwarding
	option src 'lan'
	option dest 'guest'

config rule
	option src 'guest'
	option name 'Allow-Guest-DHCP-DNS'
	option dest_port '53 67 68'
	option target 'ACCEPT'

config rule
	option src 'iot'
	option name 'Allow-IoT-DHCP-DNS-NTP'
	option dest_port '53 67 68 123'
	option target 'ACCEPT'
	list proto 'tcp'
	list proto 'udp'

config zone
	option name 'wg_s2s'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'REJECT'
	list network 'wg_s2s_2406'

config forwarding
	option src 'wg_s2s'
	option dest 'lan'

config forwarding
	option src 'lan'
	option dest 'wg_s2s'

config rule 'wg_s2s_51820'
	option name 'Allow-WireGuard-51820'
	option src 'wan'
	option dest_port '51820'
	option proto 'udp'
	option target 'ACCEPT'

config redirect
	option dest 'lan'
	option target 'DNAT'
	option name 'Tailscale-Direct-Connection'
	option family 'ipv4'
	list proto 'udp'
	option src 'wan'
	option src_dport '41641'
	option dest_ip '192.168.100.10'
	option dest_port '41641'

config forwarding
	option src 'wg_s2s'
	option dest 'guest'

config forwarding
	option src 'wg_s2s'
	option dest 'iot'

config redirect
	option dest 'lan'
	option target 'DNAT'
	option name 'Intercept-NTP-LAN'
	option family 'ipv4'
	list proto 'udp'
	option src 'lan'
	option src_dport '123'
	option dest_ip '192.168.1.1'
	option dest_port '123'

config redirect
	option dest 'iot'
	option target 'DNAT'
	option name 'Intercept-NTP-IoT'
	option family 'ipv4'
	list proto 'udp'
	option src 'iot'
	option src_dport '123'
	option dest_ip '192.168.2.1'
	option dest_port '123'

config zone
	option name 'wg_airvpn'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	list network 'wg_airvpn'
	list network 'test'

config forwarding
	option src 'lan'
	option dest 'wg_airvpn'

config zone
	option name 'dmz'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	list network 'dmz'

config forwarding
	option src 'dmz'
	option dest 'wan'

config forwarding
	option src 'lan'
	option dest 'dmz'

config forwarding
	option src 'wg_s2s'
	option dest 'dmz'

config redirect
	option dest 'dmz'
	option target 'DNAT'
	option name '80-to-DMZ'
	option src 'wan'
	option src_dport '80'
	option dest_ip '172.16.1.50'
	option dest_port '80'
	list proto 'tcp'

config redirect
	option dest 'dmz'
	option target 'DNAT'
	option name '443-to-DMZ'
	list proto 'tcp'
	option src 'wan'
	option src_dport '443'
	option dest_ip '172.16.1.50'
	option dest_port '443'

config redirect
	option dest 'lan'
	option target 'DNAT'
	option name 'DMZ-to-SMB'
	list proto 'tcp'
	option src 'dmz'
	option src_dport '445'
	option dest_ip '192.168.1.20'
	option dest_port '445'
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 'fd2d:6345:17f2::/48'
        option packet_steering '1'

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

config device
        option type 'bonding'
        option name 'bond0'
        list ports 'eth2'
        list ports 'eth3'
        option policy '802.3ad'
        option failover_mac 'none'
        option xmit_hash_policy 'layer2+3'
        option lacp_rate 'slow'
        option ad_select 'stable'

config device
        option type 'bridge'
        option name 'br0'
        option bridge_empty '1'
        list ports 'bond0'

config bridge-vlan
        option device 'br0'
        option vlan '10'
        list ports 'bond0:t'

config bridge-vlan
        option device 'br0'
        option vlan '20'
        list ports 'bond0:t'

config interface 'lan'
        option proto 'static'
        option device 'br0.10'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'

config interface 'iot'
        option proto 'static'
        option device 'br0.20'
        option ipaddr '192.168.2.1'
        option netmask '255.255.255.0'

config bridge-vlan
        option device 'br0'
        option vlan '30'
        list ports 'bond0:t'

config interface 'guest'
        option proto 'static'
        option device 'br0.30'
        option ipaddr '192.168.3.1'
        option netmask '255.255.255.0'

config interface 'wg_s2s_2406'
        option proto 'wireguard'
        option private_key '<redacted>'
        option listen_port '51820'
        list addresses '10.0.0.2/32'

config wireguard_wg_s2s_2406 's2s_vpn_1605'
        option public_key 'tDlSHxFYSqN1lhxgD3nUkIKuHP6Ri1yLmLNT6v5dX0c='
        option preshared_key '<redacted>'
        option description '1605.ddns.eleung.me'
        option route_allowed_ips '1'
        option endpoint_host '1605.ddns.eleung.me'
        option endpoint_port '51820'
        list allowed_ips '192.168.0.0/24'
        list allowed_ips 'fd3a:7c8c:cec1::/48'
        list allowed_ips '10.0.0.1/32'
        list allowed_ips '192.168.20.0/24'
        list allowed_ips '172.16.0.0/24'
        list allowed_ips '192.168.30.0/24'

config interface 'wg_airvpn'
        option proto 'wireguard'
        option private_key '<redacted>'
        list addresses '10.128.9.110/32'
        list addresses 'fd7d:76ee:e68f:a993:eec:8e8a:8dcb:c8bc/128'
        list dns '10.128.0.1'
        list dns 'fd7d:76ee:e68f:a993::1'
        option mtu '1320'

config wireguard_wg_airvpn
        option description 'Imported peer configuration'
        option public_key 'PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk='
        option preshared_key '<redacted>'
        list allowed_ips '0.0.0.0/0'
        list allowed_ips '::/0'
        option persistent_keepalive '15'
        option endpoint_host 'jp3.vpn.airdns.org'
        option endpoint_port '1637'

config interface 'dmz'
        option proto 'static'
        option device 'br0.100'
        option ipaddr '172.16.1.1'
        option netmask '255.255.255.0'

config interface 'pikvm'
        option proto 'static'
        option device 'eth0'
        option ipaddr '192.168.100.1'
        option netmask '255.255.255.0'

config bridge-vlan
        option device 'br0'
        option vlan '100'
        list ports 'bond0:t'

config interface 'test'
        option proto 'wireguard'
        option private_key '<redacted>'
        list addresses '10.133.19.5/32'
        list addresses 'fd7d:76ee:e68f:a993:9be8:2411:53ce:2f3b/128'
        list dns '10.128.0.1'
        list dns 'fd7d:76ee:e68f:a993::1'
        option mtu '1320'

config wireguard_test
        option description 'Imported peer configuration'
        option public_key 'PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk='
        option preshared_key '<redacted>'
        list allowed_ips '0.0.0.0/0'
        list allowed_ips '::/0'
        option persistent_keepalive '15'
        option endpoint_host 'sg3.vpn.airdns.org'
        option endpoint_port '1637'
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'
	option boot_timeout '30'
	option rule_create_option 'add'
	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'
	list procd_lan_device 'br0.10'
	list procd_lan_device 'br0.30'

config policy
	option name 'openai'
	option dest_addr 'chatgpt.com chat.com oaistatic.com oaiusercontent.com openai.com sora.com openai.com.cdn.cloudflare.net openaiapi-site.azureedge.net openaicom-api-bdcpf8c6d2e9atf6.z01.azurefd.net openaicomproductionae4b.blob.core.windows.net production-openaicom-storage.azureedge.net o33249.ingest.sentry.io openaicom.imgix.net browser-intake-datadoghq.com chatgpt.livekit.cloud host.livekit.cloud turn.livekit.cloud'
	option interface 'wg_airvpn'
	option enabled '0'

config policy
	option name 'anthropic'
	option dest_addr 'anthropic.com claude.ai claudeusercontent.com servd-anthropic-website.b-cdn.net'
	option interface 'wg_airvpn'
	option enabled '0'

config policy
	option name 'niconico'
	option dest_addr 'nico nicodic.jp nicomanga.jp niconico.com nicoseiga.jp nicovideo.jp nimg.jp simg.jp'
	option interface 'wg_airvpn'
	option enabled '0'

config policy
	option name 'dlsite'
	option dest_addr 'chobit.cc ci-en.jp ci-en.net dlsite.com dlsite.com.tw dlsite.jp dlsitestudio.com nijiyome.jp triokini.com'
	option interface 'wg_airvpn'
	option enabled '0'

config policy
	option name 'google deepmind'
	option dest_addr 'deepmind.com deepmind.google geller-pa.googleapis.com generativelanguage.googleapis.com proactivebackend-pa.googleapis.com ai.google.dev alkalicore-pa.clients6.google.com alkalimakersuite-pa.clients6.google.com webchannel-alkalimakersuite-pa.clients6.google.com generativeai.google makersuite.google.com aistudio.google.com bard.google.com gemini.google gemini.google.com'
	option interface 'wg_airvpn'
	option enabled '0'

config policy
	option name 'googleapis'
	option dest_addr 'googleapis.com'
	option interface 'wg_airvpn'
	option enabled '0'

config policy
	option name 'airvpn'
	option dest_addr 'airvpn.org'
	option interface 'test'
	option enabled '0'

config policy
	option name 'icanhazip'
	option dest_addr 'icanhazip.com'
	option interface 'test'
/etc/init.d/pbr status

pbr - environment
pbr 1.1.8-r31 running on OpenWrt 24.10.2.

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_test_4_dst_ip_cfg096ff5 { type ipv4_addr;  		 auto-merge; 		 counter; 		 flags interval; 		 		 policy performance; 		 		 comment "icanhazip";}
add rule inet fw4 pbr_prerouting ip daddr @pbr_test_4_dst_ip_cfg096ff5 counter goto pbr_mark_0x030000 comment "icanhazip"

pbr chains - policies
	chain pbr_forward { # handle 71
	}
	chain pbr_input { # handle 72
	}
	chain pbr_output { # handle 73
	}
	chain pbr_postrouting { # handle 75
	}
	chain pbr_prerouting { # handle 74
		ip daddr @pbr_test_4_dst_ip_cfg096ff5 counter packets 43 bytes 2580 goto pbr_mark_0x030000 comment "icanhazip" # handle 1825
	}
	chain pbr_dstnat { # handle 70
	}

pbr chains - marking
	chain pbr_mark_0x010000 { # handle 1815
		counter packets 0 bytes 0 meta mark set meta mark & 0xff01ffff | 0x00010000 # handle 1816
		return # handle 1817
	}
	chain pbr_mark_0x020000 { # handle 1818
		counter packets 0 bytes 0 meta mark set meta mark & 0xff02ffff | 0x00020000 # handle 1819
		return # handle 1820
	}
	chain pbr_mark_0x030000 { # handle 1821
		counter packets 43 bytes 2580 meta mark set meta mark & 0xff03ffff | 0x00030000 # handle 1822
		return # handle 1823
	}

pbr nft sets
	set pbr_test_4_dst_ip_cfg096ff5 { # handle 1824
		type ipv4_addr
		flags interval
		counter
		auto-merge
		comment "icanhazip"
		elements = { 104.16.184.241 counter packets 27 bytes 1620, 104.16.185.241 counter packets 16 bytes 960 }
	}

dnsmasq sets
nftset=/icanhazip.com/4#inet#fw4#pbr_test_4_dst_ip_cfg096ff5 # icanhazip

pbr tables & routing
IPv4 table 256 pbr_wan route:
default via 223.122.96.1 dev eth1 
IPv4 table 256 pbr_wan rule(s):
29999:	from all sport 51820 lookup pbr_wan
30000:	from all fwmark 0x10000/0xff0000 lookup pbr_wan

IPv4 table 257 pbr_wg_airvpn route:
default via 10.128.9.110 dev wg_airvpn 
IPv4 table 257 pbr_wg_airvpn rule(s):
29998:	from all fwmark 0x20000/0xff0000 lookup pbr_wg_airvpn

IPv4 table 258 pbr_test route:
default via 10.133.19.5 dev test 
IPv4 table 258 pbr_test rule(s):
29996:	from all fwmark 0x30000/0xff0000 lookup pbr_test
/etc/init.d/pbr reload
Using uplink interface (on_start): wan [โœ“]
Found uplink gateway (on_start): 223.122.96.1 [โœ“]
Setting up routing for 'wan/eth1/223.122.96.1' [โœ“]
Setting up routing for 'wg_airvpn/10.128.9.110' [โœ“]
Setting up routing for 'test/10.133.19.5' [โœ“]
Routing 'icanhazip' via test [โœ“]
Installing fw4 nft file [โœ“]
Setting interface trigger for wan [โœ“]
Setting interface trigger for wg_airvpn [โœ“]
Setting interface trigger for test [โœ“]

pbr 1.1.8-r31 monitoring interfaces: wan wg_airvpn test
pbr 1.1.8-r31 (fw4 nft file mode) started with gateways:
wan/eth1/223.122.96.1 [โœ“]
wg_airvpn/10.128.9.110
test/10.133.19.5
/etc/init.d/pbr status

pbr - environment
pbr 1.1.8-r31 running on OpenWrt 24.10.2.

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_test_4_dst_ip_cfg096ff5 { type ipv4_addr;  		 auto-merge; 		 counter; 		 flags interval; 		 		 policy performance; 		 		 comment "icanhazip";}
add rule inet fw4 pbr_prerouting ip daddr @pbr_test_4_dst_ip_cfg096ff5 counter goto pbr_mark_0x030000 comment "icanhazip"

pbr chains - policies
	chain pbr_forward { # handle 71
	}
	chain pbr_input { # handle 72
	}
	chain pbr_output { # handle 73
	}
	chain pbr_postrouting { # handle 75
	}
	chain pbr_prerouting { # handle 74
		ip daddr @pbr_test_4_dst_ip_cfg096ff5 counter packets 0 bytes 0 goto pbr_mark_0x030000 comment "icanhazip" # handle 2021
	}
	chain pbr_dstnat { # handle 70
	}

pbr chains - marking
	chain pbr_mark_0x010000 { # handle 2011
		counter packets 0 bytes 0 meta mark set meta mark & 0xff01ffff | 0x00010000 # handle 2012
		return # handle 2013
	}
	chain pbr_mark_0x020000 { # handle 2014
		counter packets 0 bytes 0 meta mark set meta mark & 0xff02ffff | 0x00020000 # handle 2015
		return # handle 2016
	}
	chain pbr_mark_0x030000 { # handle 2017
		counter packets 0 bytes 0 meta mark set meta mark & 0xff03ffff | 0x00030000 # handle 2018
		return # handle 2019
	}

pbr nft sets
	set pbr_test_4_dst_ip_cfg096ff5 { # handle 2020
		type ipv4_addr
		flags interval
		counter
		auto-merge
		comment "icanhazip"
	}

dnsmasq sets
nftset=/icanhazip.com/4#inet#fw4#pbr_test_4_dst_ip_cfg096ff5 # icanhazip

pbr tables & routing
IPv4 table 256 pbr_wan route:
default via 223.122.96.1 dev eth1 
IPv4 table 256 pbr_wan rule(s):
29995:	from all sport 51820 lookup pbr_wan
30000:	from all fwmark 0x10000/0xff0000 lookup pbr_wan

IPv4 table 257 pbr_wg_airvpn route:
default via 10.128.9.110 dev wg_airvpn 
IPv4 table 257 pbr_wg_airvpn rule(s):
29998:	from all fwmark 0x20000/0xff0000 lookup pbr_wg_airvpn

IPv4 table 258 pbr_test route:
default via 10.133.19.5 dev test 
IPv4 table 258 pbr_test rule(s):
29996:	from all fwmark 0x30000/0xff0000 lookup pbr_test

I did not looked at everything, I stopped at the first possible culprit :slight_smile:

For the record, how I setup WireGuard see my notes:

For some pointers about DNS and domain based routing see:

But the possible problem I spotted is the lack of Masquerading (and MTU fix)

For a typical client to a commercial provider it should look like

config zone
	option name 'wg_airvpn'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option masq '1'                 <<<<<< ADD
	option mtu_fix '1'              <<<<<<ADD
	list network 'wg_airvpn'
	list network 'test'

Hope this helps :slight_smile:

3 Likes