tsaddr.go 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package tsaddr handles Tailscale-specific IPs and ranges.
  4. package tsaddr
  5. import (
  6. "encoding/binary"
  7. "errors"
  8. "net/netip"
  9. "slices"
  10. "sync"
  11. "go4.org/netipx"
  12. "tailscale.com/net/netaddr"
  13. "tailscale.com/types/views"
  14. )
  15. // ChromeOSVMRange returns the subset of the CGNAT IPv4 range used by
  16. // ChromeOS to interconnect the host OS to containers and VMs. We
  17. // avoid allocating Tailscale IPs from it, to avoid conflicts.
  18. func ChromeOSVMRange() netip.Prefix {
  19. chromeOSRange.Do(func() { mustPrefix(&chromeOSRange.v, "100.115.92.0/23") })
  20. return chromeOSRange.v
  21. }
  22. var chromeOSRange oncePrefix
  23. // CGNATRange returns the Carrier Grade NAT address range that
  24. // is the superset range that Tailscale assigns out of.
  25. // See https://tailscale.com/s/cgnat
  26. // Note that Tailscale does not assign out of the ChromeOSVMRange.
  27. func CGNATRange() netip.Prefix {
  28. cgnatRange.Do(func() { mustPrefix(&cgnatRange.v, "100.64.0.0/10") })
  29. return cgnatRange.v
  30. }
  31. var (
  32. cgnatRange oncePrefix
  33. tsUlaRange oncePrefix
  34. tsViaRange oncePrefix
  35. ula4To6Range oncePrefix
  36. ulaEph6Range oncePrefix
  37. serviceIPv6 oncePrefix
  38. )
  39. // TailscaleServiceIP returns the IPv4 listen address of services
  40. // provided by Tailscale itself such as the MagicDNS proxy.
  41. //
  42. // For IPv6, use TailscaleServiceIPv6.
  43. func TailscaleServiceIP() netip.Addr {
  44. return netaddr.IPv4(100, 100, 100, 100) // "100.100.100.100" for those grepping
  45. }
  46. // TailscaleServiceIPv6 returns the IPv6 listen address of the services
  47. // provided by Tailscale itself such as the MagicDNS proxy.
  48. //
  49. // For IPv4, use TailscaleServiceIP.
  50. func TailscaleServiceIPv6() netip.Addr {
  51. serviceIPv6.Do(func() { mustPrefix(&serviceIPv6.v, TailscaleServiceIPv6String+"/128") })
  52. return serviceIPv6.v.Addr()
  53. }
  54. const (
  55. TailscaleServiceIPString = "100.100.100.100"
  56. TailscaleServiceIPv6String = "fd7a:115c:a1e0::53"
  57. )
  58. // IsTailscaleIP reports whether ip is an IP address in a range that
  59. // Tailscale assigns from.
  60. func IsTailscaleIP(ip netip.Addr) bool {
  61. if ip.Is4() {
  62. return CGNATRange().Contains(ip) && !ChromeOSVMRange().Contains(ip)
  63. }
  64. return TailscaleULARange().Contains(ip)
  65. }
  66. // TailscaleULARange returns the IPv6 Unique Local Address range that
  67. // is the superset range that Tailscale assigns out of.
  68. func TailscaleULARange() netip.Prefix {
  69. tsUlaRange.Do(func() { mustPrefix(&tsUlaRange.v, "fd7a:115c:a1e0::/48") })
  70. return tsUlaRange.v
  71. }
  72. // TailscaleViaRange returns the IPv6 Unique Local Address subset range
  73. // TailscaleULARange that's used for IPv4 tunneling via IPv6.
  74. func TailscaleViaRange() netip.Prefix {
  75. // Mnemonic: "b1a" sounds like "via".
  76. tsViaRange.Do(func() { mustPrefix(&tsViaRange.v, "fd7a:115c:a1e0:b1a::/64") })
  77. return tsViaRange.v
  78. }
  79. // Tailscale4To6Range returns the subset of TailscaleULARange used for
  80. // auto-translated Tailscale ipv4 addresses.
  81. func Tailscale4To6Range() netip.Prefix {
  82. // This IP range has no significance, beyond being a subset of
  83. // TailscaleULARange. The bits from /48 to /104 were picked at
  84. // random.
  85. ula4To6Range.Do(func() { mustPrefix(&ula4To6Range.v, "fd7a:115c:a1e0:ab12:4843:cd96:6200::/104") })
  86. return ula4To6Range.v
  87. }
  88. // TailscaleEphemeral6Range returns the subset of TailscaleULARange
  89. // used for ephemeral IPv6-only Tailscale nodes.
  90. func TailscaleEphemeral6Range() netip.Prefix {
  91. // This IP range has no significance, beyond being a subset of
  92. // TailscaleULARange. The bits from /48 to /64 were picked at
  93. // random, with the only criterion being to not be the conflict
  94. // with the Tailscale4To6Range above.
  95. ulaEph6Range.Do(func() { mustPrefix(&ulaEph6Range.v, "fd7a:115c:a1e0:efe3::/64") })
  96. return ulaEph6Range.v
  97. }
  98. // Tailscale4To6Placeholder returns an IP address that can be used as
  99. // a source IP when one is required, but a netmap didn't provide
  100. // any. This address never gets allocated by the 4-to-6 algorithm in
  101. // control.
  102. //
  103. // Currently used to work around a Windows limitation when programming
  104. // IPv6 routes in corner cases.
  105. func Tailscale4To6Placeholder() netip.Addr {
  106. return Tailscale4To6Range().Addr()
  107. }
  108. // Tailscale4To6 returns a Tailscale IPv6 address that maps 1:1 to the
  109. // given Tailscale IPv4 address. Returns a zero IP if ipv4 isn't a
  110. // Tailscale IPv4 address.
  111. func Tailscale4To6(ipv4 netip.Addr) netip.Addr {
  112. if !ipv4.Is4() || !IsTailscaleIP(ipv4) {
  113. return netip.Addr{}
  114. }
  115. ret := Tailscale4To6Range().Addr().As16()
  116. v4 := ipv4.As4()
  117. copy(ret[13:], v4[1:])
  118. return netip.AddrFrom16(ret)
  119. }
  120. // Tailscale6to4 returns the IPv4 address corresponding to the given
  121. // tailscale IPv6 address within the 4To6 range. The IPv4 address
  122. // and true are returned if the given address was in the correct range,
  123. // false if not.
  124. func Tailscale6to4(ipv6 netip.Addr) (netip.Addr, bool) {
  125. if !ipv6.Is6() || !Tailscale4To6Range().Contains(ipv6) {
  126. return netip.Addr{}, false
  127. }
  128. v6 := ipv6.As16()
  129. return netip.AddrFrom4([4]byte{100, v6[13], v6[14], v6[15]}), true
  130. }
  131. func mustPrefix(v *netip.Prefix, prefix string) {
  132. var err error
  133. *v, err = netip.ParsePrefix(prefix)
  134. if err != nil {
  135. panic(err)
  136. }
  137. }
  138. type oncePrefix struct {
  139. sync.Once
  140. v netip.Prefix
  141. }
  142. // FalseContainsIPFunc is shorthand for NewContainsIPFunc(views.Slice[netip.Prefix]{}).
  143. func FalseContainsIPFunc() func(ip netip.Addr) bool {
  144. return func(ip netip.Addr) bool { return false }
  145. }
  146. // NewContainsIPFunc returns a func that reports whether ip is in addrs.
  147. //
  148. // It's optimized for the cases of addrs being empty and addrs
  149. // containing 1 or 2 single-IP prefixes (such as one IPv4 address and
  150. // one IPv6 address).
  151. //
  152. // Otherwise the implementation is somewhat slow.
  153. func NewContainsIPFunc(addrs views.Slice[netip.Prefix]) func(ip netip.Addr) bool {
  154. // Specialize the three common cases: no address, just IPv4
  155. // (or just IPv6), and both IPv4 and IPv6.
  156. if addrs.Len() == 0 {
  157. return func(netip.Addr) bool { return false }
  158. }
  159. // If any addr is more than a single IP, then just do the slow
  160. // linear thing until
  161. // https://github.com/inetaf/netaddr/issues/139 is done.
  162. if views.SliceContainsFunc(addrs, func(p netip.Prefix) bool { return !p.IsSingleIP() }) {
  163. acopy := addrs.AsSlice()
  164. return func(ip netip.Addr) bool {
  165. for _, a := range acopy {
  166. if a.Contains(ip) {
  167. return true
  168. }
  169. }
  170. return false
  171. }
  172. }
  173. // Fast paths for 1 and 2 IPs:
  174. if addrs.Len() == 1 {
  175. a := addrs.At(0)
  176. return func(ip netip.Addr) bool { return ip == a.Addr() }
  177. }
  178. if addrs.Len() == 2 {
  179. a, b := addrs.At(0), addrs.At(1)
  180. return func(ip netip.Addr) bool { return ip == a.Addr() || ip == b.Addr() }
  181. }
  182. // General case:
  183. m := map[netip.Addr]bool{}
  184. for i := range addrs.LenIter() {
  185. m[addrs.At(i).Addr()] = true
  186. }
  187. return func(ip netip.Addr) bool { return m[ip] }
  188. }
  189. // PrefixesContainsIP reports whether any prefix in ipp contains ip.
  190. func PrefixesContainsIP(ipp []netip.Prefix, ip netip.Addr) bool {
  191. for _, r := range ipp {
  192. if r.Contains(ip) {
  193. return true
  194. }
  195. }
  196. return false
  197. }
  198. // PrefixIs4 reports whether p is an IPv4 prefix.
  199. func PrefixIs4(p netip.Prefix) bool { return p.Addr().Is4() }
  200. // PrefixIs6 reports whether p is an IPv6 prefix.
  201. func PrefixIs6(p netip.Prefix) bool { return p.Addr().Is6() }
  202. // ContainsExitRoutes reports whether rr contains both the IPv4 and
  203. // IPv6 /0 route.
  204. func ContainsExitRoutes(rr views.Slice[netip.Prefix]) bool {
  205. var v4, v6 bool
  206. for i := range rr.LenIter() {
  207. r := rr.At(i)
  208. if r == allIPv4 {
  209. v4 = true
  210. } else if r == allIPv6 {
  211. v6 = true
  212. }
  213. }
  214. return v4 && v6
  215. }
  216. // ContainsNonExitSubnetRoutes reports whether v contains Subnet
  217. // Routes other than ExitNode Routes.
  218. func ContainsNonExitSubnetRoutes(rr views.Slice[netip.Prefix]) bool {
  219. for i := range rr.LenIter() {
  220. if rr.At(i).Bits() != 0 {
  221. return true
  222. }
  223. }
  224. return false
  225. }
  226. var (
  227. allIPv4 = netip.MustParsePrefix("0.0.0.0/0")
  228. allIPv6 = netip.MustParsePrefix("::/0")
  229. )
  230. // AllIPv4 returns 0.0.0.0/0.
  231. func AllIPv4() netip.Prefix { return allIPv4 }
  232. // AllIPv6 returns ::/0.
  233. func AllIPv6() netip.Prefix { return allIPv6 }
  234. // ExitRoutes returns a slice containing AllIPv4 and AllIPv6.
  235. func ExitRoutes() []netip.Prefix { return []netip.Prefix{allIPv4, allIPv6} }
  236. // SortPrefixes sorts the prefixes in place.
  237. func SortPrefixes(p []netip.Prefix) {
  238. slices.SortFunc(p, netipx.ComparePrefix)
  239. }
  240. // FilterPrefixes returns a new slice, not aliasing in, containing elements of
  241. // in that match f.
  242. func FilterPrefixesCopy(in views.Slice[netip.Prefix], f func(netip.Prefix) bool) []netip.Prefix {
  243. var out []netip.Prefix
  244. for i := range in.LenIter() {
  245. if v := in.At(i); f(v) {
  246. out = append(out, v)
  247. }
  248. }
  249. return out
  250. }
  251. // IsViaPrefix reports whether p is a CIDR in the Tailscale "via" range.
  252. // See TailscaleViaRange.
  253. func IsViaPrefix(p netip.Prefix) bool {
  254. return TailscaleViaRange().Contains(p.Addr())
  255. }
  256. // UnmapVia returns the IPv4 address that corresponds to the provided Tailscale
  257. // "via" IPv4-in-IPv6 address.
  258. //
  259. // If ip is not a via address, it returns ip unchanged.
  260. func UnmapVia(ip netip.Addr) netip.Addr {
  261. if TailscaleViaRange().Contains(ip) {
  262. a := ip.As16()
  263. return netip.AddrFrom4(*(*[4]byte)(a[12:16]))
  264. }
  265. return ip
  266. }
  267. // MapVia returns an IPv6 "via" route for an IPv4 CIDR in a given siteID.
  268. func MapVia(siteID uint32, v4 netip.Prefix) (via netip.Prefix, err error) {
  269. if !v4.Addr().Is4() {
  270. return via, errors.New("want IPv4 CIDR with a site ID")
  271. }
  272. viaRange16 := TailscaleViaRange().Addr().As16()
  273. var a [16]byte
  274. copy(a[:], viaRange16[:8])
  275. binary.BigEndian.PutUint32(a[8:], siteID)
  276. ip4a := v4.Addr().As4()
  277. copy(a[12:], ip4a[:])
  278. return netip.PrefixFrom(netip.AddrFrom16(a), v4.Bits()+64+32), nil
  279. }