Skip to content

Commit 8c79486

Browse files
authored
Merge pull request moby#50357 from robmry/firewall_backend_option
Add daemon option --firewall-backend
2 parents c616e76 + 39ab393 commit 8c79486

File tree

16 files changed

+74
-23
lines changed

16 files changed

+74
-23
lines changed

daemon/command/config_unix.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ func installConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
5151
flags.BoolVar(&conf.NoNewPrivileges, "no-new-privileges", false, "Set no-new-privileges by default for new containers")
5252
flags.StringVar(&conf.IpcMode, "default-ipc-mode", conf.IpcMode, `Default mode for containers ipc ("shareable" | "private")`)
5353
flags.Var(&conf.NetworkConfig.DefaultAddressPools, "default-address-pool", "Default address pools for node specific local networks")
54+
flags.StringVar(&conf.NetworkConfig.FirewallBackend, "firewall-backend", "", "Firewall backend to use, iptables or nftables")
5455
// rootless needs to be explicitly specified for running "rootful" dockerd in rootless dockerd (#38702)
5556
// Note that conf.BridgeConfig.UserlandProxyPath and honorXDG are configured according to the value of rootless.RunningWithRootlessKit, not the value of --rootless.
5657
flags.BoolVar(&conf.Rootless, "rootless", conf.Rootless, "Enable rootless mode; typically used with RootlessKit")

daemon/config/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ type NetworkConfig struct {
148148
NetworkControlPlaneMTU int `json:"network-control-plane-mtu,omitempty"`
149149
// Default options for newly created networks
150150
DefaultNetworkOpts map[string]map[string]string `json:"default-network-opts,omitempty"`
151+
// FirewallBackend overrides the daemon's default selection of firewall
152+
// implementation. Currently only used on Linux, it is an error to
153+
// supply a value for other platforms.
154+
FirewallBackend string `json:"firewall-backend,omitempty"`
151155
}
152156

153157
// TLSOptions defines TLS configuration for the daemon server.

daemon/config/config_linux.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ func validatePlatformConfig(conf *Config) error {
243243
return errors.Wrap(err, "invalid fixed-cidr-v6")
244244
}
245245

246+
if err := validateFirewallBackend(conf.FirewallBackend); err != nil {
247+
return errors.Wrap(err, "invalid firewall-backend")
248+
}
249+
246250
return verifyDefaultCgroupNsMode(conf.CgroupNamespaceMode)
247251
}
248252

@@ -294,6 +298,14 @@ func verifyDefaultIpcMode(mode string) error {
294298
return nil
295299
}
296300

301+
func validateFirewallBackend(val string) error {
302+
switch val {
303+
case "", "iptables", "nftables":
304+
return nil
305+
}
306+
return errors.New(`allowed values are "iptables" and "nftables"`)
307+
}
308+
297309
func verifyDefaultCgroupNsMode(mode string) error {
298310
cm := container.CgroupnsMode(mode)
299311
if !cm.Valid() {

daemon/config/config_windows.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package config
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"os"
78
"path/filepath"
@@ -88,6 +89,9 @@ func validatePlatformConfig(conf *Config) error {
8889
if conf.MTU != 0 && conf.MTU != DefaultNetworkMtu {
8990
log.G(context.TODO()).Warn(`WARNING: MTU for the default network is not configurable on Windows, and this option will be ignored.`)
9091
}
92+
if conf.FirewallBackend != "" {
93+
return errors.New("firewall-backend can only be configured on Linux")
94+
}
9195
return nil
9296
}
9397

daemon/daemon.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,6 +1457,7 @@ func (daemon *Daemon) networkOptions(conf *config.Config, pg plugingetter.Plugin
14571457
nwconfig.OptionDefaultNetwork(network.DefaultNetwork),
14581458
nwconfig.OptionLabels(conf.Labels),
14591459
nwconfig.OptionNetworkControlPlaneMTU(conf.NetworkControlPlaneMTU),
1460+
nwconfig.OptionFirewallBackend(conf.FirewallBackend),
14601461
driverOptions(conf),
14611462
}
14621463

daemon/libnetwork/config/config.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ type Config struct {
4242
DatastoreBucket string
4343
ActiveSandboxes map[string]any
4444
PluginGetter plugingetter.PluginGetter
45+
FirewallBackend string
4546
}
4647

4748
// New creates a new Config and initializes it with the given Options.
@@ -154,3 +155,10 @@ func OptionActiveSandboxes(sandboxes map[string]any) Option {
154155
c.ActiveSandboxes = sandboxes
155156
}
156157
}
158+
159+
// OptionFirewallBackend returns an option setter for selection of the firewall backend.
160+
func OptionFirewallBackend(val string) Option {
161+
return func(c *Config) {
162+
c.FirewallBackend = val
163+
}
164+
}

daemon/libnetwork/controller.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,9 @@ func New(ctx context.Context, cfgOptions ...config.Option) (_ *Controller, retEr
168168
diagnosticServer: diagnostic.New(),
169169
}
170170

171-
c.selectFirewallBackend()
171+
if err := c.selectFirewallBackend(); err != nil {
172+
return nil, err
173+
}
172174
c.drvRegistry.Notify = c
173175

174176
// External plugins don't need config passed through daemon. They can

daemon/libnetwork/firewall_linux.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"errors"
66
"fmt"
7-
"os"
87

98
"github.com/containerd/log"
109
"github.com/docker/docker/daemon/libnetwork/internal/nftables"
@@ -13,16 +12,23 @@ import (
1312

1413
const userChain = "DOCKER-USER"
1514

16-
func (c *Controller) selectFirewallBackend() {
17-
// Don't try to enable nftables if firewalld is running.
18-
if iptables.UsingFirewalld() {
19-
return
15+
func (c *Controller) selectFirewallBackend() error {
16+
// If explicitly configured to use iptables, don't consider nftables.
17+
if c.cfg.FirewallBackend == "iptables" {
18+
return nil
2019
}
21-
// Only try to use nftables if explicitly enabled by env-var.
22-
// TODO(robmry) - command line options?
23-
if os.Getenv("DOCKER_FIREWALL_BACKEND") == "nftables" {
24-
_ = nftables.Enable()
20+
// If configured to use nftables, but it can't be initialised, return an error.
21+
if c.cfg.FirewallBackend == "nftables" {
22+
// Don't try to enable nftables if firewalld is running.
23+
if iptables.UsingFirewalld() {
24+
return errors.New("firewall-backend is set to nftables, but firewalld is running")
25+
}
26+
if err := nftables.Enable(); err != nil {
27+
return fmt.Errorf("firewall-backend is set to nftables: %v", err)
28+
}
29+
return nil
2530
}
31+
return nil
2632
}
2733

2834
// Sets up the DOCKER-USER chain for each iptables version (IPv4, IPv6) that's

daemon/libnetwork/firewall_others.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
package libnetwork
44

5-
func (c *Controller) selectFirewallBackend() {}
5+
func (c *Controller) selectFirewallBackend() error {
6+
return nil
7+
}
68

79
func (c *Controller) setupUserChains() {}

daemon/libnetwork/internal/nftables/nftables_linux.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ var (
6262
// nftPath is the path of the "nft" tool, set by [Enable] and left empty if the tool
6363
// is not present - in which case, nftables is disabled.
6464
nftPath string
65+
// Error returned by Enable if nftables could not be initialised.
66+
nftEnableError error
6567
// incrementalUpdateTempl is a parsed text/template, used to apply incremental updates.
6668
incrementalUpdateTempl *template.Template
6769
// reloadTempl is a parsed text/template, used to apply a whole table.
@@ -134,21 +136,23 @@ const (
134136
nftTypeIfname nftType = "ifname"
135137
)
136138

137-
// Enable checks whether the "nft" tool is available, and returns true if it is.
138-
// Subsequent calls to [Enabled] will return the same result.
139-
func Enable() bool {
139+
// Enable tries once to initialise nftables.
140+
func Enable() error {
140141
enableOnce.Do(func() {
141142
path, err := exec.LookPath("nft")
142143
if err != nil {
143144
log.G(context.Background()).WithError(err).Warnf("Failed to find nft tool")
145+
nftEnableError = fmt.Errorf("failed to find nft tool: %w", err)
146+
return
144147
}
145148
if err := parseTemplate(); err != nil {
146149
log.G(context.Background()).WithError(err).Error("Internal error while initialising nftables")
150+
nftEnableError = fmt.Errorf("internal error while initialising nftables: %w", err)
147151
return
148152
}
149153
nftPath = path
150154
})
151-
return nftPath != ""
155+
return nftEnableError
152156
}
153157

154158
// Enabled returns true if the "nft" tool is available and [Enable] has been called.

0 commit comments

Comments
 (0)