netstack_userping.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. //go:build !darwin && !ios
  4. package netstack
  5. import (
  6. "net/netip"
  7. "os"
  8. "os/exec"
  9. "runtime"
  10. "time"
  11. "tailscale.com/version/distro"
  12. )
  13. // setAmbientCapsRaw is non-nil on Linux for Synology, to run ping with
  14. // CAP_NET_RAW from tailscaled's binary.
  15. var setAmbientCapsRaw func(*exec.Cmd)
  16. var isSynology = runtime.GOOS == "linux" && distro.Get() == distro.Synology
  17. // sendOutboundUserPing sends a non-privileged ICMP (or ICMPv6) ping to dstIP with the given timeout.
  18. func (ns *Impl) sendOutboundUserPing(dstIP netip.Addr, timeout time.Duration) error {
  19. var err error
  20. switch runtime.GOOS {
  21. case "windows":
  22. err = exec.Command("ping", "-n", "1", "-w", "3000", dstIP.String()).Run()
  23. case "freebsd":
  24. // Note: 2000 ms is actually 1 second + 2,000
  25. // milliseconds extra for 3 seconds total.
  26. // See https://github.com/tailscale/tailscale/pull/3753 for details.
  27. ping := "ping"
  28. if dstIP.Is6() {
  29. ping = "ping6"
  30. }
  31. err = exec.Command(ping, "-c", "1", "-W", "2000", dstIP.String()).Run()
  32. case "openbsd":
  33. ping := "ping"
  34. if dstIP.Is6() {
  35. ping = "ping6"
  36. }
  37. err = exec.Command(ping, "-c", "1", "-w", "3", dstIP.String()).Run()
  38. case "android":
  39. ping := "/system/bin/ping"
  40. if dstIP.Is6() {
  41. ping = "/system/bin/ping6"
  42. }
  43. err = exec.Command(ping, "-c", "1", "-w", "3", dstIP.String()).Run()
  44. default:
  45. ping := "ping"
  46. if isSynology {
  47. ping = "/bin/ping"
  48. }
  49. cmd := exec.Command(ping, "-c", "1", "-W", "3", dstIP.String())
  50. if isSynology && os.Getuid() != 0 {
  51. // On DSM7 we run as non-root and need to pass
  52. // CAP_NET_RAW if our binary has it.
  53. setAmbientCapsRaw(cmd)
  54. }
  55. err = cmd.Run()
  56. }
  57. return err
  58. }