Put back the forward policy ufw disable opens when the found firewall is retired, as measured on a lab machine (hq ADR 0100)

This commit is contained in:
2026-09-22 18:03:30 +02:00
parent 588ab71d14
commit 8e2f75454d
4 changed files with 301 additions and 1 deletions
+51 -1
View File
@@ -419,11 +419,61 @@ func Enable(ctx context.Context, run Runner) error {
// Disable retires ufw without flushing it: its configuration stays on disk, and the container
// runtime's rules are not its to remove.
//
// **Nor is the forward policy ufw's to open.** Measured on a lab machine running the container
// runtime with a published port (testdata/ufw-disable-iptables-before.txt and -after.txt):
// `ufw disable` sets every built-in chain's policy to accept, the forward chain's among them. The
// runtime had set that one to drop when it turned forwarding on, and it does not set it again while
// forwarding stays on — not even on a restart. Left so, a retired ufw turns the machine into a
// router for anyone who can reach it. So each family's forward policy is read before, and one that
// was drop is put back and read back.
func Disable(ctx context.Context, run Runner) error {
type family struct{ tool, policy string }
var before []family
for _, tool := range []string{"iptables", "ip6tables"} {
if policy, ok := forwardPolicy(ctx, run, tool); ok {
before = append(before, family{tool, policy})
}
}
if _, err := run(ctx, "ufw", "disable"); err != nil {
return fmt.Errorf("disabling ufw: %w", err)
}
return expectActive(ctx, run, false)
if err := expectActive(ctx, run, false); err != nil {
return err
}
for _, f := range before {
if f.policy != "DROP" {
continue
}
if now, ok := forwardPolicy(ctx, run, f.tool); ok && now == "DROP" {
continue
}
if _, err := run(ctx, f.tool, "-P", "FORWARD", "DROP"); err != nil {
return fmt.Errorf("ufw is disabled, and %s's forward policy, which was drop, could not be put back: %w",
f.tool, err)
}
if now, ok := forwardPolicy(ctx, run, f.tool); !ok || now != "DROP" {
return fmt.Errorf("ufw is disabled, and %s's forward policy was put back to drop and reads %q",
f.tool, now)
}
}
return nil
}
// forwardPolicy reads the forward chain's policy the way iptables prints it: "-P FORWARD DROP".
// Not ok when the tool is absent or says nothing readable.
func forwardPolicy(ctx context.Context, run Runner, tool string) (string, bool) {
out, err := run(ctx, tool, "-S", "FORWARD")
if err != nil {
return "", false
}
for _, line := range strings.Split(out, "\n") {
f := strings.Fields(line)
if len(f) == 3 && f[0] == "-P" && f[1] == "FORWARD" {
return f[2], true
}
}
return "", false
}
func expectActive(ctx context.Context, run Runner, want bool) error {