From 625a63e7c2b25e3e12545a4981e43b78f5ec004c Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Sat, 21 Feb 2026 19:39:22 +0000 Subject: [PATCH] fix(firewall): flush conntrack table after enabling firewall at container start - prevent leaks for connections made the first ~10 milliseconds when Gluetun starts - seems critical, but in practice this very rarely happen and it very hard to reproduce --- cmd/gluetun/main.go | 5 +++++ go.mod | 2 ++ go.sum | 4 ++++ internal/netlink/conntrack_linux.go | 17 +++++++++++++++++ internal/netlink/conntrack_unspecified.go | 7 +++++++ 5 files changed, 35 insertions(+) create mode 100644 internal/netlink/conntrack_linux.go create mode 100644 internal/netlink/conntrack_unspecified.go diff --git a/cmd/gluetun/main.go b/cmd/gluetun/main.go index 1b3f8cc6..7dc27687 100644 --- a/cmd/gluetun/main.go +++ b/cmd/gluetun/main.go @@ -237,6 +237,10 @@ func _main(ctx context.Context, buildInfo models.BuildInformation, if err != nil { return err } + err = netLinker.FlushConntrack() + if err != nil { + return fmt.Errorf("flushing conntrack: %w", err) + } } // TODO run this in a loop or in openvpn to reload from file without restarting @@ -556,6 +560,7 @@ type netLinker interface { Linker IsWireguardSupported() (ok bool, err error) IsIPv6Supported() (ok bool, err error) + FlushConntrack() error PatchLoggerLevel(level log.Level) } diff --git a/go.mod b/go.mod index 615f774c..4475703e 100644 --- a/go.mod +++ b/go.mod @@ -55,6 +55,8 @@ require ( github.com/prometheus/procfs v0.15.1 // indirect github.com/qdm12/goservices v0.1.1-0.20251104135713-6bee97bd4978 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect + github.com/ti-mo/conntrack v0.6.0 // indirect + github.com/ti-mo/netfilter v0.5.3 // indirect golang.org/x/crypto v0.47.0 // indirect golang.org/x/mod v0.31.0 // indirect golang.org/x/sync v0.19.0 // indirect diff --git a/go.sum b/go.sum index 6e5f8372..041ff809 100644 --- a/go.sum +++ b/go.sum @@ -95,6 +95,10 @@ github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/ti-mo/conntrack v0.6.0 h1:laiW2+dzKyS2u0aVr6FeRQs+v7cj4t7q+twolL/ZkjQ= +github.com/ti-mo/conntrack v0.6.0/go.mod h1:4HZrFQQLOSuBzgQNid3H/wYyyp1kfGXUYxueXjIGibo= +github.com/ti-mo/netfilter v0.5.3 h1:ikzduvnaUMwre5bhbNwWOd6bjqLMVb33vv0XXbK0xGQ= +github.com/ti-mo/netfilter v0.5.3/go.mod h1:08SyBCg6hu1qyQk4s3DjjJKNrm3RTb32nm6AzyT972E= github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= diff --git a/internal/netlink/conntrack_linux.go b/internal/netlink/conntrack_linux.go new file mode 100644 index 00000000..53b97670 --- /dev/null +++ b/internal/netlink/conntrack_linux.go @@ -0,0 +1,17 @@ +package netlink + +import ( + "fmt" + + "github.com/ti-mo/conntrack" +) + +func (n *NetLink) FlushConntrack() error { + conn, err := conntrack.Dial(nil) + if err != nil { + return fmt.Errorf("dialing conntrack: %w", err) + } + defer conn.Close() + + return conn.Flush() +} diff --git a/internal/netlink/conntrack_unspecified.go b/internal/netlink/conntrack_unspecified.go new file mode 100644 index 00000000..d2652b26 --- /dev/null +++ b/internal/netlink/conntrack_unspecified.go @@ -0,0 +1,7 @@ +//go:build !linux + +package netlink + +func (n *NetLink) FlushConntrack() error { + panic("not implemented") +}