internal/matrix walks each pair's rules in order, as nftables would, for new connections: zone → zone (forward), zone → the firewall (input) and back (output), with the built-ins that act on new connections. A rule for the whole pair decides it; one for part of its traffic (addresses, services, times, rates, a quota) is an exception; the rest falls to the policy. Rules whose addresses all lie in networks connected to other zones are left out of a pair. GET /matrix (with ?changeset, pending changes), hc matrix [FROM TO], and a Matrix page whose cells open their rules. e2e: 166 checks, among them the matrix of the maintainer's imported ruleset. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
107 lines
6.2 KiB
Markdown
107 lines
6.2 KiB
Markdown
# Changelog
|
|
|
|
All notable changes to Housecarl are documented here. The format follows
|
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
[Semantic Versioning](https://semver.org/).
|
|
|
|
## [Unreleased]
|
|
|
|
The first version of Housecarl, a firewall manager for nftables, built
|
|
the way Jarl and Steward are.
|
|
|
|
### Added
|
|
|
|
- **Zones, address sets and services:** interfaces grouped by what they
|
|
connect to (wildcards like `incusbr*`; external zones face the
|
|
internet); sets of IPv4 and IPv6 addresses, prefixes and ranges, mixed;
|
|
ports and ICMP types by name, with twenty built in (docs/rules.md).
|
|
- **Rules** in four chains (input, forward, output, and early, before
|
|
connection tracking), in order, matching by zone, address, service,
|
|
family, connection state and status, days and hours, a rate (also per
|
|
source address), and a connection count; accept, drop, reject (ICMP or
|
|
TCP reset) or log. Raw nftables rules for the rest.
|
|
- **IPv4 and IPv6 together:** one rule becomes the nftables rules each
|
|
family needs.
|
|
- **NAT:** port forwards as one object (DNAT, the forward accept, hairpin
|
|
NAT, and optionally an IPv6 pinhole to a host's own port); source NAT
|
|
(masquerade or an address; NAT66 on request); redirects to the firewall
|
|
(docs/nat.md).
|
|
- **Built-ins**, each switchable: loopback, established connections,
|
|
invalid packets, ICMPv6 (RFC 4890), ping from internal zones, DHCPv6
|
|
client replies, antispoofing with your own prefixes, MSS clamping, and
|
|
a flowtable fast path.
|
|
- **Changesets, as in Jarl:** changes staged to be reviewed and applied
|
|
together, as one history entry. Each is checked as it is staged; the
|
|
review shows the problems, nftables' check and the diff of the ruleset.
|
|
The web UI collects edits as pending changes by default (pending rows,
|
|
a bar with Review and Apply now, a Changes page), with a switch for live
|
|
edits, and Undo in History is staged like any edit; hc stages with
|
|
`-C ID` or `HOUSECARL_CHANGESET`, and has `hc
|
|
changeset create/list/show/diff/apply/discard/remove`. An applied
|
|
changeset is on probation like any change. `--dry-run` shows the
|
|
ruleset's diff too (docs/design.md, docs/cli.md).
|
|
- **Bandwidth limits and quotas:** rate limits in bytes (`--limit
|
|
20mbytes/second,over,per-source`), per source or per destination;
|
|
quotas, an allowance of traffic per rule or per address, reset daily,
|
|
weekly, monthly on a chosen day, or by hand, kept across changes,
|
|
restarts and reboots (`hc quotas`, `hc rule reset-quota`, usage on the
|
|
rules page). Rules that count traffic are checked before established
|
|
connections are accepted, so they see every packet. Per-address limits
|
|
group IPv6 by /64 by default (`--group-v4`, `--group-v6`). Meters,
|
|
byte rates and quotas in an imported ruleset carry over
|
|
(docs/rules.md).
|
|
- **Changes checked twice and applied atomically:** validation of the
|
|
whole configuration with stable problem codes (docs/validation.md),
|
|
then `nft -c`, then one `nft -f` transaction that replaces Housecarl's
|
|
own table, `inet housecarl`, and nothing else. Dynamic sets' entries
|
|
and the counters carry across.
|
|
- **Probation:** a change made over the network rolls itself back unless
|
|
confirmed within two minutes. The web UI and `hc` confirm their own
|
|
changes once they reach Housecarl again over a new connection, from the
|
|
same address (a change that cuts its client off can't, and rolls back);
|
|
`--no-confirm` and the "a person confirms each change" setting leave it
|
|
to `hc confirm` or the banner;
|
|
changes through the local socket are kept at once; a restart rolls
|
|
back what was pending. No rule is forced to keep SSH or the web UI
|
|
open.
|
|
- **At boot:** the confirmed ruleset is loaded by
|
|
`housecarl-ruleset.service` before the network comes up, without
|
|
housecarld. An empty configuration applies nothing.
|
|
- **Warnings about the machine:** while `nftables.service` is enabled
|
|
(it loads `/etc/nftables.conf` at boot, and flushes every table when
|
|
stopped), and while the table an import came from still applies.
|
|
- **The zone matrix** (Matrix, `hc matrix`): what the rules do to new
|
|
connections between zones and to and from the firewall, worked out
|
|
from the rules in order, with each pair's exceptions; rules about
|
|
networks connected to other zones are left out of a pair.
|
|
- **Connections and tracing:** the connections the kernel tracks, with
|
|
their NAT, and closing them so the rules check them again (Traffic →
|
|
Connections, `hc connections`); a rule option, "every packet", for
|
|
blocks that stop connections already open; and a packet tracer
|
|
(Traffic → Trace, `hc trace`) that follows packets through every
|
|
table's rules and names what accepted or dropped them.
|
|
- **Hits and the log:** packet and byte counters for every rule, NAT rule,
|
|
built-in and policy; packets logged by rules and policies, read from
|
|
netlink log group 4171 (`hc log -f`, the Log page).
|
|
- **Dynamic sets** whose entries expire by themselves, changed through
|
|
their own API with tokens that may be limited to one set
|
|
(`sets:write:guests`).
|
|
- **Import** of an existing nftables ruleset (`hc import`): rules keep
|
|
their order, defines name the sets, DNAT becomes port forwards, what
|
|
can't be translated stays as raw rules, with notes; `hc takeover`
|
|
deletes the old table, on probation (docs/import.md). DNAT maps and
|
|
verdict maps are expanded into one port forward or rule per element.
|
|
- **The `hc` CLI, the REST API and the web UI** (dashboard, rules per
|
|
chain with hits and reordering, NAT, zones, sets, services, the log,
|
|
settings, import, history with undo; the rule dialog keeps the less
|
|
used parts, such as rate limits, quotas and time windows, behind "+"
|
|
buttons; each chain's built-ins are listed, with their hits, and
|
|
switched in a window), with users, roles, scoped API
|
|
tokens, sessions, the audit log, and the web UI's certificate from
|
|
Let's Encrypt through Jarl, as in Steward.
|
|
- **Packaging:** Debian packages `housecarl` and `housecarl-cli`, a
|
|
systemd unit whose only privilege is `CAP_NET_ADMIN`, daily backups.
|
|
- **The Housecarl logo:** a carved Nordic doorway in Jarl's blue, with a
|
|
simplified version for small sizes, lighter on dark backgrounds; and a
|
|
HOUSECARL wordmark in Jarl's and Steward's angular letters.
|