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 <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2024-04-07 14:25:11 -07:00 committed by Brad Fitzpatrick
parent a5e1f7d703
commit b0fbd85592
3 changed files with 25 additions and 8 deletions

View File

@ -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() {

View File

@ -21,10 +21,12 @@
"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{

View File

@ -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