Skip to content

Commit 0facb0c

Browse files
authored
Merge pull request moby#49969 from robmry/firewaller_wsl2_param
Make WSL2Mirrored into a Firewaller param
2 parents 61a1a29 + eeba428 commit 0facb0c

File tree

87 files changed

+3275
-235
lines changed

Some content is hidden

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

87 files changed

+3275
-235
lines changed

libnetwork/drivers/bridge/bridge_linux.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,7 @@ func (d *driver) configure(option map[string]interface{}) error {
514514
IPv6: config.EnableIP6Tables,
515515
Hairpin: !config.EnableUserlandProxy || config.UserlandProxyPath == "",
516516
AllowDirectRouting: config.AllowDirectRouting,
517+
WSL2Mirrored: isRunningUnderWSL2MirroredMode(context.Background()),
517518
})
518519
if err != nil {
519520
return err

libnetwork/drivers/bridge/internal/firewaller/firewaller.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ type Config struct {
2929
// AllowDirectRouting means packets addressed directly to a container's IP address will be
3030
// accepted, regardless of which network interface they are from.
3131
AllowDirectRouting bool
32+
// WSL2Mirrored is true if running under WSL2 with mirrored networking enabled.
33+
WSL2Mirrored bool
3234
}
3335

3436
// NetworkConfig contains settings for a single bridge network.

libnetwork/drivers/bridge/internal/iptabler/iptabler.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,14 @@ func NewIptabler(ctx context.Context, config firewaller.Config) (firewaller.Fire
4545
if ipt.config.IPv4 {
4646
removeIPChains(ctx, iptables.IPv4)
4747

48-
if err := setupIPChains(ctx, iptables.IPv4, ipt.config.Hairpin); err != nil {
48+
if err := setupIPChains(ctx, iptables.IPv4, ipt.config); err != nil {
4949
return nil, err
5050
}
5151

5252
// Make sure on firewall reload, first thing being re-played is chains creation
5353
iptables.OnReloaded(func() {
5454
log.G(ctx).Debugf("Recreating iptables chains on firewall reload")
55-
if err := setupIPChains(ctx, iptables.IPv4, ipt.config.Hairpin); err != nil {
55+
if err := setupIPChains(ctx, iptables.IPv4, ipt.config); err != nil {
5656
log.G(ctx).WithError(err).Error("Error reloading iptables chains")
5757
}
5858
})
@@ -69,7 +69,7 @@ func NewIptabler(ctx context.Context, config firewaller.Config) (firewaller.Fire
6969

7070
removeIPChains(ctx, iptables.IPv6)
7171

72-
err := setupIPChains(ctx, iptables.IPv6, ipt.config.Hairpin)
72+
err := setupIPChains(ctx, iptables.IPv6, ipt.config)
7373
if err != nil {
7474
// If the chains couldn't be set up, it's probably because the kernel has no IPv6
7575
// support, or it doesn't have module ip6_tables loaded. It won't be possible to
@@ -81,7 +81,7 @@ func NewIptabler(ctx context.Context, config firewaller.Config) (firewaller.Fire
8181
// Make sure on firewall reload, first thing being re-played is chains creation
8282
iptables.OnReloaded(func() {
8383
log.G(ctx).Debugf("Recreating ip6tables chains on firewall reload")
84-
if err := setupIPChains(ctx, iptables.IPv6, ipt.config.Hairpin); err != nil {
84+
if err := setupIPChains(ctx, iptables.IPv6, ipt.config); err != nil {
8585
log.G(ctx).WithError(err).Error("Error reloading ip6tables chains")
8686
}
8787
})
@@ -117,7 +117,7 @@ func (ipt *iptabler) FilterForwardDrop(ctx context.Context, ipv firewaller.IPVer
117117
return nil
118118
}
119119

120-
func setupIPChains(ctx context.Context, version iptables.IPVersion, hairpin bool) (retErr error) {
120+
func setupIPChains(ctx context.Context, version iptables.IPVersion, iptCfg firewaller.Config) (retErr error) {
121121
iptable := iptables.GetIptable(version)
122122

123123
_, err := iptable.NewChain(dockerChain, iptables.Nat)
@@ -204,12 +204,12 @@ func setupIPChains(ctx context.Context, version iptables.IPVersion, hairpin bool
204204
}
205205
}()
206206

207-
if err := addNATJumpRules(version, hairpin, true); err != nil {
207+
if err := addNATJumpRules(version, iptCfg.Hairpin, true); err != nil {
208208
return fmt.Errorf("failed to add jump rules to %s NAT table: %w", version, err)
209209
}
210210
defer func() {
211211
if retErr != nil {
212-
if err := addNATJumpRules(version, hairpin, false); err != nil {
212+
if err := addNATJumpRules(version, iptCfg.Hairpin, false); err != nil {
213213
log.G(ctx).Warnf("failed on removing jump rules from %s NAT table: %v", version, err)
214214
}
215215
}
@@ -231,7 +231,7 @@ func setupIPChains(ctx context.Context, version iptables.IPVersion, hairpin bool
231231
return err
232232
}
233233

234-
if err := mirroredWSL2Workaround(ctx, version, hairpin); err != nil {
234+
if err := mirroredWSL2Workaround(version, !iptCfg.Hairpin && iptCfg.WSL2Mirrored); err != nil {
235235
return err
236236
}
237237

libnetwork/drivers/bridge/internal/iptabler/iptabler_test.go

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func TestCleanupIptableRules(t *testing.T) {
5050
ipVersions := []iptables.IPVersion{iptables.IPv4, iptables.IPv6}
5151

5252
for _, version := range ipVersions {
53-
err := setupIPChains(context.Background(), version, true)
53+
err := setupIPChains(context.Background(), version, firewaller.Config{Hairpin: true})
5454
assert.NilError(t, err, "version:%s", version)
5555

5656
iptable := iptables.GetIptable(version)
@@ -95,15 +95,17 @@ func TestIptabler(t *testing.T) {
9595
masq
9696
snat
9797
bindLocalhost
98+
wsl2Mirrored
9899
numBoolParams
99100
)
100101
for i := range 1 << numBoolParams {
101102
p := func(n int64) bool { return (i & (1 << n)) != 0 }
102103
for _, gwmode := range []string{"nat", "nat-unprotected", "routed"} {
103104
config := firewaller.Config{
104-
IPv4: p(ipv4),
105-
IPv6: p(ipv6),
106-
Hairpin: p(hairpin),
105+
IPv4: p(ipv4),
106+
IPv6: p(ipv6),
107+
Hairpin: p(hairpin),
108+
WSL2Mirrored: p(wsl2Mirrored),
107109
}
108110
netConfig := firewaller.NetworkConfig{
109111
IfName: "br-dummy",
@@ -128,8 +130,8 @@ func TestIptabler(t *testing.T) {
128130
netConfig.Config6.HostIP = netip.MustParseAddr("fd34:d0d4:672f::123")
129131
}
130132
tn := t.Name()
131-
t.Run(fmt.Sprintf("ipv4=%v/ipv6=%v/hairpin=%v/internal=%v/icc=%v/masq=%v/snat=%v/gwm=%v/bindlh=%v",
132-
p(ipv4), p(ipv6), p(hairpin), p(internal), p(icc), p(masq), p(snat), gwmode, p(bindLocalhost)), func(t *testing.T) {
133+
t.Run(fmt.Sprintf("ipv4=%v/ipv6=%v/hairpin=%v/internal=%v/icc=%v/masq=%v/snat=%v/gwm=%v/bindlh=%v/wsl2mirrored=%v",
134+
p(ipv4), p(ipv6), p(hairpin), p(internal), p(icc), p(masq), p(snat), gwmode, p(bindLocalhost), p(wsl2Mirrored)), func(t *testing.T) {
133135
// Run in parallel, unless updating results (because tests share golden results files, so
134136
// they trample each other's output).
135137
if !golden.FlagUpdate() {
@@ -190,11 +192,20 @@ func testIptabler(t *testing.T, tn string, config firewaller.Config, netConfig f
190192
}
191193
}
192194

195+
// WSL2Mirrored should only affect IPv4 results, and only if there's a port binding
196+
// to a loopback address or docker-proxy is disabled. Share other results files.
197+
rnWSL2Mirrored := func(resName string) string {
198+
if config.IPv4 && config.WSL2Mirrored && (bindLocalhost || !config.Hairpin) {
199+
return resName + ",wsl2mirrored=true"
200+
}
201+
return resName
202+
}
203+
193204
// Initialise iptables, check the iptables config looks like it should look at the
194205
// end of the test (after deleting per-network and per-port rules).
195206
fw, err := NewIptabler(context.Background(), config)
196207
assert.NilError(t, err)
197-
checkResults("iptables", fmt.Sprintf("%s_cleaned,hairpin=%v", tn, config.Hairpin), config.IPv4)
208+
checkResults("iptables", rnWSL2Mirrored(fmt.Sprintf("%s_cleaned,hairpin=%v", tn, config.Hairpin)), config.IPv4)
198209
checkResults("ip6tables", fmt.Sprintf("%s_cleaned,hairpin=%v", tn, config.Hairpin), config.IPv6)
199210

200211
// Add the network.
@@ -220,7 +231,7 @@ func testIptabler(t *testing.T, tn string, config firewaller.Config, netConfig f
220231
assert.NilError(t, err)
221232

222233
// Check the resulting iptables config.
223-
checkResults("iptables", resName, config.IPv4)
234+
checkResults("iptables", rnWSL2Mirrored(resName), config.IPv4)
224235
checkResults("ip6tables", resName, config.IPv6)
225236

226237
// Remove the port mappings and the network, and check the result.
@@ -230,6 +241,6 @@ func testIptabler(t *testing.T, tn string, config firewaller.Config, netConfig f
230241
assert.NilError(t, err)
231242
err = nw.DelNetworkLevelRules(context.Background())
232243
assert.NilError(t, err)
233-
checkResults("iptables", fmt.Sprintf("%s_cleaned,hairpin=%v", tn, config.Hairpin), config.IPv4)
244+
checkResults("iptables", rnWSL2Mirrored(fmt.Sprintf("%s_cleaned,hairpin=%v", tn, config.Hairpin)), config.IPv4)
234245
checkResults("ip6tables", fmt.Sprintf("%s_cleaned,hairpin=%v", tn, config.Hairpin), config.IPv6)
235246
}

libnetwork/drivers/bridge/internal/iptabler/port.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func (n *network) setPerPortIptables(ctx context.Context, b types.PortBinding, e
4747
return nil
4848
}
4949

50-
if err := filterPortMappedOnLoopback(ctx, b, b.HostIP, enable); err != nil {
50+
if err := filterPortMappedOnLoopback(ctx, b, b.HostIP, n.ipt.config.WSL2Mirrored, enable); err != nil {
5151
return err
5252
}
5353

@@ -169,7 +169,7 @@ func setPerPortForwarding(b types.PortBinding, ipv iptables.IPVersion, bridgeNam
169169
// This is a no-op if the portBinding is for IPv6 (IPv6 loopback address is
170170
// non-routable), or over a network with gw_mode=routed (PBs in routed mode
171171
// don't map ports on the host).
172-
func filterPortMappedOnLoopback(ctx context.Context, b types.PortBinding, hostIP net.IP, enable bool) error {
172+
func filterPortMappedOnLoopback(ctx context.Context, b types.PortBinding, hostIP net.IP, wsl2Mirrored, enable bool) error {
173173
if rawRulesDisabled(ctx) {
174174
return nil
175175
}
@@ -184,7 +184,7 @@ func filterPortMappedOnLoopback(ctx context.Context, b types.PortBinding, hostIP
184184
"-i", "loopback0",
185185
"-j", "ACCEPT",
186186
}}
187-
enableMirrored := enable && isRunningUnderWSL2MirroredMode(ctx)
187+
enableMirrored := enable && wsl2Mirrored
188188
if err := appendOrDelChainRule(acceptMirrored, "LOOPBACK FILTERING - ACCEPT MIRRORED", enableMirrored); err != nil {
189189
return err
190190
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
*raw
2+
:PREROUTING ACCEPT [0:0]
3+
:OUTPUT ACCEPT [0:0]
4+
COMMIT
5+
*filter
6+
:INPUT ACCEPT [0:0]
7+
:FORWARD ACCEPT [0:0]
8+
:OUTPUT ACCEPT [0:0]
9+
:DOCKER - [0:0]
10+
:DOCKER-BRIDGE - [0:0]
11+
:DOCKER-CT - [0:0]
12+
:DOCKER-FORWARD - [0:0]
13+
:DOCKER-ISOLATION-STAGE-1 - [0:0]
14+
:DOCKER-ISOLATION-STAGE-2 - [0:0]
15+
-A FORWARD -j DOCKER-FORWARD
16+
-A DOCKER-FORWARD -j DOCKER-CT
17+
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
18+
-A DOCKER-FORWARD -j DOCKER-BRIDGE
19+
COMMIT
20+
*nat
21+
:PREROUTING ACCEPT [0:0]
22+
:INPUT ACCEPT [0:0]
23+
:OUTPUT ACCEPT [0:0]
24+
:POSTROUTING ACCEPT [0:0]
25+
:DOCKER - [0:0]
26+
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
27+
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
28+
-A DOCKER -d 127.0.0.0/8 -i loopback0 -j RETURN
29+
COMMIT
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
*raw
2+
:PREROUTING ACCEPT [0:0]
3+
:OUTPUT ACCEPT [0:0]
4+
COMMIT
5+
*filter
6+
:INPUT ACCEPT [0:0]
7+
:FORWARD ACCEPT [0:0]
8+
:OUTPUT ACCEPT [0:0]
9+
:DOCKER - [0:0]
10+
:DOCKER-BRIDGE - [0:0]
11+
:DOCKER-CT - [0:0]
12+
:DOCKER-FORWARD - [0:0]
13+
:DOCKER-ISOLATION-STAGE-1 - [0:0]
14+
:DOCKER-ISOLATION-STAGE-2 - [0:0]
15+
-A FORWARD -j DOCKER-FORWARD
16+
-A DOCKER-FORWARD -j DOCKER-CT
17+
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
18+
-A DOCKER-FORWARD -j DOCKER-BRIDGE
19+
COMMIT
20+
*nat
21+
:PREROUTING ACCEPT [0:0]
22+
:INPUT ACCEPT [0:0]
23+
:OUTPUT ACCEPT [0:0]
24+
:POSTROUTING ACCEPT [0:0]
25+
:DOCKER - [0:0]
26+
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
27+
-A OUTPUT -m addrtype --dst-type LOCAL -j DOCKER
28+
COMMIT
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
*raw
2+
:PREROUTING ACCEPT [0:0]
3+
:OUTPUT ACCEPT [0:0]
4+
-A PREROUTING -d 192.168.0.2/32 ! -i br-dummy -j DROP
5+
COMMIT
6+
*filter
7+
:INPUT ACCEPT [0:0]
8+
:FORWARD ACCEPT [0:0]
9+
:OUTPUT ACCEPT [0:0]
10+
:DOCKER - [0:0]
11+
:DOCKER-BRIDGE - [0:0]
12+
:DOCKER-CT - [0:0]
13+
:DOCKER-FORWARD - [0:0]
14+
:DOCKER-ISOLATION-STAGE-1 - [0:0]
15+
:DOCKER-ISOLATION-STAGE-2 - [0:0]
16+
-A FORWARD -j DOCKER-FORWARD
17+
-A DOCKER -d 192.168.0.2/32 ! -i br-dummy -o br-dummy -p tcp -m tcp --dport 80 -j ACCEPT
18+
-A DOCKER ! -i br-dummy -o br-dummy -j DROP
19+
-A DOCKER-BRIDGE -o br-dummy -j DOCKER
20+
-A DOCKER-CT -o br-dummy -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
21+
-A DOCKER-FORWARD -j DOCKER-CT
22+
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
23+
-A DOCKER-FORWARD -j DOCKER-BRIDGE
24+
-A DOCKER-FORWARD -i br-dummy -o br-dummy -j DROP
25+
-A DOCKER-FORWARD -i br-dummy ! -o br-dummy -j ACCEPT
26+
-A DOCKER-ISOLATION-STAGE-1 -i br-dummy ! -o br-dummy -j DOCKER-ISOLATION-STAGE-2
27+
-A DOCKER-ISOLATION-STAGE-2 -o br-dummy -j DROP
28+
COMMIT
29+
*nat
30+
:PREROUTING ACCEPT [0:0]
31+
:INPUT ACCEPT [0:0]
32+
:OUTPUT ACCEPT [0:0]
33+
:POSTROUTING ACCEPT [0:0]
34+
:DOCKER - [0:0]
35+
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
36+
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
37+
-A DOCKER -d 127.0.0.0/8 -i loopback0 -j RETURN
38+
-A DOCKER ! -i br-dummy -p tcp -m tcp --dport 8080 -j DNAT --to-destination 192.168.0.2:80
39+
COMMIT
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
*raw
2+
:PREROUTING ACCEPT [0:0]
3+
:OUTPUT ACCEPT [0:0]
4+
-A PREROUTING -d 192.168.0.2/32 ! -i br-dummy -j DROP
5+
-A PREROUTING -d 127.0.0.1/32 -i loopback0 -p tcp -m tcp --dport 8080 -j ACCEPT
6+
-A PREROUTING -d 127.0.0.1/32 ! -i lo -p tcp -m tcp --dport 8080 -j DROP
7+
COMMIT
8+
*filter
9+
:INPUT ACCEPT [0:0]
10+
:FORWARD ACCEPT [0:0]
11+
:OUTPUT ACCEPT [0:0]
12+
:DOCKER - [0:0]
13+
:DOCKER-BRIDGE - [0:0]
14+
:DOCKER-CT - [0:0]
15+
:DOCKER-FORWARD - [0:0]
16+
:DOCKER-ISOLATION-STAGE-1 - [0:0]
17+
:DOCKER-ISOLATION-STAGE-2 - [0:0]
18+
-A FORWARD -j DOCKER-FORWARD
19+
-A DOCKER -d 192.168.0.2/32 ! -i br-dummy -o br-dummy -p tcp -m tcp --dport 80 -j ACCEPT
20+
-A DOCKER ! -i br-dummy -o br-dummy -j DROP
21+
-A DOCKER-BRIDGE -o br-dummy -j DOCKER
22+
-A DOCKER-CT -o br-dummy -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
23+
-A DOCKER-FORWARD -j DOCKER-CT
24+
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
25+
-A DOCKER-FORWARD -j DOCKER-BRIDGE
26+
-A DOCKER-FORWARD -i br-dummy -o br-dummy -j DROP
27+
-A DOCKER-FORWARD -i br-dummy ! -o br-dummy -j ACCEPT
28+
-A DOCKER-ISOLATION-STAGE-1 -i br-dummy ! -o br-dummy -j DOCKER-ISOLATION-STAGE-2
29+
-A DOCKER-ISOLATION-STAGE-2 -o br-dummy -j DROP
30+
COMMIT
31+
*nat
32+
:PREROUTING ACCEPT [0:0]
33+
:INPUT ACCEPT [0:0]
34+
:OUTPUT ACCEPT [0:0]
35+
:POSTROUTING ACCEPT [0:0]
36+
:DOCKER - [0:0]
37+
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
38+
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
39+
-A DOCKER -d 127.0.0.0/8 -i loopback0 -j RETURN
40+
-A DOCKER -d 127.0.0.1/32 ! -i br-dummy -p tcp -m tcp --dport 8080 -j DNAT --to-destination 192.168.0.2:80
41+
COMMIT
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
*raw
2+
:PREROUTING ACCEPT [0:0]
3+
:OUTPUT ACCEPT [0:0]
4+
COMMIT
5+
*filter
6+
:INPUT ACCEPT [0:0]
7+
:FORWARD ACCEPT [0:0]
8+
:OUTPUT ACCEPT [0:0]
9+
:DOCKER - [0:0]
10+
:DOCKER-BRIDGE - [0:0]
11+
:DOCKER-CT - [0:0]
12+
:DOCKER-FORWARD - [0:0]
13+
:DOCKER-ISOLATION-STAGE-1 - [0:0]
14+
:DOCKER-ISOLATION-STAGE-2 - [0:0]
15+
-A FORWARD -j DOCKER-FORWARD
16+
-A DOCKER ! -i br-dummy -o br-dummy -j ACCEPT
17+
-A DOCKER-BRIDGE -o br-dummy -j DOCKER
18+
-A DOCKER-CT -o br-dummy -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
19+
-A DOCKER-FORWARD -j DOCKER-CT
20+
-A DOCKER-FORWARD -j DOCKER-ISOLATION-STAGE-1
21+
-A DOCKER-FORWARD -j DOCKER-BRIDGE
22+
-A DOCKER-FORWARD -i br-dummy -o br-dummy -j DROP
23+
-A DOCKER-FORWARD -i br-dummy ! -o br-dummy -j ACCEPT
24+
-A DOCKER-ISOLATION-STAGE-1 -i br-dummy ! -o br-dummy -j DOCKER-ISOLATION-STAGE-2
25+
-A DOCKER-ISOLATION-STAGE-2 -o br-dummy -j DROP
26+
COMMIT
27+
*nat
28+
:PREROUTING ACCEPT [0:0]
29+
:INPUT ACCEPT [0:0]
30+
:OUTPUT ACCEPT [0:0]
31+
:POSTROUTING ACCEPT [0:0]
32+
:DOCKER - [0:0]
33+
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
34+
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
35+
-A DOCKER -d 127.0.0.0/8 -i loopback0 -j RETURN
36+
-A DOCKER ! -i br-dummy -p tcp -m tcp --dport 8080 -j DNAT --to-destination 192.168.0.2:80
37+
COMMIT

0 commit comments

Comments
 (0)