From 94e6f853a999ac8820b14dbbb25377dac6a6c4f4 Mon Sep 17 00:00:00 2001 From: Victor Gama Date: Sun, 14 May 2023 15:36:46 -0300 Subject: [PATCH 1/2] fix: Allow port forwards to also bind IPv6 addresses --- pkg/guestagent/api/api.go | 1 + pkg/hostagent/hostagent.go | 16 +++++++-- pkg/hostagent/port_darwin.go | 70 ++++++++++++++++++++++++++---------- 3 files changed, 65 insertions(+), 22 deletions(-) diff --git a/pkg/guestagent/api/api.go b/pkg/guestagent/api/api.go index 02baa066fdd..9dfdb26ee1c 100644 --- a/pkg/guestagent/api/api.go +++ b/pkg/guestagent/api/api.go @@ -8,6 +8,7 @@ import ( var ( IPv4loopback1 = net.IPv4(127, 0, 0, 1) + IPv6loopback1 = net.IPv6loopback ) type IPPort struct { diff --git a/pkg/hostagent/hostagent.go b/pkg/hostagent/hostagent.go index bb57f856716..5b7304e1184 100644 --- a/pkg/hostagent/hostagent.go +++ b/pkg/hostagent/hostagent.go @@ -129,9 +129,19 @@ func New(instName string, stdout io.Writer, sigintCh chan os.Signal, opts ...Opt } rules = append(rules, y.PortForwards...) // Default forwards for all non-privileged ports from "127.0.0.1" and "::1" - rule := limayaml.PortForward{GuestIP: guestagentapi.IPv4loopback1} - limayaml.FillPortForwardDefaults(&rule, inst.Dir) - rules = append(rules, rule) + { + rule := limayaml.PortForward{GuestIP: guestagentapi.IPv4loopback1} + limayaml.FillPortForwardDefaults(&rule, inst.Dir) + rules = append(rules, rule) + } + { + rule := limayaml.PortForward{ + GuestIP: guestagentapi.IPv4loopback1, + HostIP: guestagentapi.IPv6loopback1, + } + limayaml.FillPortForwardDefaults(&rule, inst.Dir) + rules = append(rules, rule) + } limaDriver := driverutil.CreateTargetDriverInstance(&driver.BaseDriver{ Instance: inst, diff --git a/pkg/hostagent/port_darwin.go b/pkg/hostagent/port_darwin.go index fead0401b44..d3a38083fe2 100644 --- a/pkg/hostagent/port_darwin.go +++ b/pkg/hostagent/port_darwin.go @@ -24,14 +24,15 @@ func forwardTCP(ctx context.Context, sshConfig *ssh.SSHConfig, port int, local, if err != nil { return err } + logrus.Debugf("forwardTCP got localAddress: %s, split into %s and %s, and will parse it into an net.IP", local, localIPStr, localPortStr) localIP := net.ParseIP(localIPStr) localPort, err := strconv.Atoi(localPortStr) if err != nil { return err } - if !localIP.Equal(api.IPv4loopback1) || localPort >= 1024 { - return forwardSSH(ctx, sshConfig, port, local, remote, verb, false) + if (!localIP.Equal(api.IPv4loopback1) && !localIP.Equal(net.IPv6loopback)) || localPort >= 1024 { + return forwardSSH(ctx, sshConfig, port, remote, local, verb, false) } // on macOS, listening on 127.0.0.1:80 requires root while 0.0.0.0:80 does not require root. @@ -86,9 +87,10 @@ func forwardTCP(ctx context.Context, sshConfig *ssh.SSHConfig, port int, local, var pseudoLoopbackForwarders = make(map[string]*pseudoLoopbackForwarder) type pseudoLoopbackForwarder struct { - ln *net.TCPListener - unixAddr *net.UnixAddr - onClose func() error + lns []*net.TCPListener + unixAddr *net.UnixAddr + onClose func() error + incomingConns chan *net.TCPConn } func newPseudoLoopbackForwarder(localPort int, unixSock string) (*pseudoLoopbackForwarder, error) { @@ -97,30 +99,56 @@ func newPseudoLoopbackForwarder(localPort int, unixSock string) (*pseudoLoopback return nil, err } - lnAddr, err := net.ResolveTCPAddr("tcp4", fmt.Sprintf("0.0.0.0:%d", localPort)) - if err != nil { - return nil, err + toResolve := [][]string{ + {"tcp4", fmt.Sprintf("0.0.0.0:%d", localPort)}, + {"tcp6", fmt.Sprintf("[::]:%d", localPort)}, } - ln, err := net.ListenTCP("tcp4", lnAddr) - if err != nil { - return nil, err + + var lns []*net.TCPListener + for _, addr := range toResolve { + network, address := addr[0], addr[1] + lnAddr, err := net.ResolveTCPAddr(network, address) + if err != nil { + return nil, err + } + ln, err := net.ListenTCP(network, lnAddr) + if err != nil { + return nil, err + } + lns = append(lns, ln) } plf := &pseudoLoopbackForwarder{ - ln: ln, - unixAddr: unixAddr, + lns: lns, + incomingConns: make(chan *net.TCPConn, 10), + unixAddr: unixAddr, } return plf, nil } -func (plf *pseudoLoopbackForwarder) Serve() error { - defer plf.ln.Close() +func (plf *pseudoLoopbackForwarder) acceptLn(ln *net.TCPListener) { + defer ln.Close() for { - ac, err := plf.ln.AcceptTCP() + ac, err := ln.AcceptTCP() if err != nil { - return err + logrus.WithError(err).Errorf("Stopping listening %#v", ln) + return } + plf.incomingConns <- ac + } +} + +func (plf *pseudoLoopbackForwarder) accept() { + for _, ln := range plf.lns { + go plf.acceptLn(ln) + } +} + +func (plf *pseudoLoopbackForwarder) Serve() error { + plf.accept() + + for ac := range plf.incomingConns { remoteAddr := ac.RemoteAddr().String() // ip:port remoteAddrIP, _, err := net.SplitHostPort(remoteAddr) if err != nil { @@ -128,7 +156,7 @@ func (plf *pseudoLoopbackForwarder) Serve() error { ac.Close() continue } - if remoteAddrIP != "127.0.0.1" { + if remoteAddrIP != "127.0.0.1" && remoteAddrIP != "::" { logrus.WithError(err).Debugf("pseudoloopback forwarder: rejecting non-loopback remoteAddr %q", remoteAddr) ac.Close() continue @@ -139,6 +167,8 @@ func (plf *pseudoLoopbackForwarder) Serve() error { } }(ac) } + + return nil } func (plf *pseudoLoopbackForwarder) forward(ac *net.TCPConn) error { @@ -153,6 +183,8 @@ func (plf *pseudoLoopbackForwarder) forward(ac *net.TCPConn) error { } func (plf *pseudoLoopbackForwarder) Close() error { - _ = plf.ln.Close() + for _, ln := range plf.lns { + _ = ln.Close() + } return plf.onClose() } From 7b902d53ad65ecc666605f8c63d1e67b29f73918 Mon Sep 17 00:00:00 2001 From: Victor Gama Date: Sun, 14 May 2023 16:43:18 -0300 Subject: [PATCH 2/2] hack: Inspect vmnet logs --- hack/test-example.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/hack/test-example.sh b/hack/test-example.sh index d3a7ce11158..39b32705287 100755 --- a/hack/test-example.sh +++ b/hack/test-example.sh @@ -86,6 +86,7 @@ function diagnose() { export ftp_proxy=http://localhost:2121 INFO "Starting \"$NAME\" from \"$FILE\"" +defer "cat \"$HOME/.lima/${NAME}\"/*.log" defer "limactl delete -f \"$NAME\"" if [[ -n ${CHECKS["disk"]} ]]; then