netns.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package netns contains the common code for using the Go net package
  4. // in a logical "network namespace" to avoid routing loops where
  5. // Tailscale-created packets would otherwise loop back through
  6. // Tailscale routes.
  7. //
  8. // Despite the name netns, the exact mechanism used differs by
  9. // operating system, and perhaps even by version of the OS.
  10. //
  11. // The netns package also handles connecting via SOCKS proxies when
  12. // configured by the environment.
  13. package netns
  14. import (
  15. "context"
  16. "net"
  17. "net/netip"
  18. "sync/atomic"
  19. "tailscale.com/net/netknob"
  20. "tailscale.com/net/netmon"
  21. "tailscale.com/types/logger"
  22. )
  23. var disabled atomic.Bool
  24. // SetEnabled enables or disables netns for the process.
  25. // It defaults to being enabled.
  26. func SetEnabled(on bool) {
  27. disabled.Store(!on)
  28. }
  29. var bindToInterfaceByRoute atomic.Bool
  30. // SetBindToInterfaceByRoute enables or disables whether we use the system's
  31. // route information to bind to a particular interface. It is the same as
  32. // setting the TS_BIND_TO_INTERFACE_BY_ROUTE.
  33. //
  34. // Currently, this only changes the behaviour on macOS.
  35. func SetBindToInterfaceByRoute(v bool) {
  36. bindToInterfaceByRoute.Store(v)
  37. }
  38. var disableBindConnToInterface atomic.Bool
  39. // SetDisableBindConnToInterface disables the (normal) behavior of binding
  40. // connections to the default network interface.
  41. //
  42. // Currently, this only has an effect on Darwin.
  43. func SetDisableBindConnToInterface(v bool) {
  44. disableBindConnToInterface.Store(v)
  45. }
  46. // Listener returns a new net.Listener with its Control hook func
  47. // initialized as necessary to run in logical network namespace that
  48. // doesn't route back into Tailscale.
  49. // The netMon parameter is optional; if non-nil it's used to do faster interface lookups.
  50. func Listener(logf logger.Logf, netMon *netmon.Monitor) *net.ListenConfig {
  51. if disabled.Load() {
  52. return new(net.ListenConfig)
  53. }
  54. return &net.ListenConfig{Control: control(logf, netMon)}
  55. }
  56. // NewDialer returns a new Dialer using a net.Dialer with its Control
  57. // hook func initialized as necessary to run in a logical network
  58. // namespace that doesn't route back into Tailscale. It also handles
  59. // using a SOCKS if configured in the environment with ALL_PROXY.
  60. // The netMon parameter is optional; if non-nil it's used to do faster interface lookups.
  61. func NewDialer(logf logger.Logf, netMon *netmon.Monitor) Dialer {
  62. return FromDialer(logf, netMon, &net.Dialer{
  63. KeepAlive: netknob.PlatformTCPKeepAlive(),
  64. })
  65. }
  66. // FromDialer returns sets d.Control as necessary to run in a logical
  67. // network namespace that doesn't route back into Tailscale. It also
  68. // handles using a SOCKS if configured in the environment with
  69. // ALL_PROXY.
  70. // The netMon parameter is optional; if non-nil it's used to do faster interface lookups.
  71. func FromDialer(logf logger.Logf, netMon *netmon.Monitor, d *net.Dialer) Dialer {
  72. if disabled.Load() {
  73. return d
  74. }
  75. d.Control = control(logf, netMon)
  76. if wrapDialer != nil {
  77. return wrapDialer(d)
  78. }
  79. return d
  80. }
  81. // IsSOCKSDialer reports whether d is SOCKS-proxying dialer as returned by
  82. // NewDialer or FromDialer.
  83. func IsSOCKSDialer(d Dialer) bool {
  84. if d == nil {
  85. return false
  86. }
  87. _, ok := d.(*net.Dialer)
  88. return !ok
  89. }
  90. // wrapDialer, if non-nil, specifies a function to wrap a dialer in a
  91. // SOCKS-using dialer. It's set conditionally by socks.go.
  92. var wrapDialer func(Dialer) Dialer
  93. // Dialer is the interface for a dialer that can dial with or without a context.
  94. // It's the type implemented both by net.Dialer and the Go SOCKS dialer.
  95. type Dialer interface {
  96. Dial(network, address string) (net.Conn, error)
  97. DialContext(ctx context.Context, network, address string) (net.Conn, error)
  98. }
  99. func isLocalhost(addr string) bool {
  100. host, _, err := net.SplitHostPort(addr)
  101. if err != nil {
  102. // error means the string didn't contain a port number, so use the string directly
  103. host = addr
  104. }
  105. // localhost6 == RedHat /etc/hosts for ::1, ip6-loopback & ip6-localhost == Debian /etc/hosts for ::1
  106. if host == "localhost" || host == "localhost6" || host == "ip6-loopback" || host == "ip6-localhost" {
  107. return true
  108. }
  109. ip, _ := netip.ParseAddr(host)
  110. return ip.IsLoopback()
  111. }