diff --git a/pkg/port/builtin/child/child.go b/pkg/port/builtin/child/child.go index 83ab638f..2a9e0098 100644 --- a/pkg/port/builtin/child/child.go +++ b/pkg/port/builtin/child/child.go @@ -123,6 +123,11 @@ func (d *childDriver) handleConnectRequest(c *net.UnixConn, req *msg.Request) er ip := req.IP if ip == "" { ip = "127.0.0.1" + if req.ParentIP != "" { + if req.ParentIP != req.HostGatewayIP && req.ParentIP != "0.0.0.0" { + ip = req.ParentIP + } + } } else { p := net.ParseIP(ip) if p == nil { diff --git a/pkg/port/builtin/msg/msg.go b/pkg/port/builtin/msg/msg.go index f77468ec..4bb12d5d 100644 --- a/pkg/port/builtin/msg/msg.go +++ b/pkg/port/builtin/msg/msg.go @@ -19,10 +19,12 @@ const ( // Request and Response are encoded as JSON with uint32le length header. type Request struct { - Type string // "init" or "connect" - Proto string // "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6" - IP string - Port int + Type string // "init" or "connect" + Proto string // "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6" + IP string + Port int + ParentIP string + HostGatewayIP string } // Reply may contain FD as OOB @@ -48,14 +50,33 @@ func Initiate(c *net.UnixConn) error { return c.CloseRead() } +func hostGatewayIP() string { + addrs, err := net.InterfaceAddrs() + if err != nil { + return "" + } + + for _, addr := range addrs { + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + return ipnet.IP.String() + } + } + } + + return "" +} + // ConnectToChild connects to the child UNIX socket, and obtains TCP or UDP socket FD // that corresponds to the port spec. func ConnectToChild(c *net.UnixConn, spec port.Spec) (int, error) { req := Request{ - Type: RequestTypeConnect, - Proto: spec.Proto, - Port: spec.ChildPort, - IP: spec.ChildIP, + Type: RequestTypeConnect, + Proto: spec.Proto, + Port: spec.ChildPort, + IP: spec.ChildIP, + ParentIP: spec.ParentIP, + HostGatewayIP: hostGatewayIP(), } if _, err := lowlevelmsgutil.MarshalToWriter(c, &req); err != nil { return 0, err