From ee278848eef48a1c76828e12e2a7ba815fdac9ec Mon Sep 17 00:00:00 2001 From: abrown38 Date: Fri, 23 Oct 2026 00:15:31 +0100 Subject: [PATCH] Docs: matching everything but a few; release builds of a candidate Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 3 +++ docs/development.md | 8 ++++++++ docs/rules.md | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cb769e6..f1e8722 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -121,6 +121,9 @@ All notable changes to Housecarl are documented here. The format follows marked with a red bar. An empty list is never saved as negated (it matched everything anyway, but would have negated what was added to it later). +- docs/rules.md: "Matching everything but a few", on leaving some + addresses out with a zone and "any but", and what to do when the range + isn't a zone. - The rule dialog shows only the zone fields its chain can use: no "Going out on" for input and early, no "Coming in on" for output (they could only be refused). A zone left in a field the chain hides diff --git a/docs/development.md b/docs/development.md index a26e8b4..e280e20 100644 --- a/docs/development.md +++ b/docs/development.md @@ -135,6 +135,14 @@ As for Jarl and Steward: 3. Run `make test && make e2e`. 4. Commit as "Release X", tag it `git tag -a vX -m "Housecarl X"`, and push. +A fix to a release candidate may go out as a build of it rather than a +new candidate: `0.2.0-rc.3+git-`, where `` is the +short ID of the last commit before "Release X" and `` is `git +rev-list --count` of it. The count orders the builds (apt compares it as a +number; the ID alone would order them at random); each sorts after +`0.2.0-rc.3` and before `0.2.0-rc.4`. Debian writes it +`0.2.0~rc.3+git~`. + The tag starts `.gitea/workflows/release.yml`, which checks the tag against `VERSION` and the CHANGELOG, runs the tests, builds the tarballs, the CLI for each OS and the `.deb`s, and publishes them diff --git a/docs/rules.md b/docs/rules.md index a64e377..8cef081 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -165,6 +165,40 @@ hc rule add forward --in wan --status dnat hc rule add forward --in wan -a drop ``` +### Matching everything but a few + +A field matches **any of** its entries, or with `--not-…` ("any but" in +the web UI) anything else; it can't do both. "The LAN except the NAS" is +still one rule: the zone says which network, and the addresses say which +of it to leave out, because zones and addresses are different fields and +a rule needs all of them to match. + +| What you want | One rule | +|---|---| +| the LAN, except the NAS | `--in lan --from nas --not-from` | +| everyone on guest, except one device, has a quota | `--in guest --from tv --not-from --quota 10gbytes,over,daily` | +| the internet, except one host | `--out wan --to blocked --not-to` | + +```sh +# Each device on the LAN: 50 GB a month, but not the NAS (its backups) +hc rule add forward --in lan --out wan --from nas --not-from --quota 50gbytes,over,per-source,monthly -a drop +``` + +Leaving part of an address range out ("10.0.0.0/8 except 10.0.5.0/24") +when it isn't a zone takes one of: + +* **Two rules, the exception first**, when the exception gets the + opposite action: `--from 10.0.5.0/24 -a drop` above `--from + 10.0.0.0/8`. There is no action that skips a rule and goes on, so this + doesn't work when the exception should just fall through to later + rules. +* **Ranges around the hole**: `--from 10.0.0.0-10.0.4.255 --from + 10.0.6.0-10.255.255.255`. +* **A [raw rule](#raw-rules)**: `ip saddr 10.0.0.0/8 ip saddr != 10.0.5.0/24 accept`. + +There's no need to leave a zone out of other zones: an interface belongs +to one zone, so "any of lan, guest" already leaves out everything else. + ### Bandwidth and quotas A **byte rate** limits bandwidth: `--limit 20mbytes/second,over,per-source