Repository navigation
iptables backend (#23) - #24
Merged
Merged
Conversation
On a stock cloud image (Ubuntu with iptables-persistent, INPUT ending in a catch-all REJECT, docker chains) 0.4.1 picked nftables and listed ip filter / INPUT as writable: an allow would have been appended after the REJECT as a native nft rule, never matching, possibly breaking iptables-save, and gone at the next boot. The new backend reads iptables-save/ip6tables-save (-c), inserts every rule in front of the chain's catch-all with the position and the reason in the preview, deletes by specification, and makes persisting a separate, previewed step (netfilter-persistent save, or service iptables save on RHEL) with a diff against the saved files. The header, the status line and --check report runtime-vs-saved drift, ignoring the chains docker and tailscaled rebuild at start. Staging reuses the session with a dialect: iptables-restore --noflush per family, rolled back from a filter snapshot. Selection picks iptables when its loader is active or enabled, when the nft ruleset shows iptables-nft filter tables with rules of the operator's own, or when the legacy tables carry rules; docker plumbing alone does not count. The nftables backend now refuses to write into any xtables table and points at --backend iptables. Fixtures are scrubbed captures from a real host; a namespace test drives a real iptables under unshare -rn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MbCfX3T8khyd9hsrN5kMo3
The README gets an iptables section (where a rule lands, persisting as its own step, how the backend is chosen, what nftables now refuses), the demo and flag lists name it, and three screenshots from --demo=iptables show the insert before the catch-all and the persist diff. test/smoke.sh gains an iptables branch: selection and its reason, the variant, the INPUT count against iptables -S, the placement before the catch-all, drift reported for a rule added behind the tool's back and cleared when it goes, and --backend nftables refusing ip filter. It passed 18/18 on the lab's Ubuntu 24.04 guest converted to the cloud-image shape, and the compat line for iptables 1.8.10 is harvested from that run. The header's reminder to persist now appears only when the reload shows drift, and the delete dialog names the port on backends whose destination column does not carry it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MbCfX3T8khyd9hsrN5kMo3
Naming the fourth backend pushed it to 86; the validate job refuses that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MbCfX3T8khyd9hsrN5kMo3
Naming the fourth backend pushed the tagline, the description, the W key and needs_sudo past their maxLength; the package description follows the tagline, as check-nfpm requires. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MbCfX3T8khyd9hsrN5kMo3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #23.
What
A fourth backend, iptables, for hosts whose filter tables are written through the xtables tools (iptables-nft or legacy) and restored at boot by iptables-persistent / netfilter-persistent (Debian, Ubuntu) or iptables-services (Fedora, RHEL): the stock cloud-image shape where INPUT ends in
-j REJECT --reject-with icmp-host-prohibitedand docker has added its chains.internal/backends): a running ufw or firewalld still wins. Then iptables when its loader is active or enabled (netfilter-persistent, or theiptablesunit of iptables-services), when the nft ruleset shows iptables-nft filter tables with rules of the operator's own, or when the legacy tables carry rules. Docker plumbing alone does not count, so a pure-nft host running docker stays on nftables. The reason line names the loader and the file it restores, and any native nft table the iptables backend does not show.iptables-save -c/ip6tables-save -c(nf_tables and legacy). One view per built-in chain and family (INPUT (iptables)besideINPUT (ip6tables)), then every other chain holding a rule, read-only. Chains of docker, tailscaled, kube-proxy, fail2ban... are shown and never written.iptables -I <chain> <pos>with the position right before the first catch-all REJECT/DROP; the preview shows the position and why. An explicit position after the catch-all is refused. Deletes go by specification (iptables -D INPUT <spec>), not by number. Policies via-P.W:netfilter-persistent save(Debian/Ubuntu) orservice iptables save+service ip6tables save(RHEL), with a unified diff against the saved files. Header factsaved: in sync/saved: differs: N lines not saved (W), a status-line reminder after a change, and--check/--reportreport runtime-vs-saved drift. The comparison covers the filter table and ignores the chains other daemons rebuild at start (a host where tailscaled addedts-inputafter the last save reads as in sync).iptables-restore --noflushper family (all or nothing per family) and rolls back by restoring a filter-table snapshot taken right before the apply (nat is left alone).ip/ip6table with iptables' names and upper-case built-in chains or xtables expressions is read-only, with a message pointing at--backend iptables; when those tables carry operator rules, DetectManagement names iptables as the firewall in charge.--demo=iptables(OCI-like: INPUT ending in REJECT, docker chains, metadata chain), a--checkiptablesblock (variant, writable chains and placement, open/shadowed INPUT ports, what ends INPUT, persistence + drift, staging), a--reportline, a compat entry (minimum 1.6,iptables --version), README section, three screenshots, and a smoke branch withrecord_compat.Tests
nft -j list ruleset, plus a docker-on-nft fixture captured in a namespace.TestAgainstRealIptablesdrives real iptables underunshare -rn(insert before REJECT, staged batch, rollback, a rejected batch changes nothing): passes locally with iptables 1.8.11 (nf_tables).make lintclean (gofmt, vet, exec boundary, golangci-lint),go test -race ./...green.Real case (read-only)
The dev build's
--checkon the real host (not mutated), excerpt:Lab evidence (tui-lab
ubuntuguest, Ubuntu 24.04.5)The guest was snapshotted, then made to look like the cloud image: ufw disabled (iptables-persistent removes it),
iptables-persistentinstalled, the scrubbed cloudrules.v4(INPUT ending in the REJECT, docker and metadata chains) loaded and saved. All flows below were driven in the real TUI through tmux; the guest was restored to its snapshot afterwards.Open 51820/udp: inserted before the REJECT
Open 443/tcp, then persist (W) with the diff
Reboot 1: rules survive, before the REJECT
On the guest after
systemctl reboot: boot time, boot_id,systemctl is-active netfilter-persistent,iptables -S INPUT, then--check.Delete 443/tcp, persist, reboot 2
The second boot has a new boot_id (the previous one is at the end of the block).
Staged apply through iptables-restore, keep window expires, rollback
lab.sh test tui-firewall --bin ... ubuntuNot covered
service iptables save/service ip6tables save) but not run on a lab guest: the Fedora guest was busy.🤖 Generated with Claude Code
https://claude.ai/code/session_01MbCfX3T8khyd9hsrN5kMo3