interfaces.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package interfaces contains helpers for looking up system network interfaces.
  4. package interfaces
  5. import (
  6. "bytes"
  7. "fmt"
  8. "net"
  9. "net/http"
  10. "net/netip"
  11. "runtime"
  12. "slices"
  13. "sort"
  14. "strings"
  15. "tailscale.com/hostinfo"
  16. "tailscale.com/net/netaddr"
  17. "tailscale.com/net/tsaddr"
  18. "tailscale.com/net/tshttpproxy"
  19. )
  20. // LoginEndpointForProxyDetermination is the URL used for testing
  21. // which HTTP proxy the system should use.
  22. var LoginEndpointForProxyDetermination = "https://controlplane.tailscale.com/"
  23. func isUp(nif *net.Interface) bool { return nif.Flags&net.FlagUp != 0 }
  24. func isLoopback(nif *net.Interface) bool { return nif.Flags&net.FlagLoopback != 0 }
  25. func isProblematicInterface(nif *net.Interface) bool {
  26. name := nif.Name
  27. // Don't try to send disco/etc packets over zerotier; they effectively
  28. // DoS each other by doing traffic amplification, both of them
  29. // preferring/trying to use each other for transport. See:
  30. // https://github.com/tailscale/tailscale/issues/1208
  31. if strings.HasPrefix(name, "zt") || (runtime.GOOS == "windows" && strings.Contains(name, "ZeroTier")) {
  32. return true
  33. }
  34. return false
  35. }
  36. // LocalAddresses returns the machine's IP addresses, separated by
  37. // whether they're loopback addresses. If there are no regular addresses
  38. // it will return any IPv4 linklocal or IPv6 unique local addresses because we
  39. // know of environments where these are used with NAT to provide connectivity.
  40. func LocalAddresses() (regular, loopback []netip.Addr, err error) {
  41. // TODO(crawshaw): don't serve interface addresses that we are routing
  42. ifaces, err := netInterfaces()
  43. if err != nil {
  44. return nil, nil, err
  45. }
  46. var regular4, regular6, linklocal4, ula6 []netip.Addr
  47. for _, iface := range ifaces {
  48. stdIf := iface.Interface
  49. if !isUp(stdIf) || isProblematicInterface(stdIf) {
  50. // Skip down interfaces and ones that are
  51. // problematic that we don't want to try to
  52. // send Tailscale traffic over.
  53. continue
  54. }
  55. ifcIsLoopback := isLoopback(stdIf)
  56. addrs, err := iface.Addrs()
  57. if err != nil {
  58. return nil, nil, err
  59. }
  60. for _, a := range addrs {
  61. switch v := a.(type) {
  62. case *net.IPNet:
  63. ip, ok := netip.AddrFromSlice(v.IP)
  64. if !ok {
  65. continue
  66. }
  67. ip = ip.Unmap()
  68. // TODO(apenwarr): don't special case cgNAT.
  69. // In the general wireguard case, it might
  70. // very well be something we can route to
  71. // directly, because both nodes are
  72. // behind the same CGNAT router.
  73. if tsaddr.IsTailscaleIP(ip) {
  74. continue
  75. }
  76. if ip.IsLoopback() || ifcIsLoopback {
  77. loopback = append(loopback, ip)
  78. } else if ip.IsLinkLocalUnicast() {
  79. if ip.Is4() {
  80. linklocal4 = append(linklocal4, ip)
  81. }
  82. // We know of no cases where the IPv6 fe80:: addresses
  83. // are used to provide WAN connectivity. It is also very
  84. // common for users to have no IPv6 WAN connectivity,
  85. // but their OS supports IPv6 so they have an fe80::
  86. // address. We don't want to report all of those
  87. // IPv6 LL to Control.
  88. } else if ip.Is6() && ip.IsPrivate() {
  89. // Google Cloud Run uses NAT with IPv6 Unique
  90. // Local Addresses to provide IPv6 connectivity.
  91. ula6 = append(ula6, ip)
  92. } else {
  93. if ip.Is4() {
  94. regular4 = append(regular4, ip)
  95. } else {
  96. regular6 = append(regular6, ip)
  97. }
  98. }
  99. }
  100. }
  101. }
  102. if len(regular4) == 0 && len(regular6) == 0 {
  103. // if we have no usable IP addresses then be willing to accept
  104. // addresses we otherwise wouldn't, like:
  105. // + 169.254.x.x (AWS Lambda and Azure App Services use NAT with these)
  106. // + IPv6 ULA (Google Cloud Run uses these with address translation)
  107. regular4 = linklocal4
  108. regular6 = ula6
  109. }
  110. regular = append(regular4, regular6...)
  111. sortIPs(regular)
  112. sortIPs(loopback)
  113. return regular, loopback, nil
  114. }
  115. func sortIPs(s []netip.Addr) {
  116. sort.Slice(s, func(i, j int) bool { return s[i].Less(s[j]) })
  117. }
  118. // Interface is a wrapper around Go's net.Interface with some extra methods.
  119. type Interface struct {
  120. *net.Interface
  121. AltAddrs []net.Addr // if non-nil, returned by Addrs
  122. Desc string // extra description (used on Windows)
  123. }
  124. func (i Interface) IsLoopback() bool { return isLoopback(i.Interface) }
  125. func (i Interface) IsUp() bool { return isUp(i.Interface) }
  126. func (i Interface) Addrs() ([]net.Addr, error) {
  127. if i.AltAddrs != nil {
  128. return i.AltAddrs, nil
  129. }
  130. return i.Interface.Addrs()
  131. }
  132. // ForeachInterfaceAddress is a wrapper for GetList, then
  133. // List.ForeachInterfaceAddress.
  134. func ForeachInterfaceAddress(fn func(Interface, netip.Prefix)) error {
  135. ifaces, err := GetList()
  136. if err != nil {
  137. return err
  138. }
  139. return ifaces.ForeachInterfaceAddress(fn)
  140. }
  141. // ForeachInterfaceAddress calls fn for each interface in ifaces, with
  142. // all its addresses. The IPPrefix's IP is the IP address assigned to
  143. // the interface, and Bits are the subnet mask.
  144. func (ifaces List) ForeachInterfaceAddress(fn func(Interface, netip.Prefix)) error {
  145. for _, iface := range ifaces {
  146. addrs, err := iface.Addrs()
  147. if err != nil {
  148. return err
  149. }
  150. for _, a := range addrs {
  151. switch v := a.(type) {
  152. case *net.IPNet:
  153. if pfx, ok := netaddr.FromStdIPNet(v); ok {
  154. fn(iface, pfx)
  155. }
  156. }
  157. }
  158. }
  159. return nil
  160. }
  161. // ForeachInterface is a wrapper for GetList, then
  162. // List.ForeachInterface.
  163. func ForeachInterface(fn func(Interface, []netip.Prefix)) error {
  164. ifaces, err := GetList()
  165. if err != nil {
  166. return err
  167. }
  168. return ifaces.ForeachInterface(fn)
  169. }
  170. // ForeachInterface calls fn for each interface in ifaces, with
  171. // all its addresses. The IPPrefix's IP is the IP address assigned to
  172. // the interface, and Bits are the subnet mask.
  173. func (ifaces List) ForeachInterface(fn func(Interface, []netip.Prefix)) error {
  174. for _, iface := range ifaces {
  175. addrs, err := iface.Addrs()
  176. if err != nil {
  177. return err
  178. }
  179. var pfxs []netip.Prefix
  180. for _, a := range addrs {
  181. switch v := a.(type) {
  182. case *net.IPNet:
  183. if pfx, ok := netaddr.FromStdIPNet(v); ok {
  184. pfxs = append(pfxs, pfx)
  185. }
  186. }
  187. }
  188. sort.Slice(pfxs, func(i, j int) bool {
  189. return pfxs[i].Addr().Less(pfxs[j].Addr())
  190. })
  191. fn(iface, pfxs)
  192. }
  193. return nil
  194. }
  195. // State is intended to store the state of the machine's network interfaces,
  196. // routing table, and other network configuration.
  197. // For now it's pretty basic.
  198. type State struct {
  199. // InterfaceIPs maps from an interface name to the IP addresses
  200. // configured on that interface. Each address is represented as an
  201. // IPPrefix, where the IP is the interface IP address and Bits is
  202. // the subnet mask.
  203. InterfaceIPs map[string][]netip.Prefix
  204. Interface map[string]Interface
  205. // HaveV6 is whether this machine has an IPv6 Global or Unique Local Address
  206. // which might provide connectivity on a non-Tailscale interface that's up.
  207. HaveV6 bool
  208. // HaveV4 is whether the machine has some non-localhost,
  209. // non-link-local IPv4 address on a non-Tailscale interface that's up.
  210. HaveV4 bool
  211. // IsExpensive is whether the current network interface is
  212. // considered "expensive", which currently means LTE/etc
  213. // instead of Wifi. This field is not populated by GetState.
  214. IsExpensive bool
  215. // DefaultRouteInterface is the interface name for the
  216. // machine's default route.
  217. //
  218. // It is not yet populated on all OSes.
  219. //
  220. // When non-empty, its value is the map key into Interface and
  221. // InterfaceIPs.
  222. DefaultRouteInterface string
  223. // HTTPProxy is the HTTP proxy to use, if any.
  224. HTTPProxy string
  225. // PAC is the URL to the Proxy Autoconfig URL, if applicable.
  226. PAC string
  227. }
  228. func (s *State) String() string {
  229. var sb strings.Builder
  230. fmt.Fprintf(&sb, "interfaces.State{defaultRoute=%v ", s.DefaultRouteInterface)
  231. if s.DefaultRouteInterface != "" {
  232. if iface, ok := s.Interface[s.DefaultRouteInterface]; ok && iface.Desc != "" {
  233. fmt.Fprintf(&sb, "(%s) ", iface.Desc)
  234. }
  235. }
  236. sb.WriteString("ifs={")
  237. var ifs []string
  238. for k := range s.Interface {
  239. if s.keepInterfaceInStringSummary(k) {
  240. ifs = append(ifs, k)
  241. }
  242. }
  243. sort.Slice(ifs, func(i, j int) bool {
  244. upi, upj := s.Interface[ifs[i]].IsUp(), s.Interface[ifs[j]].IsUp()
  245. if upi != upj {
  246. // Up sorts before down.
  247. return upi
  248. }
  249. return ifs[i] < ifs[j]
  250. })
  251. for i, ifName := range ifs {
  252. if i > 0 {
  253. sb.WriteString(" ")
  254. }
  255. iface := s.Interface[ifName]
  256. if iface.Interface == nil {
  257. fmt.Fprintf(&sb, "%s:nil", ifName)
  258. continue
  259. }
  260. if !iface.IsUp() {
  261. fmt.Fprintf(&sb, "%s:down", ifName)
  262. continue
  263. }
  264. fmt.Fprintf(&sb, "%s:[", ifName)
  265. needSpace := false
  266. for _, pfx := range s.InterfaceIPs[ifName] {
  267. a := pfx.Addr()
  268. if a.IsMulticast() {
  269. continue
  270. }
  271. fam := "4"
  272. if a.Is6() {
  273. fam = "6"
  274. }
  275. if needSpace {
  276. sb.WriteString(" ")
  277. }
  278. needSpace = true
  279. switch {
  280. case a.IsLoopback():
  281. fmt.Fprintf(&sb, "lo%s", fam)
  282. case a.IsLinkLocalUnicast():
  283. fmt.Fprintf(&sb, "llu%s", fam)
  284. default:
  285. fmt.Fprintf(&sb, "%s", pfx)
  286. }
  287. }
  288. sb.WriteString("]")
  289. }
  290. sb.WriteString("}")
  291. if s.IsExpensive {
  292. sb.WriteString(" expensive")
  293. }
  294. if s.HTTPProxy != "" {
  295. fmt.Fprintf(&sb, " httpproxy=%s", s.HTTPProxy)
  296. }
  297. if s.PAC != "" {
  298. fmt.Fprintf(&sb, " pac=%s", s.PAC)
  299. }
  300. fmt.Fprintf(&sb, " v4=%v v6=%v}", s.HaveV4, s.HaveV6)
  301. return sb.String()
  302. }
  303. // Equal reports whether s and s2 are exactly equal.
  304. func (s *State) Equal(s2 *State) bool {
  305. if s == nil && s2 == nil {
  306. return true
  307. }
  308. if s == nil || s2 == nil {
  309. return false
  310. }
  311. if s.HaveV6 != s2.HaveV6 ||
  312. s.HaveV4 != s2.HaveV4 ||
  313. s.IsExpensive != s2.IsExpensive ||
  314. s.DefaultRouteInterface != s2.DefaultRouteInterface ||
  315. s.HTTPProxy != s2.HTTPProxy ||
  316. s.PAC != s2.PAC {
  317. return false
  318. }
  319. for iname, i := range s.Interface {
  320. i2, ok := s2.Interface[iname]
  321. if !ok {
  322. return false
  323. }
  324. if !i.Equal(i2) {
  325. return false
  326. }
  327. }
  328. for iname, vv := range s.InterfaceIPs {
  329. if !slices.Equal(vv, s2.InterfaceIPs[iname]) {
  330. return false
  331. }
  332. }
  333. return true
  334. }
  335. // HasIP reports whether any interface has the provided IP address.
  336. func (s *State) HasIP(ip netip.Addr) bool {
  337. if s == nil {
  338. return false
  339. }
  340. for _, pv := range s.InterfaceIPs {
  341. for _, p := range pv {
  342. if p.Contains(ip) {
  343. return true
  344. }
  345. }
  346. }
  347. return false
  348. }
  349. func (a Interface) Equal(b Interface) bool {
  350. if (a.Interface == nil) != (b.Interface == nil) {
  351. return false
  352. }
  353. if !(a.Desc == b.Desc && netAddrsEqual(a.AltAddrs, b.AltAddrs)) {
  354. return false
  355. }
  356. if a.Interface != nil && !(a.Index == b.Index &&
  357. a.MTU == b.MTU &&
  358. a.Name == b.Name &&
  359. a.Flags == b.Flags &&
  360. bytes.Equal([]byte(a.HardwareAddr), []byte(b.HardwareAddr))) {
  361. return false
  362. }
  363. return true
  364. }
  365. func (s *State) HasPAC() bool { return s != nil && s.PAC != "" }
  366. // AnyInterfaceUp reports whether any interface seems like it has Internet access.
  367. func (s *State) AnyInterfaceUp() bool {
  368. if runtime.GOOS == "js" || runtime.GOOS == "tamago" {
  369. return true
  370. }
  371. return s != nil && (s.HaveV4 || s.HaveV6)
  372. }
  373. func netAddrsEqual(a, b []net.Addr) bool {
  374. if len(a) != len(b) {
  375. return false
  376. }
  377. for i, av := range a {
  378. if av.Network() != b[i].Network() || av.String() != b[i].String() {
  379. return false
  380. }
  381. }
  382. return true
  383. }
  384. func hasTailscaleIP(pfxs []netip.Prefix) bool {
  385. for _, pfx := range pfxs {
  386. if tsaddr.IsTailscaleIP(pfx.Addr()) {
  387. return true
  388. }
  389. }
  390. return false
  391. }
  392. func isTailscaleInterface(name string, ips []netip.Prefix) bool {
  393. if runtime.GOOS == "darwin" && strings.HasPrefix(name, "utun") && hasTailscaleIP(ips) {
  394. // On macOS in the sandboxed app (at least as of
  395. // 2021-02-25), we often see two utun devices
  396. // (e.g. utun4 and utun7) with the same IPv4 and IPv6
  397. // addresses. Just remove all utun devices with
  398. // Tailscale IPs until we know what's happening with
  399. // macOS NetworkExtensions and utun devices.
  400. return true
  401. }
  402. return name == "Tailscale" || // as it is on Windows
  403. strings.HasPrefix(name, "tailscale") // TODO: use --tun flag value, etc; see TODO in method doc
  404. }
  405. // getPAC, if non-nil, returns the current PAC file URL.
  406. var getPAC func() string
  407. // GetState returns the state of all the current machine's network interfaces.
  408. //
  409. // It does not set the returned State.IsExpensive. The caller can populate that.
  410. //
  411. // Deprecated: use netmon.Monitor.InterfaceState instead.
  412. func GetState() (*State, error) {
  413. s := &State{
  414. InterfaceIPs: make(map[string][]netip.Prefix),
  415. Interface: make(map[string]Interface),
  416. }
  417. if err := ForeachInterface(func(ni Interface, pfxs []netip.Prefix) {
  418. ifUp := ni.IsUp()
  419. s.Interface[ni.Name] = ni
  420. s.InterfaceIPs[ni.Name] = append(s.InterfaceIPs[ni.Name], pfxs...)
  421. if !ifUp || isTailscaleInterface(ni.Name, pfxs) {
  422. return
  423. }
  424. for _, pfx := range pfxs {
  425. if pfx.Addr().IsLoopback() {
  426. continue
  427. }
  428. s.HaveV6 = s.HaveV6 || isUsableV6(pfx.Addr())
  429. s.HaveV4 = s.HaveV4 || isUsableV4(pfx.Addr())
  430. }
  431. }); err != nil {
  432. return nil, err
  433. }
  434. dr, _ := DefaultRoute()
  435. s.DefaultRouteInterface = dr.InterfaceName
  436. // Populate description (for Windows, primarily) if present.
  437. if desc := dr.InterfaceDesc; desc != "" {
  438. if iface, ok := s.Interface[dr.InterfaceName]; ok {
  439. iface.Desc = desc
  440. s.Interface[dr.InterfaceName] = iface
  441. }
  442. }
  443. if s.AnyInterfaceUp() {
  444. req, err := http.NewRequest("GET", LoginEndpointForProxyDetermination, nil)
  445. if err != nil {
  446. return nil, err
  447. }
  448. if u, err := tshttpproxy.ProxyFromEnvironment(req); err == nil && u != nil {
  449. s.HTTPProxy = u.String()
  450. }
  451. if getPAC != nil {
  452. s.PAC = getPAC()
  453. }
  454. }
  455. return s, nil
  456. }
  457. // HTTPOfListener returns the HTTP address to ln.
  458. // If the listener is listening on the unspecified address, it
  459. // it tries to find a reasonable interface address on the machine to use.
  460. func HTTPOfListener(ln net.Listener) string {
  461. ta, ok := ln.Addr().(*net.TCPAddr)
  462. if !ok || !ta.IP.IsUnspecified() {
  463. return fmt.Sprintf("http://%v/", ln.Addr())
  464. }
  465. var goodIP string
  466. var privateIP string
  467. ForeachInterfaceAddress(func(i Interface, pfx netip.Prefix) {
  468. ip := pfx.Addr()
  469. if ip.IsPrivate() {
  470. if privateIP == "" {
  471. privateIP = ip.String()
  472. }
  473. return
  474. }
  475. goodIP = ip.String()
  476. })
  477. if privateIP != "" {
  478. goodIP = privateIP
  479. }
  480. if goodIP != "" {
  481. return fmt.Sprintf("http://%v/", net.JoinHostPort(goodIP, fmt.Sprint(ta.Port)))
  482. }
  483. return fmt.Sprintf("http://localhost:%v/", fmt.Sprint(ta.Port))
  484. }
  485. var likelyHomeRouterIP func() (netip.Addr, bool)
  486. // LikelyHomeRouterIP returns the likely IP of the residential router,
  487. // which will always be an IPv4 private address, if found.
  488. // In addition, it returns the IP address of the current machine on
  489. // the LAN using that gateway.
  490. // This is used as the destination for UPnP, NAT-PMP, PCP, etc queries.
  491. func LikelyHomeRouterIP() (gateway, myIP netip.Addr, ok bool) {
  492. if likelyHomeRouterIP != nil {
  493. gateway, ok = likelyHomeRouterIP()
  494. if !ok {
  495. return
  496. }
  497. }
  498. if !ok {
  499. return
  500. }
  501. ForeachInterfaceAddress(func(i Interface, pfx netip.Prefix) {
  502. if !i.IsUp() {
  503. // Skip interfaces that aren't up.
  504. return
  505. } else if myIP.IsValid() {
  506. // We already have a valid self IP; skip this one.
  507. return
  508. }
  509. ip := pfx.Addr()
  510. if !ip.IsValid() || !ip.Is4() {
  511. // Skip IPs that aren't valid or aren't IPv4, since we
  512. // always return an IPv4 address.
  513. return
  514. }
  515. if gateway.IsPrivate() && ip.IsPrivate() {
  516. myIP = ip
  517. ok = true
  518. return
  519. }
  520. })
  521. return gateway, myIP, myIP.IsValid()
  522. }
  523. // isUsableV4 reports whether ip is a usable IPv4 address which could
  524. // conceivably be used to get Internet connectivity. Globally routable and
  525. // private IPv4 addresses are always Usable, and link local 169.254.x.x
  526. // addresses are in some environments.
  527. func isUsableV4(ip netip.Addr) bool {
  528. if !ip.Is4() || ip.IsLoopback() {
  529. return false
  530. }
  531. if ip.IsLinkLocalUnicast() {
  532. switch hostinfo.GetEnvType() {
  533. case hostinfo.AWSLambda:
  534. return true
  535. case hostinfo.AzureAppService:
  536. return true
  537. default:
  538. return false
  539. }
  540. }
  541. return true
  542. }
  543. // isUsableV6 reports whether ip is a usable IPv6 address which could
  544. // conceivably be used to get Internet connectivity. Globally routable
  545. // IPv6 addresses are always Usable, and Unique Local Addresses
  546. // (fc00::/7) are in some environments used with address translation.
  547. func isUsableV6(ip netip.Addr) bool {
  548. return v6Global1.Contains(ip) ||
  549. (ip.Is6() && ip.IsPrivate() && !tsaddr.TailscaleULARange().Contains(ip))
  550. }
  551. var (
  552. v6Global1 = netip.MustParsePrefix("2000::/3")
  553. )
  554. // keepInterfaceInStringSummary reports whether the named interface should be included
  555. // in the String method's summary string.
  556. func (s *State) keepInterfaceInStringSummary(ifName string) bool {
  557. iface, ok := s.Interface[ifName]
  558. if !ok || iface.Interface == nil {
  559. return false
  560. }
  561. if ifName == s.DefaultRouteInterface {
  562. return true
  563. }
  564. up := iface.IsUp()
  565. for _, p := range s.InterfaceIPs[ifName] {
  566. a := p.Addr()
  567. if a.IsLinkLocalUnicast() || a.IsLoopback() {
  568. continue
  569. }
  570. if up || a.IsGlobalUnicast() || a.IsPrivate() {
  571. return true
  572. }
  573. }
  574. return false
  575. }
  576. // isInterestingIP reports whether ip is an interesting IP that we
  577. // should log in interfaces.State logging. We don't need to show
  578. // loopback, link-local addresses, or non-Tailscale ULA addresses.
  579. func isInterestingIP(ip netip.Addr) bool {
  580. if ip.IsLoopback() || ip.IsLinkLocalUnicast() {
  581. return false
  582. }
  583. return true
  584. }
  585. var altNetInterfaces func() ([]Interface, error)
  586. // RegisterInterfaceGetter sets the function that's used to query
  587. // the system network interfaces.
  588. func RegisterInterfaceGetter(getInterfaces func() ([]Interface, error)) {
  589. altNetInterfaces = getInterfaces
  590. }
  591. // List is a list of interfaces on the machine.
  592. type List []Interface
  593. // GetList returns the list of interfaces on the machine.
  594. func GetList() (List, error) {
  595. return netInterfaces()
  596. }
  597. // netInterfaces is a wrapper around the standard library's net.Interfaces
  598. // that returns a []*Interface instead of a []net.Interface.
  599. // It exists because Android SDK 30 no longer permits Go's net.Interfaces
  600. // to work (Issue 2293); this wrapper lets us the Android app register
  601. // an alternate implementation.
  602. func netInterfaces() ([]Interface, error) {
  603. if altNetInterfaces != nil {
  604. return altNetInterfaces()
  605. }
  606. ifs, err := net.Interfaces()
  607. if err != nil {
  608. return nil, err
  609. }
  610. ret := make([]Interface, len(ifs))
  611. for i := range ifs {
  612. ret[i].Interface = &ifs[i]
  613. }
  614. return ret, nil
  615. }
  616. // DefaultRouteDetails are the details about a default route returned
  617. // by DefaultRoute.
  618. type DefaultRouteDetails struct {
  619. // InterfaceName is the interface name. It must always be populated.
  620. // It's like "eth0" (Linux), "Ethernet 2" (Windows), "en0" (macOS).
  621. InterfaceName string
  622. // InterfaceDesc is populated on Windows at least. It's a
  623. // longer description, like "Red Hat VirtIO Ethernet Adapter".
  624. InterfaceDesc string
  625. // InterfaceIndex is like net.Interface.Index.
  626. // Zero means not populated.
  627. InterfaceIndex int
  628. // TODO(bradfitz): break this out into v4-vs-v6 once that need arises.
  629. }
  630. // DefaultRouteInterface is like DefaultRoute but only returns the
  631. // interface name.
  632. func DefaultRouteInterface() (string, error) {
  633. dr, err := DefaultRoute()
  634. if err != nil {
  635. return "", err
  636. }
  637. return dr.InterfaceName, nil
  638. }
  639. // DefaultRoute returns details of the network interface that owns
  640. // the default route, not including any tailscale interfaces.
  641. func DefaultRoute() (DefaultRouteDetails, error) {
  642. return defaultRoute()
  643. }
  644. // HasCGNATInterface reports whether there are any non-Tailscale interfaces that
  645. // use a CGNAT IP range.
  646. func HasCGNATInterface() (bool, error) {
  647. hasCGNATInterface := false
  648. cgnatRange := tsaddr.CGNATRange()
  649. err := ForeachInterface(func(i Interface, pfxs []netip.Prefix) {
  650. if hasCGNATInterface || !i.IsUp() || isTailscaleInterface(i.Name, pfxs) {
  651. return
  652. }
  653. for _, pfx := range pfxs {
  654. if cgnatRange.Overlaps(pfx) {
  655. hasCGNATInterface = true
  656. break
  657. }
  658. }
  659. })
  660. if err != nil {
  661. return false, err
  662. }
  663. return hasCGNATInterface, nil
  664. }
  665. var interfaceDebugExtras func(ifIndex int) (string, error)
  666. // InterfaceDebugExtras returns extra debugging information about an interface
  667. // if any (an empty string will be returned if there are no additional details).
  668. // Formatting is platform-dependent and should not be parsed.
  669. func InterfaceDebugExtras(ifIndex int) (string, error) {
  670. if interfaceDebugExtras != nil {
  671. return interfaceDebugExtras(ifIndex)
  672. }
  673. return "", nil
  674. }