Firewall4 and /etc/config/firewall on OpenWrt
From OpenWrt 22.03 onward, firewall4 (fw4) uses nftables as its default backend while retaining the familiar UCI syntax in /etc/config/firewall. UCI covers a reasonable subset of Netfilter; special nftables behavior should use the include mechanisms instead of forcing everything into one config rule.1
Warning: Back up
/etc/config/firewallbefore editing. Double-check the result before reloading; if access is lost, use Failsafe to restore it. Never expose an Internet port just because a rule looks plausible.1
Manage it with LuCI and UCI
In LuCI, open Network → Firewall. LuCI maps closely to the file sections but may remove # comments. From the CLI, uci changes values in /etc/config/firewall; uci commit saves them, but the firewall still needs a reload to generate new tables. The source warns that uci does not understand content inside /etc/firewall.user.1
Create a rule with UCI:
uci add firewall ruleuci set firewall.@rule[-1].name='Reject VPN to LAN traffic'uci set firewall.@rule[-1].src='vpn'uci set firewall.@rule[-1].dest='lan'uci set firewall.@rule[-1].proto='all'uci set firewall.@rule[-1].target='REJECT'uci commit firewallservice firewall restart
Inspect what UCI created:
# uci show firewallfirewall.@rule[^20]=rulefirewall.@rule[^20].name='Reject VPN to LAN traffic'firewall.@rule[^20].src='vpn'firewall.@rule[^20].dest='lan'firewall.@rule[^20].proto='all'firewall.@rule[^20].target='REJECT'...
To see parsing diagnostics while reloading, use /etc/init.d/firewall reload or fw4 reload and read the complete output before closing the SSH session.1
Core configuration sections
defaults
Defaults define the global policy and common protections:
config defaults option input 'ACCEPT' option output 'ACCEPT' option forward 'REJECT' option custom_chains '1' option drop_invalid '1' option synflood_protect '1' option synflood_rate '25/s' option synflood_burst '50' option tcp_ecn '1' option tcp_syncookies '1' option tcp_window_scaling '1'
zone
A zone groups one or more interfaces. A WAN zone commonly enables masquerading and mtu_fix:
config zone option name 'wan' option network 'wan wan6' option input 'REJECT' option output 'ACCEPT' option forward 'REJECT' option masq '1' option mtu_fix '1'
input is traffic reaching the router through the zone, output originates on the router, and forward crosses interfaces. masq applies IPv4 NAT to traffic leaving a zone and is normally used on WAN.1
forwarding
Forwarding is directional; it is not automatically bidirectional:
config forwarding option src 'lan' option dest 'wan'
To allow traffic both ways, create two forwardings with reversed src and dest, and ensure that connection tracking is appropriate on at least one side, normally the zone with masq.1
rule
A rule can match zones, IPs, MAC addresses, ports, protocols, families, and a target:
config rule option name 'Reject LAN to WAN for custom IP' option src 'lan' option src_ip '192.168.1.2' option src_mac '00:11:22:33:44:55' option src_port '80' option dest 'wan' option dest_ip '194.25.2.129' option dest_port '120' option proto 'tcp' option target 'REJECT'
An example that accepts SSH from a specific LAN range to a server:
config rule option name 'forward ssh to server' option family 'ipv4' option src 'lan' option src_ip '192.168.1.0/24' option dest 'lan' option dest_ip '172.30.100.1' option proto 'tcp' option dest_port '22' option target 'ACCEPT'
With only src, a rule matches traffic entering the router; with only dest, traffic leaving it; with both, forwarded traffic. src_ip and dest_ip accept an address or CIDR, port ranges use start-stop, and proto and family must match the actual traffic.1
redirect: DNAT and SNAT
DNAT sends incoming traffic to an internal host:
config redirect option name 'DNAT WAN to LAN for SSH' option src 'wan' option src_dport '19900' option dest 'lan' option dest_ip '192.168.1.1' option dest_port '22' option proto 'tcp' option target 'DNAT'
SNAT changes the source of traffic leaving a zone:
config redirect option name 'SNAT DMZ 192.168.1.250 to WAN 1.2.3.4 for ICMP' option src 'dmz' option src_ip '192.168.1.250' option src_dip '1.2.3.4' option dest 'wan' option proto 'icmp' option target 'SNAT'
For DNAT, specify src_dport when the rule must not expose every port matching the remaining conditions. Test from the Internet and restrict the source whenever possible.1
IP sets
An IP set matches a list of addresses instead of repeating many rules. Distinguish fw3 and fw4 options, the IP-set type, storage/match options, and how a rule or redirect refers to ipset. Do not reference a set that has not been created; when a package creates it automatically, check startup ordering and firewall logs.1
{{< ads >}}
nftables includes on fw4 (22.03+)
UCI firewall does not cover every Netfilter feature. With fw4, either include an nftables snippet at a table/chain position or include a compatible shell script. A chain snippet example:
# /etc/config/firewallconfig include option type 'nftables' option path '/etc/my_custom_firewall_rule.nft' option position 'chain-pre' option chain 'input_wan' # /etc/my_custom_firewall_rule.nfttcp dport 0-1023 log prefix "Inbound WAN connection attempt to low TCP port: "
A table-post include:
config include option type 'nftables' option path '/etc/my_custom_firewall_chain.nft' option position 'table-post'
For /etc/firewall.user, declare a script include and mark it fw4-compatible:
config include option enabled 1 option type 'script' option path '/etc/firewall.user' option fw4_compatible 1
fw4 can also load automatic drop-in includes below /usr/share/nftables.d/ when auto_includes is enabled. Packages may use that hook; do not put arbitrary code there without checking ordering and chain scope.1
fw3 includes and reload procedure
On OpenWrt 21.02 and earlier, type 'script' and /etc/firewall.user are the older fw3 path; do not carry a fw3 example into fw4 without checking nftables syntax. A minimal fw3 include from the source is:
config include option path '/etc/firewall.user'
After each change:
- Inspect the diff of
/etc/config/firewalland every include file. - Run
uci commit firewallafter UCI edits. - Reload and read the diagnostics.
- Test LuCI/SSH, LAN-to-WAN traffic, zone isolation, and published ports.
- If access is lost, enter Failsafe and restore the backup.
A firewall is a contract among zones, forwardings, rules, redirects, and includes. A successful build does not prove that the policy is safe; test each traffic direction in practice.1
Comments & Discussion
Share your thoughts, ask questions and feedback