FIREWALL_IMPLEMENTATION option

This commit is contained in:
Quentin McGaw
2026-08-06 15:56:19 +00:00
parent 113253b523
commit 27b089d757
6 changed files with 37 additions and 9 deletions
+1
View File
@@ -165,6 +165,7 @@ ENV VPN_SERVICE_PROVIDER=pia \
FIREWALL_VPN_INPUT_PORTS= \ FIREWALL_VPN_INPUT_PORTS= \
FIREWALL_INPUT_PORTS= \ FIREWALL_INPUT_PORTS= \
FIREWALL_OUTBOUND_SUBNETS= \ FIREWALL_OUTBOUND_SUBNETS= \
FIREWALL_IMPLEMENTATION=iptables \
FIREWALL_DEBUG=off \ FIREWALL_DEBUG=off \
# Logging # Logging
LOG_LEVEL=info \ LOG_LEVEL=info \
+2 -2
View File
@@ -226,8 +226,8 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
if *allSettings.Firewall.Debug { // To remove in v4 if *allSettings.Firewall.Debug { // To remove in v4
firewallLogger.Patch(log.SetLevel(log.LevelDebug)) firewallLogger.Patch(log.SetLevel(log.LevelDebug))
} }
firewallConf, err := firewall.NewConfig(ctx, firewallLogger, cmder, firewallConf, err := firewall.NewConfig(ctx, allSettings.Firewall.Implementation,
defaultRoutes, localNetworks) firewallLogger, cmder, defaultRoutes, localNetworks)
if err != nil { if err != nil {
return err return err
} }
@@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"net/netip" "net/netip"
"github.com/qdm12/gluetun/internal/configuration/settings/helpers"
"github.com/qdm12/gosettings" "github.com/qdm12/gosettings"
"github.com/qdm12/gosettings/reader" "github.com/qdm12/gosettings/reader"
"github.com/qdm12/gotree" "github.com/qdm12/gotree"
@@ -16,6 +17,7 @@ type Firewall struct {
OutboundSubnets []netip.Prefix OutboundSubnets []netip.Prefix
Enabled *bool Enabled *bool
Debug *bool Debug *bool
Implementation string
} }
func (f Firewall) validate() (err error) { func (f Firewall) validate() (err error) {
@@ -33,6 +35,10 @@ func (f Firewall) validate() (err error) {
} }
} }
if !helpers.IsOneOf(f.Implementation, "iptables", "nftables") {
return fmt.Errorf("firewall implementation %q must be either 'iptables' or 'nftables'", f.Implementation)
}
return nil return nil
} }
@@ -52,6 +58,7 @@ func (f *Firewall) copy() (copied Firewall) {
OutboundSubnets: gosettings.CopySlice(f.OutboundSubnets), OutboundSubnets: gosettings.CopySlice(f.OutboundSubnets),
Enabled: gosettings.CopyPointer(f.Enabled), Enabled: gosettings.CopyPointer(f.Enabled),
Debug: gosettings.CopyPointer(f.Debug), Debug: gosettings.CopyPointer(f.Debug),
Implementation: f.Implementation,
} }
} }
@@ -64,11 +71,13 @@ func (f *Firewall) overrideWith(other Firewall) {
f.OutboundSubnets = gosettings.OverrideWithSlice(f.OutboundSubnets, other.OutboundSubnets) f.OutboundSubnets = gosettings.OverrideWithSlice(f.OutboundSubnets, other.OutboundSubnets)
f.Enabled = gosettings.OverrideWithPointer(f.Enabled, other.Enabled) f.Enabled = gosettings.OverrideWithPointer(f.Enabled, other.Enabled)
f.Debug = gosettings.OverrideWithPointer(f.Debug, other.Debug) f.Debug = gosettings.OverrideWithPointer(f.Debug, other.Debug)
f.Implementation = gosettings.OverrideWithComparable(f.Implementation, other.Implementation)
} }
func (f *Firewall) setDefaults() { func (f *Firewall) setDefaults() {
f.Enabled = gosettings.DefaultPointer(f.Enabled, true) f.Enabled = gosettings.DefaultPointer(f.Enabled, true)
f.Debug = gosettings.DefaultPointer(f.Debug, false) f.Debug = gosettings.DefaultPointer(f.Debug, false)
f.Implementation = gosettings.DefaultComparable(f.Implementation, "iptables")
} }
func (f Firewall) String() string { func (f Firewall) String() string {
@@ -83,6 +92,8 @@ func (f Firewall) toLinesNode() (node *gotree.Node) {
return node return node
} }
node.Appendf("Implementation: %s", f.Implementation)
if *f.Debug { if *f.Debug {
node.Appendf("Debug mode: on") node.Appendf("Debug mode: on")
} }
@@ -138,5 +149,7 @@ func (f *Firewall) read(r *reader.Reader) (err error) {
return err return err
} }
f.Implementation = r.String("FIREWALL_IMPLEMENTATION")
return nil return nil
} }
@@ -65,7 +65,8 @@ func Test_Settings_String(t *testing.T) {
| Block ads: no | Block ads: no
| Block surveillance: yes | Block surveillance: yes
Firewall settings: Firewall settings:
| Enabled: yes | Enabled: yes
| Implementation: iptables
Log settings: Log settings:
| Log level: INFO | Log level: INFO
Health settings: Health settings:
+16 -4
View File
@@ -7,6 +7,7 @@ import (
"sync" "sync"
"github.com/qdm12/gluetun/internal/firewall/iptables" "github.com/qdm12/gluetun/internal/firewall/iptables"
"github.com/qdm12/gluetun/internal/firewall/nftables"
"github.com/qdm12/gluetun/internal/models" "github.com/qdm12/gluetun/internal/models"
"github.com/qdm12/gluetun/internal/routing" "github.com/qdm12/gluetun/internal/routing"
) )
@@ -33,15 +34,26 @@ type Config struct {
} }
// NewConfig creates a new Config instance and returns an error // NewConfig creates a new Config instance and returns an error
// if no iptables implementation is available. // if no firewall implementation is available.
func NewConfig(ctx context.Context, logger Logger, func NewConfig(ctx context.Context, implementation string, logger Logger,
runner CmdRunner, defaultRoutes []routing.DefaultRoute, runner CmdRunner, defaultRoutes []routing.DefaultRoute,
localNetworks []routing.LocalNetwork, localNetworks []routing.LocalNetwork,
) (config *Config, err error) { ) (config *Config, err error) {
impl, err := iptables.New(ctx, runner, logger) var impl firewallImpl
var customRulesPath string
switch implementation {
case "iptables":
impl, err = iptables.New(ctx, runner, logger)
if err != nil { if err != nil {
return nil, fmt.Errorf("creating iptables firewall: %w", err) return nil, fmt.Errorf("creating iptables firewall: %w", err)
} }
customRulesPath = "/iptables/post-rules.txt"
case "nftables":
impl = nftables.New(logger)
customRulesPath = "/gluetun/firewall/nftables/post-rules.txt"
default:
return nil, fmt.Errorf("unknown firewall implementation: %s", implementation)
}
return &Config{ return &Config{
runner: runner, runner: runner,
@@ -51,6 +63,6 @@ func NewConfig(ctx context.Context, logger Logger,
defaultRoutes: defaultRoutes, defaultRoutes: defaultRoutes,
localNetworks: localNetworks, localNetworks: localNetworks,
impl: impl, impl: impl,
customRulesPath: "/iptables/post-rules.txt", customRulesPath: customRulesPath,
}, nil }, nil
} }
+1
View File
@@ -16,6 +16,7 @@ type Logger interface {
Debug(s string) Debug(s string)
Info(s string) Info(s string)
Warn(s string) Warn(s string)
Warnf(format string, args ...any)
Error(s string) Error(s string)
} }