Using /etc/nftables.d/10-custom-filter-chains.nft

I upgraded most of my devices to OpenWrt 22.03 today and I'm having issues using the nft-infrastructure.
I have some quite complex firewall configurations, some of them aren't covered by the UI, that's why I configured my rules using /etc/firewall.user until today.
When trying to solve my issues, I even had issues with "simple" rules, and I don't get what I might be doing wrong. For getting closer to understanding the infrastructure, I created a forward rule in the UI, which was working. Using nft list ruleset I found the rule:

chain forward {
    [...]
    iifname "tun0" ip saddr <vpnnet>/<vpnmask> ip daddr <lannet>/<lanmask> counter packets 1 bytes 84 jump accept_to_lan comment "!fw4: Allow-VPN"
    [...]
}

I then disabled this rule and added following to /etc/nftables.d/10-custom-filter-chains.nft:

chain handle_accept {
    ct state new log prefix "handle_accept: "
    accept
}
chain user_pre_forward {
    type filter hook forward priority filter - 1; policy accept;
    iifname "tun0" ip saddr <vpnnet>/<vpnmask> ip daddr <lannet>/<lanmask> counter jump handle_accept comment "!fw4: Allow-VPN"
}

logread shows the rule is hit correctly (there is a line with "handle_accept"), but the packet is still dropped (the forward policy in "General Settings" is used).

What am I missing? Thanks for your help!

It is explained here:

https://wiki.nftables.org/wiki-nftables/index.php/Configuring_chains#Base_chain_priority

1 Like

Thank you for your answer. If I understand this correctly, my rule creates an "accept" in the "user_pre_forward"-chain (priority -1). Since the "forward"-chain has a higher priority (0), it is handled afterwards and the default policy is applied.
Moving this rule to the "user_post_forward"-chain (priority 1) also doesn't work, in this case, I don't see any entry in the log as if the default policy of the "forward"-chain is "final".
How can I solve this? Is there a way to make the accept in the "user_pre_forward"-chain final? Or is there a way to make the rules in the post-chains respected even if the default policy is set to drop/reject?

I think the wiki is clear enough about that.

If the packet is accepted, it will traverse the next chain (if any) bearing the same hook type and with a later priority, but if it is dropped/rejected, no further rules or chains will be evaluated.

This explains why in the first case the packets are rejected by the forward hook chain with (later) priority 0 and in the second case, they never reach the chain with priority 1.

Anyway, I don't understand why you insist on playing with priorities.

Just create a firewall zone named vpn and attach the tun interface to it. Then populate the automatically created forward_vpn chain with your exotic rules using includes.

1 Like

I also thought about creating a firewall zone and assigning the tun-interface but I was unsure whether this would be a persistent solution as the tun-interface will not be existing all the time and especially be absent when the firewall is initialized the first time after a system start.
And I probably also was stuck to this way because that's how I used to configure it until 21.02 and I was biased implementing it as similar as possible.
A little misleading might be the default 10-custom-filter-chains.nft as the user_post_forward is existing in the default configuration and at the same time, the default policy of forwarding is to drop packets - so the chain cannot be reached. Probably a comment in the default config could be an improvement?

That's not a problem.
You can even use wildcards for the interface (device) name.

config zone
        option name 'vpn'
        option input 'ACCEPT' # Change it if the vpn is considered untrusted
        option output 'ACCEPT'
        option forward 'REJECT'
        list device 'tun+'

config rule
        option name 'Allow-vpn-to-lan'
        option src 'vpn'
	    option dest 'lan'
        option src_ip '<vpnnet>/<vpnmask>'
        option dest_ip '<lannet>/<lanmask>'
        option target 'ACCEPT'
        list proto 'all'
1 Like

Just in case someone reads this thread, here are some additional details:

  1. Another rule is needed to forward traffic from lan to vpn
  2. I limited the rules to IPv4 as my VPN does not support IPv6
  3. For forwarding DLNA/UPnP/SSDP-Packets, I created a custom file.

Here is the current status:
/etc/config/firewall:

config zone
	option name 'vpn'
	option input 'ACCEPT'
	option output 'ACCEPT'
	list device 'tun+'
	option forward 'REJECT'

config rule
	option name 'Drop-Lan-IPs-from-VPN'
	option src 'vpn'
	option dest 'lan'
	option target 'DROP'
	option family 'ipv4'
	list proto 'all'
	list src_ip '<lannet>/<lanmask>'

config rule
	option name 'Allow-vpn-to-lan'
	option src 'vpn'
	option dest 'lan'
	option target 'ACCEPT'
	option family 'ipv4'
	list src_ip '<vpnnet>/<vpnmask>'
	list proto 'all'
	list dest_ip '<lannet>/<lanmask>'
	list dest_ip '239.255.255.250'

config rule
	option name 'Allow-lan-to-vpn'
	option src 'lan'
	option dest 'vpn'
	option target 'ACCEPT'
	option family 'ipv4'
	list src_ip '<lannet>/<lanmask>'
	list proto 'all'
	list dest_ip '<vpnnet>/<vpnmask>'
	list dest_ip '239.255.255.250'

/etc/nftables.d/11-ttl-mangle-dlna.nft:

chain mangle_postrouting_dlna_ttl {
	type filter hook postrouting priority mangle; policy accept;
	oifname tun* ip saddr <lannet>/<lanmask> ip daddr 239.255.255.250 counter ip ttl set 3
}

1 Like