From 23c6609a6eb3439d1054aea093a12d8cf15bff1e Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Wed, 29 Apr 2026 22:34:37 +0000 Subject: [PATCH] Ship fips0 nftables security baseline (Linux) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a default-deny nftables ruleset for the fips0 mesh interface as a packaged operator asset, with a companion fips-firewall.service oneshot unit for systemd hosts. Both are shipped disabled — the baseline is an operator conffile and the unit is intentionally not enabled in postinst. Activation is an explicit one-liner: sudo systemctl enable --now fips-firewall.service This is deliberate: silently mutating host firewall state on package install is hostile across the axes that matter (collisions with existing operator nftables / Docker / OPNsense rulesets, surprise behaviour for hosts that already filter elsewhere, conversion of an explicit security decision into an invisible one). The opt-in posture preserves operator agency. The baseline closes a real default-exposure gap: any service on a mesh host bound to a wildcard address (0.0.0.0 or [::]) is reachable from every authenticated peer in the mesh by default. Identity on the mesh is the peer's npub but identity is not authorization, and the mesh is closer to a shared LAN than to the public internet. With this filter loaded, the surface is closed unless a drop-in opens it explicitly. Baseline shape: - Early-return for non-fips0 traffic (every other firewall left undisturbed) - conntrack established/related accept (replies to outbound flows) - ICMPv6 echo-request accept (ping6 reachability) - include "/etc/fips/fips.d/*.nft" — operator-supplied allowances - counter drop default The accompanying docs/fips-security.md lays out the threat model (npub-authenticated mesh is closer to a shared LAN than to the public internet — identity is not authorization), the activation workflow, drop-in extension recipes (allow inbound SSH from a specific peer fd97:.../128, allow HTTP from one /64, etc), drop visibility / debugging via the journal log rule and the drop counter, coexistence with the runtime-managed `inet fips_gateway` table, what the baseline does NOT cover (outbound, application auth, mesh handshake ACL = PR #50 / IDEA-0047 territory), and future cross-OS work (macOS PF baseline, OpenWrt fw4, gateway abstraction). Packaging: - packaging/common/fips.nft → /etc/fips/fips.nft (conffile) - packaging/debian/fips-firewall.service → /lib/systemd/system/ - docs/fips-security.md → /usr/share/doc/fips/ - postinst creates /etc/fips/fips.d/ (mode 0755) on configure - prerm stops/disables fips-firewall.service on remove/purge OpenWrt fw4 path and macOS PF baseline are deferred — separate asymmetries, separate work. --- CHANGELOG.md | 9 + Cargo.toml | 5 +- docs/fips-security.md | 344 +++++++++++++++++++++++++ packaging/common/fips.nft | 128 +++++++++ packaging/debian/fips-firewall.service | 17 ++ packaging/debian/postinst | 13 +- packaging/debian/prerm | 2 + 7 files changed, 516 insertions(+), 2 deletions(-) create mode 100644 docs/fips-security.md create mode 100644 packaging/common/fips.nft create mode 100644 packaging/debian/fips-firewall.service diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c439c1..7a93634 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +#### Security + +- Mesh-interface nftables baseline (Linux). Ships `/etc/fips/fips.nft` + as a documented operator conffile and `fips-firewall.service` + (disabled by default) for default-deny inbound on the `fips0` mesh + interface. Operators enable explicitly with + `systemctl enable --now fips-firewall.service`. Drop-ins in + `/etc/fips/fips.d/*.nft`. See `docs/fips-security.md`. + #### Platform Support - Windows platform support: wintun TUN device, TCP control socket on diff --git a/Cargo.toml b/Cargo.toml index 75f7d93..e1b718a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -76,15 +76,18 @@ assets = [ ["target/release/fipstop", "/usr/bin/", "755"], ["packaging/common/fips.yaml", "/etc/fips/fips.yaml", "600"], ["packaging/common/hosts", "/etc/fips/hosts", "644"], + ["packaging/common/fips.nft", "/etc/fips/fips.nft", "644"], ["packaging/debian/fips.service", "/lib/systemd/system/fips.service", "644"], ["packaging/debian/fips-dns.service", "/lib/systemd/system/fips-dns.service", "644"], + ["packaging/debian/fips-firewall.service", "/lib/systemd/system/fips-firewall.service", "644"], ["packaging/common/fips-dns-setup", "/usr/lib/fips/fips-dns-setup", "755"], ["packaging/common/fips-dns-teardown", "/usr/lib/fips/fips-dns-teardown", "755"], ["packaging/debian/fips.tmpfiles", "/usr/lib/tmpfiles.d/fips.conf", "644"], ["target/release/fips-gateway", "/usr/bin/", "755"], ["packaging/debian/fips-gateway.service", "/lib/systemd/system/fips-gateway.service", "644"], + ["docs/fips-security.md", "/usr/share/doc/fips/fips-security.md", "644"], ] -conf-files = ["/etc/fips/fips.yaml", "/etc/fips/hosts"] +conf-files = ["/etc/fips/fips.yaml", "/etc/fips/hosts", "/etc/fips/fips.nft"] [dev-dependencies] tempfile = "3.15" diff --git a/docs/fips-security.md b/docs/fips-security.md new file mode 100644 index 0000000..23f9a89 --- /dev/null +++ b/docs/fips-security.md @@ -0,0 +1,344 @@ +# FIPS Mesh-Interface Security + +This document describes the operator-facing security posture of the +`fips0` mesh interface on Linux: the threat model, the default-deny +nftables baseline shipped as `/etc/fips/fips.nft`, how to enable it, +and how to extend it with per-host allowances. + +The baseline is a documented operator conffile, not an auto-loaded +package side-effect. Activation is an explicit one-liner. The +rationale for that design and the operator workflow follow. + +## Threat Model for `fips0` + +The mesh is a flat layer-3 segment. Every authenticated peer on the +mesh can route packets to every other peer's `fips0` address. Identity +on the mesh is the peer's npub — the FMP link layer authenticates that +identity with Noise IK and the FSP session layer authenticates +endpoints with Noise XK — but identity is **not** authorization. +Knowing who sent a packet does not, by itself, decide whether the +local host should accept it. + +That means: any service on a mesh host that binds to a wildcard +address (`0.0.0.0`, `[::]`, or any IPv6 address that includes the +`fips0` interface in its scope) is reachable from every peer in the +mesh by default. There is no NAT, no perimeter firewall, no +"local-only" address space between you and an arbitrary peer. The +mesh is closer to a shared LAN than to the public internet. + +Compare to the corresponding internet trust assumptions: + +| Surface | Public internet | FIPS mesh (no baseline) | +|---|---|---| +| Reachability from arbitrary peer | Mediated by NAT, firewalls, ISPs | Direct | +| Default identity | None | Peer npub (authenticated) | +| Default authorization | None | None | +| Accidental exposure cost | Low (NAT hides you) | High (every peer sees you) | + +The third row is the gap this document closes. The default-deny +baseline removes "accidental exposure" from the failure modes an +operator has to think about. + +## The Default-Deny Baseline + +The shipped baseline is `/etc/fips/fips.nft`. It defines a single +nftables table, `inet fips`, with one chain hooked at `input`. The +chain: + +1. Returns immediately for any packet not arriving on `fips0`. This + makes the table a no-op for every other interface — Docker, Tor, + the host's main filter table, OPNsense, anything. +2. Accepts packets that conntrack identifies as `established` or + `related`. Replies to outbound flows initiated from the mesh host + come back; ICMPv6 errors related to existing flows (Packet Too + Big, Destination Unreachable) come back. +3. Accepts ICMPv6 echo-request, so `ping6` reachability tests work. +4. Includes operator drop-ins from `/etc/fips/fips.d/*.nft`. An empty + directory is fine — the include glob simply matches nothing. +5. Falls through to `counter drop`. Every dropped packet increments + the counter, visible via `nft list table inet fips`. + +Outbound from `fips0` is unrestricted. The baseline is concerned only +with what the mesh host accepts, not what it sends. + +The file is a documented dpkg conffile. Operator edits to +`/etc/fips/fips.nft` are preserved across upgrades, the same way +edits to `/etc/fips/fips.yaml` and `/etc/fips/hosts` are preserved. +If the packaged baseline is ever updated upstream, dpkg prompts the +operator on upgrade rather than silently overwriting local changes. + +The canonical artifact is the file itself; read it for the inline +documentation that the rest of this document references. + +## Loading the Baseline + +The package ships `fips-firewall.service`, a systemd oneshot unit +that runs `nft -f /etc/fips/fips.nft` on start and removes the +`inet fips` table on stop. It is **not** enabled by default. To +activate the baseline: + +```sh +sudo systemctl enable --now fips-firewall.service +``` + +This loads the table now and arranges for it to load on every +subsequent boot. To disable and tear it down: + +```sh +sudo systemctl disable --now fips-firewall.service +``` + +To reload after editing `/etc/fips/fips.nft` or adding a drop-in +under `/etc/fips/fips.d/`: + +```sh +sudo systemctl reload-or-restart fips-firewall.service +``` + +(or equivalently `sudo nft -f /etc/fips/fips.nft`, since the file is +idempotent — it begins with `add table inet fips; flush table inet +fips;` so re-running it replaces the live ruleset atomically.) + +### Why no auto-load on package install + +The `postinst` script does **not** enable `fips-firewall.service`. +This is deliberate. Quietly mutating host firewall state on package +install is hostile on every axis that matters: it surprises operators +who already have their own nftables ruleset, it can collide with +podman/Docker/OPNsense integrations even though the early-return +makes it technically safe, and it converts an explicit security +decision into an invisible one. The mesh-interface filter belongs to +the operator, not to the package's `postinst`. + +The activation gesture is one short, well-formed command. The +rationale is documented in the file's inline header and in this +document. That is enough; auto-loading would trade discoverability +for no real gain. + +### Coexistence with other firewalls + +The `inet fips` table only matches packets arriving on `fips0`. +Anything else returns from the chain on the first rule. Specifically: + +- **Docker / containerd** install nftables rules in the `ip` and `ip6` + families and operate on `docker0`, `br-*`, and `veth*` + interfaces. They do not touch `fips0`. The two tables coexist + without interference. +- **Tor** runs in user space and does not install firewall rules. The + baseline is independent of Tor's onion-service and SOCKS listeners. +- **OPNsense** is an upstream perimeter device. The baseline runs on + the local host and applies only to traffic that has already reached + the host's `fips0` interface. They do not interact. +- **The host's main `/etc/nftables.conf`** typically defines a + separate `inet filter` table. nftables allows multiple tables in + the same family to coexist; both run in parallel at hook + `input`/priority 0 and the `iifname != "fips0" return` rule keeps + the `inet fips` table from interfering with anything outside the + mesh interface. +- **`inet fips_gateway`**, when `fips-gateway` is running, manages + DNAT/SNAT on the LAN-facing interface to translate virtual IPs to + mesh addresses. It is a separate concern owned by the gateway + binary and is unrelated to this baseline. See the section below. + +If you prefer to fold the baseline into your existing +`/etc/nftables.conf` instead of using the systemd unit, you can: + +```nft +# in /etc/nftables.conf +include "/etc/fips/fips.nft" +``` + +In that case do not enable `fips-firewall.service` — let the host's +main nftables setup own the loading. The two are mutually exclusive. + +## Operator Extension via `/etc/fips/fips.d/*.nft` + +The baseline drops everything inbound on `fips0` except conntrack +replies and ICMPv6 echo. To open specific services to specific peers, +drop a file into `/etc/fips/fips.d/` ending in `.nft`. Each file is +included inline into the `inbound` chain at the marked point and may +contain any nftables rule lines valid in that context. + +Reload after editing: + +```sh +sudo systemctl reload-or-restart fips-firewall.service +# or: sudo nft -f /etc/fips/fips.nft +``` + +Common patterns follow. + +### Allow inbound SSH from a specific peer + +```nft +# /etc/fips/fips.d/ssh-from-bastion.nft +ip6 saddr fd97:1234:5678:9abc:def0:1234:5678:9abc tcp dport 22 accept +``` + +The source filter is the peer's mesh address. To find a peer's mesh +address, look in their `fips.pub` (which contains the npub) and +derive the `fd97:...` address from it, or query the running daemon: + +```sh +fipsctl show identity-cache +fipsctl show peers +``` + +### Allow inbound HTTP from one /64 of peers + +If you operate a logical group of peers under a shared address +prefix, source-filter by the prefix: + +```nft +# /etc/fips/fips.d/http-from-cluster.nft +ip6 saddr fd97:1234:5678:9abc::/64 tcp dport 80 accept +``` + +The mesh address space is `fd00::/8`, so `/64` filters carve out +manageable subgroups. Plan your prefixes before deploying many peers. + +### Allow inbound DNS broadly + +Some services need to be reachable from any mesh peer (a public DNS +resolver, a public bootstrap node): + +```nft +# /etc/fips/fips.d/dns-public.nft +udp dport 53 accept +tcp dport 53 accept +``` + +Omit the source filter only when the service is intended to be +universally reachable on the mesh. The baseline's purpose is to make +"universally reachable" an explicit decision rather than the default. + +### Multiple peers, one service + +```nft +# /etc/fips/fips.d/git-from-trusted.nft +ip6 saddr { + fd97:1111:2222:3333:4444:5555:6666:7777, + fd97:8888:9999:aaaa:bbbb:cccc:dddd:eeee +} tcp dport 9418 accept +``` + +Set syntax keeps multi-peer rules readable and is more efficient than +a chain of individual rules. + +## Drop Visibility and Debugging + +The baseline counter increments on every dropped packet. Inspect it: + +```sh +sudo nft list table inet fips +``` + +Look for the `counter packets N bytes M drop` line at the bottom of +the `inbound` chain. A non-zero counter means peers are sending +traffic that hits the default-deny — usually benign (probes, +neighbor discovery) but occasionally a misconfigured drop-in. + +To see which packets are being dropped, uncomment the `log` line +near the bottom of `/etc/fips/fips.nft`: + +```nft +log prefix "fips drop: " level info limit rate 10/minute +``` + +Reload: + +```sh +sudo nft -f /etc/fips/fips.nft +``` + +Then tail the kernel log: + +```sh +sudo journalctl -k -f -g "fips drop:" +``` + +The rate-limit prevents flooding the journal under sustained probing. +Adjust the rate, log level, or prefix as needed for the situation. +Re-comment the rule when you are done; production hosts do not need +the log line on by default. + +## Coexistence with `inet fips_gateway` + +When `fips-gateway` is running, it manages a separate nftables +table, `inet fips_gateway`, containing the DNAT and masquerade rules +that translate between the gateway's virtual-IP pool and mesh +addresses on the LAN-facing interface. That table is created and +torn down by the gateway binary at runtime and is not an operator +artifact in the same sense as `inet fips`. + +The two tables do not interfere: + +- `inet fips` filters inbound on `fips0`. +- `inet fips_gateway` performs NAT on the LAN interface. + +They operate on different interfaces and at different hook points +(`input` filter vs. `prerouting`/`postrouting` NAT). Both can be +loaded simultaneously on a gateway host, and that is the intended +deployment shape. See `docs/design/fips-gateway.md` for the gateway +table's structure. + +## What the Baseline Does Not Cover + +The baseline is one half of a defense-in-depth posture. It is +explicitly not: + +- **Outbound filtering.** Anything the mesh host originates on + `fips0` is unrestricted. If you need to constrain what the host + can send to the mesh, add rules to a separate chain hooked at + `output` — out of scope for the baseline. +- **Application-layer authorization.** The baseline decides whether + a packet reaches a service. It does not decide whether the peer + npub on the other end is allowed to use that service. That is the + application's responsibility (e.g., an `authorized_keys` file for + SSH, an ACL in the application's configuration). +- **ACL on the mesh handshake.** The FMP Noise IK handshake currently + authenticates the peer's npub but does not consult an allowlist + before establishing a link. A peer with a known npub can connect + and become a routing peer regardless of operator intent. Mesh- + level ACLs are tracked under IDEA-0047 / PR #50 and are a separate + concern from the inbound packet filter described here. +- **Compromised peers.** A peer whose key has been stolen or whose + host has been taken over is, by mesh-level identity, still that + peer. Source-address filtering in drop-ins limits damage, but the + baseline cannot revoke trust on its own. + +Treat the baseline as removing the "wide-open by default" failure +mode. Higher-layer authorization decisions are the operator's and +the application's, the same as on any other shared network. + +## Future Work + +The current baseline is Linux-only. Parallel work for other targets: + +- **macOS PF baseline.** macOS uses Packet Filter (PF), inherited + from OpenBSD. PF maps cleanly onto the same conceptual model as + nftables: stateful inspection (`keep state` ≈ `ct state + established,related`), default policy, anchor-based modular rule + loading. A `packaging/macos/fips.pf` will land alongside the + Linux baseline with the same posture: documented asset, no + auto-load, operator opts in via launchd. The macOS interface name + is `utunN` rather than `fips0`, so the rule template needs runtime + substitution or a PF interface group assigned at TUN bring-up; + this is being worked through with the macOS port. +- **OpenWrt fw4 path.** OpenWrt's fw4 already drives nftables under + the hood, but rules go into `/etc/nftables.d/` includes or UCI + entries in `/etc/config/firewall`, not a free-standing + `fips.nft`. The ipk will ship a layout-compatible variant or + document the operator setup separately, decided when the OpenWrt + packaging is updated. +- **Cross-OS gateway abstraction.** `fips-gateway` is currently + Linux-only because `src/gateway/nat.rs` uses the `rustables` + netlink API directly. macOS gateway support requires a PF-backed + equivalent behind a shared backend trait. This is a larger lift + than the static baseline and is tracked separately under the same + IDEA thread. + +When those land, this document will grow per-OS sections describing +each baseline's load mechanism and extension points. The threat +model and the operator-extension principle are the same on every OS; +only the filter syntax and the activation gesture differ. diff --git a/packaging/common/fips.nft b/packaging/common/fips.nft new file mode 100644 index 0000000..8885db6 --- /dev/null +++ b/packaging/common/fips.nft @@ -0,0 +1,128 @@ +#!/usr/sbin/nft -f +# +# ╔═══════════════════════════════════════════════════════════════════╗ +# ║ fips0 nftables policy — security baseline ║ +# ╚═══════════════════════════════════════════════════════════════════╝ +# +# Polices ONLY the fips0 mesh interface — every packet not arriving +# on fips0 returns immediately, leaving Docker, Tor, OPNsense, the +# host's main /etc/nftables.conf, and any other firewall undisturbed. +# +# ─── DEFAULT POLICY ───────────────────────────────────────────────── +# +# INBOUND on fips0: DROP everything except — +# • replies to outbound flows we initiated +# (conntrack established/related) +# • ICMPv6 echo-request (ping6 reachability) +# • rules in /etc/fips/fips.d/*.nft drop-ins +# +# OUTBOUND from fips0: unrestricted +# +# Why default-deny: services binding to 0.0.0.0 or [::] accept +# connections on fips0 by default. This baseline ensures that +# accidental exposure of HTTP, SSH, databases, etc. through the +# mesh is impossible without explicit operator action. +# +# ─── LOADING / RELOADING ──────────────────────────────────────────── +# +# Apply this file: +# +# sudo nft -f /etc/fips/fips.nft +# +# To make it persist across reboots, load it from your preferred +# mechanism: a systemd unit that runs `nft -f` on start, an include +# from /etc/nftables.conf, etc. +# +# Verify the loaded ruleset: +# +# sudo nft list table inet fips +# +# ─── ADDING INBOUND ALLOWANCES ────────────────────────────────────── +# +# Drop a file into /etc/fips/fips.d/ ending in .nft. Each file is +# included inline into the `inbound` chain at the marked point below. +# Format: chain-context rule lines, one per line. For example: +# +# /etc/fips/fips.d/services.nft +# ──────────────────────────── +# tcp dport 22 accept +# tcp dport 80 accept +# udp dport 53 accept +# ip6 saddr fd97:467a::/64 tcp dport 22 accept # SSH from one /64 +# ip6 saddr fd97:.../128 tcp dport 8443 accept # one specific peer +# +# After editing, reload: +# +# sudo nft -f /etc/fips/fips.nft +# +# (or trigger your loading mechanism's reload). +# +# Source-based filtering uses the peer's mesh address (npub-derived +# fd97:... format). To find a peer's mesh address, look in their +# fips.pub or query the daemon. +# +# Note: an empty /etc/fips/fips.d/ is fine — the include glob simply +# matches nothing and the baseline policy applies as-is. +# +# ─── DEBUGGING / DROP VISIBILITY ──────────────────────────────────── +# +# To see drops in the systemd journal: +# 1. Uncomment the `log` rule near the bottom of the inbound chain. +# 2. Reload: sudo nft -f /etc/fips/fips.nft +# 3. Tail: sudo journalctl -k -f -g "fips drop:" +# +# Drop counter (always on, no log): +# sudo nft list table inet fips +# +# ─── COEXISTENCE WITH OTHER NFTABLES TABLES ───────────────────────── +# +# This table lives in the `inet` family. Other tables you may see: +# +# inet fips_gateway — created by the fips-gateway binary when +# running (separate concern from this file). +# See the fips-gateway design doc for details. +# +# ip / ip6 family — Docker, /etc/nftables.conf, etc. +# Independent of this table. +# +# All hook at standard filter priority (0). Order between same-family +# same-priority tables is determined by load order, but the early- +# return for non-fips0 traffic makes this chain a no-op for anything +# not on fips0, so coexistence is safe. + +# ━━━ Idempotent table replacement ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ +add table inet fips +flush table inet fips + +table inet fips { + + chain inbound { + type filter hook input priority 0; policy accept; + + # Non-fips0 traffic returns immediately — chain is a no-op + # for anything not arriving on the fips0 mesh interface. + iifname != "fips0" return + + # Replies to outbound flows + related ICMPv6 errors + # (Packet Too Big for PMTU, Destination Unreachable, etc.) + ct state established,related accept + + # ICMPv6 echo-request — ping6 reachability tests. + meta nfproto ipv6 icmpv6 type echo-request accept + + # Operator-supplied allow rules from drop-in files. + # See "ADDING INBOUND ALLOWANCES" in the header. + include "/etc/fips/fips.d/*.nft" + + # Optional: log drops to journal (rate-limited). + # Uncomment to enable, then reload via `nft -f`. + # + #log prefix "fips drop: " level info limit rate 10/minute + + # Default deny on fips0 inbound. Counter visible via + # `nft list table inet fips`. + counter drop + } +} + +# ━━━ END OF FILE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ diff --git a/packaging/debian/fips-firewall.service b/packaging/debian/fips-firewall.service new file mode 100644 index 0000000..7720d9b --- /dev/null +++ b/packaging/debian/fips-firewall.service @@ -0,0 +1,17 @@ +# Firewall is not enabled by default. Enable with: systemctl enable --now fips-firewall +[Unit] +Description=FIPS mesh-interface nftables baseline +Documentation=file:///etc/fips/fips.nft file:///usr/share/doc/fips/fips-security.md +Before=fips.service +ConditionPathExists=/etc/fips/fips.nft + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/sbin/nft -f /etc/fips/fips.nft +ExecStop=-/usr/sbin/nft delete table inet fips +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target diff --git a/packaging/debian/postinst b/packaging/debian/postinst index 9920b18..3e2c200 100755 --- a/packaging/debian/postinst +++ b/packaging/debian/postinst @@ -9,12 +9,23 @@ case "$1" in groupadd --system fips fi + # Drop-in directory for operator nftables rules included by + # /etc/fips/fips.nft. Empty by default; the include glob matches + # nothing cleanly out of the box. + if [ ! -d /etc/fips/fips.d ]; then + mkdir -p /etc/fips/fips.d + chmod 755 /etc/fips/fips.d + fi + # Ensure runtime directory exists with correct ownership if [ -d /run/systemd/system ]; then systemd-tmpfiles --create /usr/lib/tmpfiles.d/fips.conf 2>/dev/null || true fi - # Reload systemd and enable services + # Reload systemd and enable services. fips-firewall.service is + # intentionally NOT enabled here — operators opt in explicitly + # with `systemctl enable --now fips-firewall.service`. See + # /usr/share/doc/fips/fips-security.md for the rationale. if [ -d /run/systemd/system ]; then systemctl daemon-reload systemctl enable fips.service 2>/dev/null || true diff --git a/packaging/debian/prerm b/packaging/debian/prerm index b8961ac..399f5b6 100755 --- a/packaging/debian/prerm +++ b/packaging/debian/prerm @@ -9,6 +9,8 @@ case "$1" in systemctl disable fips-dns.service 2>/dev/null || true systemctl stop fips.service 2>/dev/null || true systemctl disable fips.service 2>/dev/null || true + systemctl stop fips-firewall.service 2>/dev/null || true + systemctl disable fips-firewall.service 2>/dev/null || true systemctl daemon-reload fi ;;