tsaddr.go 9.0 KB

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