Use simulated dual-stack binds when using WSL
Resolves a WSL problem where traffic from only one stack is relayed Signed-off-by: Jason T. Greene <jason.greene@redhat.com>
This commit is contained in:
parent
5ac00a7287
commit
772ead2531
|
@ -1,3 +1,6 @@
|
||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -307,11 +310,11 @@ func exposePorts(pm rkport.Manager, portMappings []types.PortMapping, childIP st
|
||||||
ChildPort: int(port.ContainerPort + i),
|
ChildPort: int(port.ContainerPort + i),
|
||||||
ChildIP: childIP,
|
ChildIP: childIP,
|
||||||
}
|
}
|
||||||
if err := rkportutil.ValidatePortSpec(spec, nil); err != nil {
|
|
||||||
return err
|
for _, spec = range splitDualStackSpecIfWsl(spec) {
|
||||||
}
|
if err := validateAndAddPort(ctx, pm, spec); err != nil {
|
||||||
if _, err := pm.AddPort(ctx, spec); err != nil {
|
return err
|
||||||
return err
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -319,6 +322,17 @@ func exposePorts(pm rkport.Manager, portMappings []types.PortMapping, childIP st
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateAndAddPort(ctx context.Context, pm rkport.Manager, spec rkport.Spec) error {
|
||||||
|
if err := rkportutil.ValidatePortSpec(spec, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if _, err := pm.AddPort(ctx, spec); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func child() error {
|
func child() error {
|
||||||
// load the config from the parent
|
// load the config from the parent
|
||||||
var opaque map[string]string
|
var opaque map[string]string
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/containers/common/pkg/machine"
|
||||||
|
rkport "github.com/rootless-containers/rootlesskit/pkg/port"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WSL machines do not relay ipv4 traffic to dual-stack ports, simulate instead
|
||||||
|
func splitDualStackSpecIfWsl(spec rkport.Spec) []rkport.Spec {
|
||||||
|
specs := []rkport.Spec{spec}
|
||||||
|
protocol := spec.Proto
|
||||||
|
if machine.MachineHostType() != machine.Wsl || strings.HasSuffix(protocol, "4") || strings.HasSuffix(protocol, "6") {
|
||||||
|
return specs
|
||||||
|
}
|
||||||
|
|
||||||
|
ip := net.ParseIP(spec.ParentIP)
|
||||||
|
splitLoopback := ip.IsLoopback() && ip.To4() == nil
|
||||||
|
// Map ::1 and 0.0.0.0/:: to ipv4 + ipv6 to simulate dual-stack
|
||||||
|
if ip.IsUnspecified() || splitLoopback {
|
||||||
|
specs = append(specs, spec)
|
||||||
|
specs[0].Proto = protocol + "4"
|
||||||
|
specs[1].Proto = protocol + "6"
|
||||||
|
if splitLoopback {
|
||||||
|
// Hacky, but we will only have one ipv4 loopback with WSL config
|
||||||
|
specs[0].ParentIP = "127.0.0.1"
|
||||||
|
}
|
||||||
|
if ip.IsUnspecified() {
|
||||||
|
specs[0].ParentIP = "0.0.0.0"
|
||||||
|
specs[1].ParentIP = "::"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return specs
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/containers/common/pkg/machine"
|
||||||
|
"github.com/rootless-containers/rootlesskit/pkg/port"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SpecData struct {
|
||||||
|
mach string
|
||||||
|
sourceProto string
|
||||||
|
sourceIP string
|
||||||
|
expectCount int
|
||||||
|
expectProto string
|
||||||
|
expectIP string
|
||||||
|
secondProto string
|
||||||
|
secondIP string
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDualStackSplit(t *testing.T) {
|
||||||
|
//nolint
|
||||||
|
const (
|
||||||
|
IP4_ALL = "0.0.0.0"
|
||||||
|
IP4__LO = "127.0.0.1"
|
||||||
|
IP6_ALL = "::"
|
||||||
|
IP6__LO = "::1"
|
||||||
|
TCP_ = "tcp"
|
||||||
|
TCP4 = "tcp4"
|
||||||
|
TCP6 = "tcp6"
|
||||||
|
WSL = "wsl"
|
||||||
|
___ = ""
|
||||||
|
IP6_REG = "2001:0db8:85a3:0000:0000:8a2e:0370:7334"
|
||||||
|
IP4_REG = "10.0.0.1"
|
||||||
|
)
|
||||||
|
|
||||||
|
tests := []SpecData{
|
||||||
|
// Split cases
|
||||||
|
{WSL, TCP_, IP4_ALL, 2, TCP4, IP4_ALL, TCP6, IP6_ALL},
|
||||||
|
{WSL, TCP_, IP6_ALL, 2, TCP4, IP4_ALL, TCP6, IP6_ALL},
|
||||||
|
{WSL, TCP_, IP6__LO, 2, TCP4, IP4__LO, TCP6, IP6__LO},
|
||||||
|
|
||||||
|
// Non-Split
|
||||||
|
{WSL, TCP_, IP4__LO, 1, TCP_, IP4__LO, "", ""},
|
||||||
|
{WSL, TCP4, IP4_ALL, 1, TCP4, IP4_ALL, "", ""},
|
||||||
|
{WSL, TCP6, IP6__LO, 1, TCP6, IP6__LO, "", ""},
|
||||||
|
{WSL, TCP_, IP4_REG, 1, TCP_, IP4_REG, "", ""},
|
||||||
|
{WSL, TCP_, IP6_REG, 1, TCP_, IP6_REG, "", ""},
|
||||||
|
{___, TCP_, IP4_ALL, 1, TCP_, IP4_ALL, "", ""},
|
||||||
|
{___, TCP_, IP6_ALL, 1, TCP_, IP6_ALL, "", ""},
|
||||||
|
{___, TCP_, IP4__LO, 1, TCP_, IP4__LO, "", ""},
|
||||||
|
{___, TCP_, IP6__LO, 1, TCP_, IP6__LO, "", ""},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, data := range tests {
|
||||||
|
verifySplit(t, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func verifySplit(t *testing.T, data SpecData) {
|
||||||
|
machine := machine.GetMachineMarker()
|
||||||
|
oldEnable, oldType := machine.Enabled, machine.Type
|
||||||
|
machine.Enabled, machine.Type = len(data.mach) > 0, data.mach
|
||||||
|
|
||||||
|
source := port.Spec{
|
||||||
|
Proto: data.sourceProto,
|
||||||
|
ParentIP: data.sourceIP,
|
||||||
|
ParentPort: 100,
|
||||||
|
ChildIP: "1.1.1.1",
|
||||||
|
ChildPort: 200,
|
||||||
|
}
|
||||||
|
expect, second := source, source
|
||||||
|
specs := splitDualStackSpecIfWsl(source)
|
||||||
|
|
||||||
|
assert.Equal(t, data.expectCount, len(specs))
|
||||||
|
|
||||||
|
expect.Proto = data.expectProto
|
||||||
|
expect.ParentIP = data.expectIP
|
||||||
|
assert.Equal(t, expect, specs[0])
|
||||||
|
|
||||||
|
if data.expectCount > 1 {
|
||||||
|
second.Proto = data.secondProto
|
||||||
|
second.ParentIP = data.secondIP
|
||||||
|
assert.Equal(t, second, specs[1])
|
||||||
|
}
|
||||||
|
|
||||||
|
machine.Enabled, machine.Type = oldEnable, oldType
|
||||||
|
}
|
Loading…
Reference in New Issue