Просмотр исходного кода

net/tsdial: partially fix "tailscale nc" (UserDial) on macOS

At least in the case of dialing a Tailscale IP.

Updates #4529

Change-Id: I9fd667d088a14aec4a56e23aabc2b1ffddafa3fe
Signed-off-by: Brad Fitzpatrick <[email protected]>
Brad Fitzpatrick 1 год назад
Родитель
Сommit
b0fbd85592
3 измененных файлов с 25 добавлено и 8 удалено
  1. 2 4
      cmd/tailscale/cli/ssh.go
  2. 14 4
      net/tsdial/tsdial.go
  3. 9 0
      version/prop.go

+ 2 - 4
cmd/tailscale/cli/ssh.go

@@ -106,10 +106,8 @@ func runSSH(ctx context.Context, args []string) error {
 		"-o", "CanonicalizeHostname no", // https://github.com/tailscale/tailscale/issues/10348
 	)
 
-	// TODO(bradfitz): nc is currently broken on macOS:
-	// https://github.com/tailscale/tailscale/issues/4529
-	// So don't use it for now. MagicDNS is usually working on macOS anyway
-	// and they're not in userspace mode, so 'nc' isn't very useful.
+	// MagicDNS is usually working on macOS anyway and they're not in userspace
+	// mode, so 'nc' isn't very useful.
 	if runtime.GOOS != "darwin" {
 		socketArg := ""
 		if rootArgs.socket != "" && rootArgs.socket != paths.DefaultTailscaledSocket() {

+ 14 - 4
net/tsdial/tsdial.go

@@ -21,10 +21,12 @@ import (
 	"tailscale.com/net/netknob"
 	"tailscale.com/net/netmon"
 	"tailscale.com/net/netns"
+	"tailscale.com/net/tsaddr"
 	"tailscale.com/types/logger"
 	"tailscale.com/types/netmap"
 	"tailscale.com/util/clientmetric"
 	"tailscale.com/util/mak"
+	"tailscale.com/version"
 )
 
 // Dialer dials out of tailscaled, while taking care of details while
@@ -337,6 +339,14 @@ func (d *Dialer) UserDial(ctx context.Context, network, addr string) (net.Conn,
 		}
 		return d.NetstackDialTCP(ctx, ipp)
 	}
+	// Workaround for macOS for now: dial Tailscale IPs with peer dialer.
+	// TODO(bradfitz): fix dialing subnet routers, public IPs via exit nodes,
+	// etc. This is a temporary partial for macOS. We need to plumb ART tables &
+	// prefs & host routing table updates around in more places. We just don't
+	// know from the limited context here how to dial properly.
+	if version.IsMacGUIVariant() && tsaddr.IsTailscaleIP(ipp.Addr()) {
+		return d.getPeerDialer().DialContext(ctx, network, ipp.String())
+	}
 	// TODO(bradfitz): netns, etc
 	var stdDialer net.Dialer
 	return stdDialer.DialContext(ctx, network, ipp.String())
@@ -365,14 +375,14 @@ func (d *Dialer) dialPeerAPI(ctx context.Context, network, addr string) (net.Con
 	return d.getPeerDialer().DialContext(ctx, network, addr)
 }
 
-// getPeerDialer returns the *net.Dialer to use to dial peers to use
-// PeerAPI.
+// getPeerDialer returns the *net.Dialer to use to dial peers (e.g. for peerapi,
+// or "tailscale nc")
 //
 // This is not used in netstack mode.
 //
 // The primary function of this is to work on macOS & iOS's in the
-// Network/System Extension so it can mark the dialer as staying
-// within the network namespace/sandbox.
+// Network/System Extension so it can mark the dialer as staying within the
+// network namespace/sandbox.
 func (d *Dialer) getPeerDialer() *net.Dialer {
 	d.peerDialerOnce.Do(func() {
 		d.peerDialer = &net.Dialer{

+ 9 - 0
version/prop.go

@@ -40,6 +40,15 @@ func OS() string {
 	return runtime.GOOS
 }
 
+// IsMacGUIVariant reports whether runtime.GOOS=="darwin" and this one of the
+// two GUI variants (that is, not tailscaled-on-macOS).
+// This predicate should not be used to determine sandboxing properties. It's
+// meant for callers to determine whether the NetworkExtension-like auto-netns
+// is in effect.
+func IsMacGUIVariant() bool {
+	return IsMacAppStore() || IsMacSysExt()
+}
+
 // IsSandboxedMacOS reports whether this process is a sandboxed macOS
 // process (either the app or the extension). It is true for the Mac App Store
 // and macsys (System Extension) version on macOS, and false for