Releases: sol1/shorewall-nft
Release list
v0.3.0
shorewall-nft 0.3.0 adds the configuration-file man pages, bundles the sample configurations, ships a skeleton /etc/shorewall on a fresh install, and adds a remote deploy and check path for Shorewall Lite. It also proves the ipsec zone match against a live SA.
Man pages and samples
The shorewall-*(5) manual pages are here. shorewall-rules, shorewall-zones and the rest are generated from Shorewall's own DocBook, so they read like upstream, with shorewall-nft notes added where a setting maps to a specific nftables construct. Annotating every construct is still in progress; a page without a note is still an accurate reference for the file format, because shorewall-nft reads the identical files. The command reference, man shorewall, documents the verbs that are ours: init, load and reload to a lite target, monitor, automate, savesets, and the provider verbs. The Shorewall sample topologies are bundled under /usr/share/shorewall-nft/samples.
A configuration on a fresh install
A fresh install now has a skeleton /etc/shorewall and /etc/shorewall6: an empty zones, interfaces, policy and rules, and a shorewall.conf with safe defaults, so shorewall check and the other commands have something to read. The package does not own /etc/shorewall. It seeds the skeleton from the deb postinst and the rpm %post one file at a time, only where a file is absent, so an install over an existing configuration, including the Shorewall it replaces, never touches it. A box with no configuration at all reports a located error instead of a traceback.
Remote deploy and check
shorewall load --capture runs shorecap on the target over ssh and compiles against the target's own kernel, so the ruleset matches without a separate capture step. shorewall check -r validates a configuration against a remote Shorewall Lite target's kernel: it compiles here, copies the firewall to the target, and runs its check there, loading nothing. After a successful load the redundant check suggestion is gone (#25, #26, #27).
IPSEC zone
The ipsec zone match is proven end to end against a live xfrm SA in the test harness. The tunnels file opens IKE and ESP to the peer, so the arriving ESP is accepted and the kernel decrypts it, and the decrypted traffic then matches the zone by reqid. Without the tunnels entry the firewall would drop the ESP before it could be decrypted, which is why an ipsec zone needs it.
v0.2.10
shorewall-nft 0.2.10 makes INCLUDE resolve files through CONFIG_PATH, and points the systemd units at the binary's real install path. Both came from users checking the compiler and the packages against real setups.
CONFIG_PATH
An INCLUDE or ?INCLUDE directive now resolves a bare file name through the directories in CONFIG_PATH, matching upstream. A rules file can say ?INCLUDE DMZ.rules and have it found in a rules.d directory listed in CONFIG_PATH, the way it worked under Shorewall on iptables. The file is still looked for next to the including file first, so every relative include keeps working. Only a name that is not found there, and that has no directory part, falls back to the CONFIG_PATH search. A name with a slash in it is taken as written. CONFIG_PATH was ignored before, so an include written this way failed to resolve.
systemd units on a unified /usr
The systemd units call the firewall binary at the path it installs to, taken from SBINDIR, instead of hardcoding /usr/sbin. On Debian that is still /usr/sbin, so the units do not change. On Fedora 42 and later, where /usr/sbin is a symlink into /usr/bin and the binary installs to /usr/bin, the units now name /usr/bin/shorewall and keep working if the /usr/sbin compatibility symlink is ever removed. The rpm build checks that the binary named by ExecStart exists.
v0.2.9
shorewall-nft 0.2.9 is mostly configuration-compatibility fixes found while a user checked existing iptables configs against it, plus the AutoBL auto-blacklist action.
Configuration compatibility
- A per-interface sysctl for a VLAN interface (
enp2s0.10) is written with/separators, sosysctldoes not split the dotted name into a.../conf/enp2s0/10/...path (#17). REDIRECTaccepts a service name in the DEST port, likeREDIRECT net ssh tcp 28534; nft resolves it against /etc/services (#18).- A mangle rule with the firewall zone as its source goes in the output chain, matching upstream, instead of being rejected as an address (#19).
- A snat DEST written
interface::address(a double colon, upstream's way to give a destination address with no interface alias) parses cleanly instead of emitting a stray colon (#20). - The blrules SOURCE and DEST columns accept a comma-separated zone list, the same as the rules file, including a trailing
zone:addresslist (#22).
Conntrack helper on a rule
A per-rule {HELPER=name} option assigns a conntrack helper, for example ACCEPT vm $FW udp 69,4011 {HELPER=tftp} so TFTP's data channel is tracked. It was silently dropped before, so the helper never applied (#23).
AutoBL
The AutoBL action auto-blacklists a source that opens more than a configured number of connections in an interval. Upstream builds it from the recent module and connection events; nft does it directly with a dynamic timed set and a rate meter, so it is native. AutoBL(SSH,60,5,2,300,DROP,warn) wifi $FW tcp 22 accepts normal SSH and, when a source exceeds 5 connections in 60 seconds, adds it to a blacklist set and drops it for 300 seconds. It is refused with a located error on an nft too old for the meter and dynamic-set support (0.9.0).
v0.2.8
shorewall-nft 0.2.8 fixes a boot-ordering regression, adds more native standard actions, and closes three configuration-compatibility gaps a user hit checking iptables configs.
The boot fix (#16)
The firewall now starts after the network is online, matching upstream shorewall. It ordered before the network before, so a configuration with provider routing or a routes file failed at boot: those routes reference nexthops on interfaces that were not up yet, and the kernel rejected them with "Device for nexthop is not up". The systemd units and the OpenRC init order after network-online now.
Standard actions
More of actions.std is native nftables.
- The TCP-flag actions
TCPFlags,RST,FIN,NotSyn,dropNotSynandrejNotSynmatch tcp flags, andA_REJECTaudits then rejects. DropSmurfsdrops a broadcast or multicast source,DropDNSrepdrops late DNS replies, andGlusterFSopens the GlusterFS ports.LimitandBLACKLIST, which need features not built yet, now fail with a located error naming the action instead of the generic one. Limit points at the RATE LIMIT column, which upstream recommends over it.
Configuration compatibility
?INCLUDEis accepted as the directive spelling ofINCLUDE.- A params file that uses old-style backtick command substitution is sourced through the shell, as one using
$(...)already was. - A maclist entry with no MAC address (a
-in the MAC column) verifies by IP alone, the way upstream allows.
v0.2.7
shorewall-nft 0.2.7 brings IPSEC zones, more upstream-compatible policy and zone columns, native standard actions, a connection lister, and three fixes for configs a user hit on a live shorewall6 box.
IPSEC zones
The ipsec, ipsec4 and ipsec6 zone types now compile. A zone is scoped to its security association, so cleartext on the tunnel interface is not in the zone. A site-to-site tunnel keys on reqid or spi, tunnel mode matches the outer addresses, and a reqid-less zone matches any SA inbound. When a cleartext zone shares the interface, decrypted traffic is excluded from it, so per-host encryption is correct. On an nft too old for the ipsec match (0.9.0) the zone is refused with a located error rather than a rule that will not load.
Upstream compatibility
The policy RATE LIMIT and CONNLIMIT columns are honoured. The zones file OPTIONS, IN OPTIONS and OUT OPTIONS columns are accepted.
Standard actions
Standard Shorewall actions are now native nftables rather than the upstream action files, which carry embedded Perl and inline iptables and cannot be expanded as-is.
AllowICMPsaccepts the ICMP types a network needs: the RFC 4890 set on IPv6, destination-unreachable and time-exceeded on IPv4 (#14).- The conntrack-state actions
New,Established,Related,InvalidandUntracked, and theallowInvalidanddropInvalidwrappers, matchct state. BroadcastandMulticastand theirallowBcast,dropBcast,allowMcastanddropMcastwrappers match the destination address type.
Monitoring
shorewall show connections lists the tracked connections. It uses the conntrack command when present and /proc/net/nf_conntrack otherwise, so there is no hard dependency on conntrack-tools.
Fixes
- A bracketed IPv6 SNAT target,
SNAT([2001:db8::1]), compiles again. It had been rejected as an invalid target since the 0.1 series. - A firewall with only a policy and no rules file compiles, matching upstream, instead of failing on the missing file.
- An excluded interface primary address,
!&interface, in a REDIRECT or DNAT original-destination now resolves to the interface's address set instead of a literal nft rejects (#15).
v0.2.6
shorewall-nft 0.2.6
This release brings back shorewall monitor, teaches the compiler the documented upstream address-column forms, and folds in two rounds of feedback from the shorewall-users list.
shorewall monitor
shorewall monitor is back. The classic view is a refreshing text screen equivalent to upstream's, built on the standard library so it is always available. shorewall monitor fancy is a new interactive TUI (optional, needs textual): it draws a zone-flow diagram, the firewall as a hub with one weighted spoke per zone, with a live zone selector you open with o, plus a per-interface throughput and denied-chain strip below it. It reads the nftables counters (set COUNTERS=Yes) and /proc/net/dev, never a packet capture. monitor fancy --once prints a static snapshot and needs only rich.
Upstream address-column compatibility
Five documented SOURCE/DEST forms from shorewall-rules(5) now compile and match upstream behaviour, each locked against the upstream compiler by a differential corpus case: zone:[!]interface, zone:interface:address, the included!excluded exclusion, the zone:(...) grouping, and &interface (the interface's primary address, resolved at load the way upstream resolves $SW_<IF>_ADDRESS).
Fixes from the list
A DNAT whose source-zone list names an empty zone is now skipped with a warning rather than rejecting the whole configuration, matching upstream. The RATE LIMIT column now applies to DNAT and REDIRECT, so rate limiting an incoming connection works; it was silently dropped before. &interface now resolves in the DNAT and NAT address columns too, not only in a rule SOURCE or DEST, so it is no longer emitted as a literal that nft treats as a hostname. A params file that uses shell logic, a loop, an include glob or a bash builtin, is sourced through bash the way upstream sources it, so bash-form params and their .inc includes work; permissions are checked first, so REQUIRE_SECURE_CONFIG=Yes refuses a writable params before it is sourced. shorewall6 configuration paths infer the IPv6 family, and address-column errors report the offending file and line. The state directory /var/lib/shorewall-nft is now 0750, like shorewall's.
Full Changelog: v0.2.5...v0.2.6
v0.2.5
shorewall-nft 0.2.5
Support for older nftables, so a mixed Debian and Ubuntu fleet moves to shorewall-nft with one package and one configuration.
Debian 10, Debian 11 and Ubuntu 20.04 ship nftables between 0.9.0 and 0.9.8, below the 1.0.2 baseline. shorewall-nft now probes the local nft and kernel and emits the ruleset form they can load, chosen per box. A modern release keeps today's output unchanged; an older one gets an equivalent ruleset.
What the compiler adapts on an older nft:
- Numeric chain priorities in place of the names nft 0.9.0 lacks.
- Bitwise tcp flags (
tcp flags & (syn|rst) == syn) in place of the mask shorthand nft 0.9.x cannot parse. - Plain
dnat towithout theip/ip6qualifier, which nft 0.9.0 rejects. - A de-concatenated zone dispatch (one rule per interface pair) where the kernel has no set concatenation, as on Debian 10's stock 4.19 kernel.
Two features need a newer nftables than the oldest releases ship. They are refused at check time with a clear, located message, never emitted as rules that fail to load: NETMAP needs nftables 0.9.5 (Ubuntu 20.04 has 0.9.3), and ECN control needs tcp flag names added after 0.9.0 (Debian 10). The rest of the configuration compiles and loads.
Every choice is driven by a capability probe that loads a test construct, so a kernel gap counts as well as a parser gap. Compat CI now installs on each release and loads every corpus ruleset with that release's own nftables, including a forced-legacy pass on the oldest userspaces. The package also depends on netbase, which provides /etc/protocols for resolving ipv6-icmp.
See docs/design/legacy-nft.md for the design and the measured capability map.
Full Changelog: v0.2.4...v0.2.5
v0.2.4
shorewall-nft 0.2.4
Three fixes from shorewall-users feedback (thanks, Winston Sorfleet).
rules: the all/any meta-zone with an address restriction. A rule like DROP net all:192.168.45.0/24 failed with unknown zone all. The parser recognised the all/any catch-all only when it stood alone, not when it carried an address. It now splits the address off first, in both rules and blrules, and the address is applied across the expanded zone pairs.
shorewall6 rtrules: bracketed IPv6 addresses. An rtrules SOURCE or DEST like [2607:f2c0:f00e:b700::/64] failed with invalid interface name '[2607'. The brackets exist precisely to keep the address colons out of the interface:address split; the parser now strips them and also handles the interface:[address] combined form.
interfaces: rpfilter is now enforced. The rpfilter option was accepted but warned as not applied. It now emits a strict reverse-path check (fib saddr . iif oif missing drop) per flagged interface, disposed via RPFILTER_DISPOSITION. Established traffic is exempt, so asymmetric return traffic on a multi-ISP box is not caught, and a DHCP client handshake is let through, both matching upstream. sfilter and norfc1918 remain accepted but warned; for anti-spoofing on older setups routefilter (the kernel rp_filter sysctl) is also available.
Full Changelog: v0.2.3...v0.2.4
v0.2.3
shorewall-nft 0.2.3
A fix release for issue #10: upgrading the legacy shorewall rpm no longer
loses /etc/shorewall.
Because shorewall-nft obsoletes the old shorewall package, which owned the
config as %config(noreplace), rpm deleted the unmodified files and renamed the
modified ones to .rpmsave when it erased that package during the swap.
shorewall-nft does not own that configuration (it is the administrator's), so
nothing protected it.
The config is now snapshotted in %pretrans and restored in %posttrans,
without taking ownership. Deleted files are put back and the .rpmsave renames
undone, so the administrator's /etc/shorewall and /etc/shorewall6 survive the
upgrade intact. Fresh installs and shorewall-nft self-upgrades are no-ops.
The .deb was never affected: dpkg keeps conffiles on package removal.
The exact rpm mechanics are now covered by a test that builds a stand-in
shorewall-5.2.8, upgrades to shorewall-nft in a Fedora container, and checks
the config survives.
Full Changelog: v0.2.2...v0.2.3
v0.2.2
shorewall-nft 0.2.2
Gentoo support.
Gentoo has no native package in a repository yet, so this release adds two
supported ways to install, both reusing the shared installer so the on-disk
layout matches the other distros:
- From source.
./packaging/install.sh packaging/shorewallrc.gentoo. The
installer now recognises ashorewallcommand owned by Portage (it checks
qfileandequery) and refuses to overwrite it, so unmerge
net-firewall/shorewallfirst. - From an ebuild.
packaging/gentoo/shorewall-nft-0.2.2.ebuild. Copy it
into an overlay undernet-firewall/shorewall-nft/, runebuild <file> manifest, then emerge it.
Gentoo defaults to OpenRC, so an OpenRC init ships too. One script serves both
families, keyed on the service name; the ebuild installs it as shorewall and
shorewall6. Enable with rc-update add shorewall default. The systemd units
are installed as well and work on a systemd Gentoo.
See docs/distros.md for the Gentoo section. Both install paths are exercised in
CI in a real gentoo/stage3 container.
Full Changelog: v0.2.1...v0.2.2