From 058ba3486771333e52ca2c1ed349fa622b781c83 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Mon, 26 Aug 2024 14:45:32 +0200 Subject: [PATCH] pasta: add new --map-guest-addr option The --map-guest-addr option allows us to sepcify a ip that is remapped to the actual host ip that was used by pasta. This is done to fix the problem where connecting to the host ip was not possible as the same ip was used in the netns. We now set --map-guest-addr 169.254.1.2 which follows the same idea we already used for the --dns-forward option. With that podman can use this ip to set it for host.containers.internal which should the case where there was no second host ip available, see https://github.com/containers/podman/issues/19213 Signed-off-by: Paul Holzinger --- libnetwork/pasta/pasta_linux.go | 48 +++++++++--- libnetwork/pasta/pasta_linux_test.go | 113 +++++++++++++++++++++------ libnetwork/pasta/types.go | 3 + 3 files changed, 129 insertions(+), 35 deletions(-) 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 }