diff --git a/libnetwork/pasta/pasta_linux.go b/libnetwork/pasta/pasta_linux.go index bce603f52..6caf49411 100644 --- a/libnetwork/pasta/pasta_linux.go +++ b/libnetwork/pasta/pasta_linux.go @@ -26,11 +26,16 @@ import ( ) const ( - dnsForwardOpt = "--dns-forward" + dnsForwardOpt = "--dns-forward" + mapGuestAddrOpt = "--map-guest-addr" // dnsForwardIpv4 static ip used as nameserver address inside the netns, // given this is a "link local" ip it should be very unlikely that it causes conflicts dnsForwardIpv4 = "169.254.1.1" + + // mapGuestAddrIpv4 static ip used as forwarder address inside the netns to reach the host, + // given this is a "link local" ip it should be very unlikely that it causes conflicts + mapGuestAddrIpv4 = "169.254.1.2" ) type SetupOptions struct { @@ -60,7 +65,7 @@ func Setup2(opts *SetupOptions) (*SetupResult, error) { return nil, fmt.Errorf("could not find pasta, the network namespace can't be configured: %w", err) } - cmdArgs, dnsForwardIPs, err := createPastaArgs(opts) + cmdArgs, dnsForwardIPs, mapGuestAddrIPs, err := createPastaArgs(opts) if err != nil { return nil, err } @@ -112,19 +117,27 @@ func Setup2(opts *SetupOptions) (*SetupResult, error) { } result.IPv6 = ipv6 - for _, ip := range dnsForwardIPs { + result.DNSForwardIPs = filterIpFamily(dnsForwardIPs, ipv4, ipv6) + result.MapGuestAddrIPs = filterIpFamily(mapGuestAddrIPs, ipv4, ipv6) + + return result, nil +} + +func filterIpFamily(ips []string, ipv4, ipv6 bool) []string { + var result []string + for _, ip := range ips { ipp := net.ParseIP(ip) - // add the namesever ip only if the address family matches + // add the ip only if the address family matches if ipv4 && util.IsIPv4(ipp) || ipv6 && util.IsIPv6(ipp) { - result.DNSForwardIPs = append(result.DNSForwardIPs, ip) + result = append(result, ip) } } - - return result, nil + return result } -// createPastaArgs creates the pasta arguments, it returns the args to be passed to pasta(1) and as second arg the dns forward ips used. -func createPastaArgs(opts *SetupOptions) ([]string, []string, error) { +// createPastaArgs creates the pasta arguments, it returns the args to be passed to pasta(1) +// and as second arg the dns forward ips used. As third arg the map guest addr ips used. +func createPastaArgs(opts *SetupOptions) ([]string, []string, []string, error) { noTCPInitPorts := true noUDPInitPorts := true noTCPNamespacePorts := true @@ -149,6 +162,7 @@ func createPastaArgs(opts *SetupOptions) ([]string, []string, error) { }) var dnsForwardIPs []string + var mapGuestAddrIPs []string for i, opt := range cmdArgs { switch opt { case "-t", "--tcp-ports": @@ -166,6 +180,10 @@ func createPastaArgs(opts *SetupOptions) ([]string, []string, error) { if len(cmdArgs) > i+1 { dnsForwardIPs = append(dnsForwardIPs, cmdArgs[i+1]) } + case mapGuestAddrOpt: + if len(cmdArgs) > i+1 { + mapGuestAddrIPs = append(mapGuestAddrIPs, cmdArgs[i+1]) + } } } @@ -186,7 +204,7 @@ func createPastaArgs(opts *SetupOptions) ([]string, []string, error) { noUDPInitPorts = false cmdArgs = append(cmdArgs, "-u") default: - return nil, nil, fmt.Errorf("can't forward protocol: %s", protocol) + return nil, nil, nil, fmt.Errorf("can't forward protocol: %s", protocol) } arg := fmt.Sprintf("%s%d-%d:%d-%d", addr, @@ -226,5 +244,13 @@ func createPastaArgs(opts *SetupOptions) ([]string, []string, error) { cmdArgs = append(cmdArgs, "--netns", opts.Netns) - return cmdArgs, dnsForwardIPs, nil + // do this as last arg + if len(mapGuestAddrIPs) == 0 { + // the user did not request custom --map-guest-addr so add our own so that we can use this + // for our own host.containers.internal host entry. + cmdArgs = append(cmdArgs, mapGuestAddrOpt, mapGuestAddrIpv4) + mapGuestAddrIPs = append(mapGuestAddrIPs, mapGuestAddrIpv4) + } + + return cmdArgs, dnsForwardIPs, mapGuestAddrIPs, nil } diff --git a/libnetwork/pasta/pasta_linux_test.go b/libnetwork/pasta/pasta_linux_test.go index 6ad78b242..16beeebbd 100644 --- a/libnetwork/pasta/pasta_linux_test.go +++ b/libnetwork/pasta/pasta_linux_test.go @@ -20,11 +20,12 @@ func makeSetupOptions(configArgs, extraArgs []string, ports []types.PortMapping) func Test_createPastaArgs(t *testing.T) { tests := []struct { - name string - input *SetupOptions - wantArgs []string - wantDnsForward []string - wantErr string + name string + input *SetupOptions + wantArgs []string + wantDnsForward []string + wantMapGuestAddr []string + wantErr string }{ { name: "default options", @@ -36,8 +37,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "--dns-forward", dnsForwardIpv4, "-t", "none", "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "basic port", @@ -49,8 +52,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-t", "80-80:80-80", "--dns-forward", dnsForwardIpv4, "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "port range", @@ -62,8 +67,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-t", "80-82:80-82", "--dns-forward", dnsForwardIpv4, "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "different host and container port", @@ -75,8 +82,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-t", "80-80:60-60", "--dns-forward", dnsForwardIpv4, "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "tcp and udp port", @@ -91,8 +100,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-t", "80-80:60-60", "-u", "100-100:100-100", "--dns-forward", dnsForwardIpv4, "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "two tcp ports", @@ -107,8 +118,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-t", "80-80:60-60", "-t", "100-100:100-100", "--dns-forward", dnsForwardIpv4, "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "invalid port", @@ -131,8 +144,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-i", "eth0", "-n", "24", "--dns-forward", dnsForwardIpv4, "-t", "none", "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "config options before extra options", @@ -144,8 +159,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-i", "eth0", "-n", "24", "--dns-forward", dnsForwardIpv4, "-t", "none", "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "-T option", @@ -157,8 +174,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-T", "80", "--dns-forward", dnsForwardIpv4, "-t", "none", "-u", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "--tcp-ns option", @@ -170,8 +189,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "--tcp-ns", "80", "--dns-forward", dnsForwardIpv4, "-t", "none", "-u", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "--map-gw option", @@ -183,8 +204,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "--dns-forward", dnsForwardIpv4, "-t", "none", "-u", "none", "-T", "none", "-U", "none", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { // https://github.com/containers/podman/issues/22477 @@ -196,8 +219,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-T", "80", "--dns-forward", dnsForwardIpv4, "-t", "none", "-u", "none", "-U", "none", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "two --map-gw", @@ -209,8 +234,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-T", "80", "--dns-forward", dnsForwardIpv4, "-t", "none", "-u", "none", "-U", "none", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "--dns-forward option", @@ -222,8 +249,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "--dns-forward", "192.168.255.255", "-t", "none", "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{"192.168.255.255"}, + wantDnsForward: []string{"192.168.255.255"}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "two --dns-forward options", @@ -235,8 +264,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "--dns-forward", "192.168.255.255", "--dns-forward", "::1", "-t", "none", "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{"192.168.255.255", "::1"}, + wantDnsForward: []string{"192.168.255.255", "::1"}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "port and custom opt", @@ -248,8 +279,10 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "-i", "eth0", "-t", "80-80:80-80", "--dns-forward", dnsForwardIpv4, "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, }, { name: "Add verbose logging", @@ -261,14 +294,45 @@ func Test_createPastaArgs(t *testing.T) { wantArgs: []string{ "--config-net", "--log-file=/tmp/log", "--trace", "--debug", "--dns-forward", dnsForwardIpv4, "-t", "none", "-u", "none", "-T", "none", "-U", "none", - "--no-map-gw", "--netns", "netns123", + "--no-map-gw", "--netns", "netns123", mapGuestAddrOpt, mapGuestAddrIpv4, }, - wantDnsForward: []string{dnsForwardIpv4}, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{mapGuestAddrIpv4}, + }, + { + name: "--map-guest-addr option", + input: makeSetupOptions( + nil, + []string{mapGuestAddrOpt, "192.168.255.255"}, + nil, + ), + wantArgs: []string{ + "--config-net", mapGuestAddrOpt, "192.168.255.255", dnsForwardOpt, dnsForwardIpv4, + "-t", "none", "-u", "none", "-T", "none", "-U", "none", "--no-map-gw", "--quiet", + "--netns", "netns123", + }, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{"192.168.255.255"}, + }, + { + name: "two --map-guest-addr options", + input: makeSetupOptions( + nil, + []string{mapGuestAddrOpt, "192.168.255.255", mapGuestAddrOpt, "::1"}, + nil, + ), + wantArgs: []string{ + "--config-net", mapGuestAddrOpt, "192.168.255.255", mapGuestAddrOpt, "::1", + dnsForwardOpt, dnsForwardIpv4, "-t", "none", "-u", "none", "-T", "none", + "-U", "none", "--no-map-gw", "--quiet", "--netns", "netns123", + }, + wantDnsForward: []string{dnsForwardIpv4}, + wantMapGuestAddr: []string{"192.168.255.255", "::1"}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - args, dnsForward, err := createPastaArgs(tt.input) + args, dnsForward, mapGuestAddr, err := createPastaArgs(tt.input) if tt.wantErr != "" { assert.EqualError(t, err, tt.wantErr, "createPastaArgs error") return @@ -276,6 +340,7 @@ func Test_createPastaArgs(t *testing.T) { assert.NoError(t, err, "expect no createPastaArgs error") assert.Equal(t, tt.wantArgs, args, "check arguments") assert.Equal(t, tt.wantDnsForward, dnsForward, "check dns forward") + assert.Equal(t, tt.wantMapGuestAddr, mapGuestAddr, "check map guest addr") }) } } diff --git a/libnetwork/pasta/types.go b/libnetwork/pasta/types.go index b601e5169..f570afc3e 100644 --- a/libnetwork/pasta/types.go +++ b/libnetwork/pasta/types.go @@ -10,6 +10,9 @@ type SetupResult struct { // DNSForwardIP is the ip used in --dns-forward, it should be added as first // entry to resolv.conf in the container. DNSForwardIPs []string + // MapGuestIps are the ips used for the --map-guest-addr option which + // we can use for the host.containers.internal entry. + MapGuestAddrIPs []string // IPv6 says whenever pasta run with ipv6 support IPv6 bool }