xcode: allow ICMP ping relay on macOS + iOS platforms (#12048)
Fixes tailscale/tailscale#10393 Fixes tailscale/corp#15412 Fixes tailscale/corp#19808 On Apple platforms, exit nodes and subnet routers have been unable to relay pings from Tailscale devices to non-Tailscale devices due to sandbox restrictions imposed on our network extensions by Apple. The sandbox prevented the code in netstack.go from spawning the `ping` process which we were using. Replace that exec call with logic to send an ICMP echo request directly, which appears to work in userspace, and not trigger a sandbox violation in the syslog. Signed-off-by: Andrea Gottardo <andrea@gottardo.me>main
parent
59848fe14b
commit
e5f67f90a2
@ -0,0 +1,65 @@ |
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build !darwin && !ios
|
||||
|
||||
package netstack |
||||
|
||||
import ( |
||||
"net/netip" |
||||
"os" |
||||
"os/exec" |
||||
"runtime" |
||||
"time" |
||||
|
||||
"tailscale.com/version/distro" |
||||
) |
||||
|
||||
// setAmbientCapsRaw is non-nil on Linux for Synology, to run ping with
|
||||
// CAP_NET_RAW from tailscaled's binary.
|
||||
var setAmbientCapsRaw func(*exec.Cmd) |
||||
|
||||
var isSynology = runtime.GOOS == "linux" && distro.Get() == distro.Synology |
||||
|
||||
// sendOutboundUserPing sends a non-privileged ICMP (or ICMPv6) ping to dstIP with the given timeout.
|
||||
func (ns *Impl) sendOutboundUserPing(dstIP netip.Addr, timeout time.Duration) error { |
||||
var err error |
||||
switch runtime.GOOS { |
||||
case "windows": |
||||
err = exec.Command("ping", "-n", "1", "-w", "3000", dstIP.String()).Run() |
||||
case "freebsd": |
||||
// Note: 2000 ms is actually 1 second + 2,000
|
||||
// milliseconds extra for 3 seconds total.
|
||||
// See https://github.com/tailscale/tailscale/pull/3753 for details.
|
||||
ping := "ping" |
||||
if dstIP.Is6() { |
||||
ping = "ping6" |
||||
} |
||||
err = exec.Command(ping, "-c", "1", "-W", "2000", dstIP.String()).Run() |
||||
case "openbsd": |
||||
ping := "ping" |
||||
if dstIP.Is6() { |
||||
ping = "ping6" |
||||
} |
||||
err = exec.Command(ping, "-c", "1", "-w", "3", dstIP.String()).Run() |
||||
case "android": |
||||
ping := "/system/bin/ping" |
||||
if dstIP.Is6() { |
||||
ping = "/system/bin/ping6" |
||||
} |
||||
err = exec.Command(ping, "-c", "1", "-w", "3", dstIP.String()).Run() |
||||
default: |
||||
ping := "ping" |
||||
if isSynology { |
||||
ping = "/bin/ping" |
||||
} |
||||
cmd := exec.Command(ping, "-c", "1", "-W", "3", dstIP.String()) |
||||
if isSynology && os.Getuid() != 0 { |
||||
// On DSM7 we run as non-root and need to pass
|
||||
// CAP_NET_RAW if our binary has it.
|
||||
setAmbientCapsRaw(cmd) |
||||
} |
||||
err = cmd.Run() |
||||
} |
||||
return err |
||||
} |
||||
@ -0,0 +1,38 @@ |
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:build darwin || ios
|
||||
|
||||
package netstack |
||||
|
||||
import ( |
||||
"net/netip" |
||||
"time" |
||||
|
||||
"github.com/prometheus-community/pro-bing" |
||||
) |
||||
|
||||
// sendOutboundUserPing sends a non-privileged ICMP (or ICMPv6) ping to dstIP with the given timeout.
|
||||
func (ns *Impl) sendOutboundUserPing(dstIP netip.Addr, timeout time.Duration) error { |
||||
p, err := probing.NewPinger(dstIP.String()) |
||||
if err != nil { |
||||
ns.logf("sendICMPPingToIP failed to create pinger: %v", err) |
||||
return err |
||||
} |
||||
|
||||
p.Timeout = timeout |
||||
p.Count = 1 |
||||
p.SetPrivileged(false) |
||||
|
||||
p.OnSend = func(pkt *probing.Packet) { |
||||
ns.logf("sendICMPPingToIP: forwarding ping to %s:", p.Addr()) |
||||
} |
||||
p.OnRecv = func(pkt *probing.Packet) { |
||||
ns.logf("sendICMPPingToIP: %d bytes pong from %s: icmp_seq=%d time=%v", pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt) |
||||
} |
||||
p.OnFinish = func(stats *probing.Statistics) { |
||||
ns.logf("sendICMPPingToIP: done, %d replies received", stats.PacketsRecv) |
||||
} |
||||
|
||||
return p.Run() |
||||
} |
||||
Loading…
Reference in new issue