Bookmark

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/firewall before 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:

1
2
3
4
5
6
7
8
uci add firewall rule
uci 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 firewall
service firewall restart

Inspect what UCI created:

1
2
3
4
5
6
7
8
# uci show firewall
firewall.@rule[^20]=rule
firewall.@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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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:

1
2
3
4
5
6
7
8
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:

1
2
3
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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
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:

1
2
3
4
5
6
7
8
9
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:

1
2
3
4
5
6
7
8
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

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:

1
2
3
4
5
6
7
8
9
# /etc/config/firewall
config 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.nft
tcp dport 0-1023 log prefix "Inbound WAN connection attempt to low TCP port: "

A table-post include:

1
2
3
4
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:

1
2
3
4
5
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:

1
2
config include
	option	path		'/etc/firewall.user'

After each change:

  1. Inspect the diff of /etc/config/firewall and every include file.
  2. Run uci commit firewall after UCI edits.
  3. Reload and read the diagnostics.
  4. Test LuCI/SSH, LAN-to-WAN traffic, zone isolation, and published ports.
  5. 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

Sources


0 Bình luận

Góp Ý / Bình Luận / Đánh giá