Skip to content

Commit 10f3491

Browse files
authored
Merge pull request moby#50182 from robmry/nftables_endpoint_rules
nftables: per-endpoint rules
2 parents 222610a + e203426 commit 10f3491

File tree

90 files changed

+143
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+143
-1
lines changed

libnetwork/drivers/bridge/internal/nftabler/endpoint.go

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,63 @@ package nftabler
44

55
import (
66
"context"
7+
"fmt"
78
"net/netip"
9+
"strings"
10+
11+
"github.com/docker/docker/libnetwork/drivers/bridge/internal/firewaller"
12+
"github.com/docker/docker/libnetwork/internal/nftables"
813
)
914

1015
func (n *network) AddEndpoint(ctx context.Context, epIPv4, epIPv6 netip.Addr) error {
11-
return nil
16+
return n.modEndpoint(ctx, epIPv4, epIPv6, true)
1217
}
1318

1419
func (n *network) DelEndpoint(ctx context.Context, epIPv4, epIPv6 netip.Addr) error {
20+
return n.modEndpoint(ctx, epIPv4, epIPv6, false)
21+
}
22+
23+
func (n *network) modEndpoint(ctx context.Context, epIPv4, epIPv6 netip.Addr, enable bool) error {
24+
if n.fw.config.IPv4 && epIPv4.IsValid() {
25+
if err := n.filterDirectAccess(ctx, n.fw.table4, n.config.Config4, epIPv4, enable); err != nil {
26+
return err
27+
}
28+
if err := nftApply(ctx, n.fw.table4); err != nil {
29+
return fmt.Errorf("adding rules for bridge %s: %w", n.config.IfName, err)
30+
}
31+
}
32+
if n.fw.config.IPv6 && epIPv6.IsValid() {
33+
if err := n.filterDirectAccess(ctx, n.fw.table6, n.config.Config6, epIPv6, enable); err != nil {
34+
return err
35+
}
36+
if err := nftApply(ctx, n.fw.table6); err != nil {
37+
return fmt.Errorf("adding rules for bridge %s: %w", n.config.IfName, err)
38+
}
39+
}
1540
return nil
1641
}
42+
43+
// filterDirectAccess drops packets addressed directly to the container's IP address,
44+
// when direct routing is not permitted by network configuration.
45+
//
46+
// It is a no-op if:
47+
// - gateway mode is "nat-unprotected" or "routed".
48+
// - direct routing is enabled at the daemon level.
49+
// - "raw" rules are disabled (possibly because the host doesn't have the necessary
50+
// kernel support).
51+
//
52+
// Packets originating on the bridge's own interface and addressed directly to the
53+
// container are allowed - the host always has direct access to its own containers
54+
// (it doesn't need to use the port mapped to its own addresses, although it can).
55+
//
56+
// "Trusted interfaces" are treated in the same way as the bridge itself.
57+
func (n *network) filterDirectAccess(ctx context.Context, table nftables.TableRef, conf firewaller.NetworkConfigFam, epIP netip.Addr, enable bool) error {
58+
if n.config.Internal || conf.Unprotected || conf.Routed || n.fw.config.AllowDirectRouting {
59+
return nil
60+
}
61+
updater := table.ChainUpdateFunc(ctx, rawPreroutingChain, enable)
62+
ifNames := strings.Join(n.config.TrustedHostInterfaces, ", ")
63+
return updater(ctx, rawPreroutingPortsRuleGroup,
64+
`%s daddr %s iifname != { %s, %s } counter drop comment "DROP DIRECT ACCESS"`,
65+
table.Family(), epIP, n.config.IfName, ifNames)
66+
}

libnetwork/drivers/bridge/internal/nftabler/nftabler.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ const (
3838
fwdInFinalRuleGroup
3939
)
4040

41+
const (
42+
rawPreroutingPortsRuleGroup = iota + initialRuleGroup + 1
43+
)
44+
4145
type nftabler struct {
4246
config firewaller.Config
4347
table4 nftables.TableRef

libnetwork/drivers/bridge/internal/nftabler/testdata/TestNftabler_hairpin=false,internal=false,icc=false,masq=false,snat=false,gwm=nat,bindlh=false,wsl2mirrored=true__ip.golden

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libnetwork/drivers/bridge/internal/nftabler/testdata/TestNftabler_hairpin=false,internal=false,icc=false,masq=false,snat=false,gwm=nat,bindlh=false__ip.golden

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libnetwork/drivers/bridge/internal/nftabler/testdata/TestNftabler_hairpin=false,internal=false,icc=false,masq=false,snat=false,gwm=nat,bindlh=false__ip6.golden

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libnetwork/drivers/bridge/internal/nftabler/testdata/TestNftabler_hairpin=false,internal=false,icc=false,masq=false,snat=false,gwm=nat,bindlh=true,wsl2mirrored=true__ip.golden

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libnetwork/drivers/bridge/internal/nftabler/testdata/TestNftabler_hairpin=false,internal=false,icc=false,masq=false,snat=false,gwm=nat,bindlh=true__ip.golden

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libnetwork/drivers/bridge/internal/nftabler/testdata/TestNftabler_hairpin=false,internal=false,icc=false,masq=false,snat=false,gwm=nat,bindlh=true__ip6.golden

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libnetwork/drivers/bridge/internal/nftabler/testdata/TestNftabler_hairpin=false,internal=false,icc=false,masq=false,snat=true,gwm=nat,bindlh=false,wsl2mirrored=true__ip.golden

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

libnetwork/drivers/bridge/internal/nftabler/testdata/TestNftabler_hairpin=false,internal=false,icc=false,masq=false,snat=true,gwm=nat,bindlh=false__ip.golden

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)