peerapi.go 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package ipnlocal
  4. import (
  5. "context"
  6. "encoding/base64"
  7. "encoding/json"
  8. "errors"
  9. "fmt"
  10. "hash/crc32"
  11. "html"
  12. "io"
  13. "net"
  14. "net/http"
  15. "net/netip"
  16. "os"
  17. "runtime"
  18. "slices"
  19. "strconv"
  20. "strings"
  21. "sync"
  22. "time"
  23. "golang.org/x/net/dns/dnsmessage"
  24. "golang.org/x/net/http/httpguts"
  25. "tailscale.com/envknob"
  26. "tailscale.com/feature"
  27. "tailscale.com/feature/buildfeatures"
  28. "tailscale.com/health"
  29. "tailscale.com/hostinfo"
  30. "tailscale.com/net/netaddr"
  31. "tailscale.com/net/netmon"
  32. "tailscale.com/net/netutil"
  33. "tailscale.com/net/sockstats"
  34. "tailscale.com/tailcfg"
  35. "tailscale.com/types/netmap"
  36. "tailscale.com/types/views"
  37. "tailscale.com/util/clientmetric"
  38. "tailscale.com/wgengine/filter"
  39. )
  40. var initListenConfig func(*net.ListenConfig, netip.Addr, *netmon.State, string) error
  41. // peerDNSQueryHandler is implemented by tsdns.Resolver.
  42. type peerDNSQueryHandler interface {
  43. HandlePeerDNSQuery(context.Context, []byte, netip.AddrPort, func(name string) bool) (res []byte, err error)
  44. }
  45. type peerAPIServer struct {
  46. b *LocalBackend
  47. resolver peerDNSQueryHandler
  48. }
  49. func (s *peerAPIServer) listen(ip netip.Addr, ifState *netmon.State) (ln net.Listener, err error) {
  50. // Android for whatever reason often has problems creating the peerapi listener.
  51. // But since we started intercepting it with netstack, it's not even important that
  52. // we have a real kernel-level listener. So just create a dummy listener on Android
  53. // and let netstack intercept it.
  54. if runtime.GOOS == "android" {
  55. return newFakePeerAPIListener(ip), nil
  56. }
  57. ipStr := ip.String()
  58. var lc net.ListenConfig
  59. if initListenConfig != nil {
  60. // On iOS/macOS, this sets the lc.Control hook to
  61. // setsockopt the interface index to bind to, to get
  62. // out of the network sandbox.
  63. if err := initListenConfig(&lc, ip, ifState, s.b.dialer.TUNName()); err != nil {
  64. return nil, err
  65. }
  66. if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
  67. ipStr = ""
  68. }
  69. }
  70. if s.b.sys.IsNetstack() {
  71. ipStr = ""
  72. }
  73. tcp4or6 := "tcp4"
  74. if ip.Is6() {
  75. tcp4or6 = "tcp6"
  76. }
  77. // Make a best effort to pick a deterministic port number for
  78. // the ip. The lower three bytes are the same for IPv4 and IPv6
  79. // Tailscale addresses (at least currently), so we'll usually
  80. // get the same port number on both address families for
  81. // dev/debugging purposes, which is nice. But it's not so
  82. // deterministic that people will bake this into clients.
  83. // We try a few times just in case something's already
  84. // listening on that port (on all interfaces, probably).
  85. for try := uint8(0); try < 5; try++ {
  86. a16 := ip.As16()
  87. hashData := a16[len(a16)-3:]
  88. hashData[0] += try
  89. tryPort := (32 << 10) | uint16(crc32.ChecksumIEEE(hashData))
  90. ln, err = lc.Listen(context.Background(), tcp4or6, net.JoinHostPort(ipStr, strconv.Itoa(int(tryPort))))
  91. if err == nil {
  92. return ln, nil
  93. }
  94. }
  95. // Fall back to some random ephemeral port.
  96. ln, err = lc.Listen(context.Background(), tcp4or6, net.JoinHostPort(ipStr, "0"))
  97. // And if we're on a platform with netstack (anything but iOS), then just fallback to netstack.
  98. if err != nil && runtime.GOOS != "ios" {
  99. s.b.logf("peerapi: failed to do peerAPI listen, harmless (netstack available) but error was: %v", err)
  100. return newFakePeerAPIListener(ip), nil
  101. }
  102. return ln, err
  103. }
  104. type peerAPIListener struct {
  105. ps *peerAPIServer
  106. ip netip.Addr
  107. lb *LocalBackend
  108. // ln is the Listener. It can be nil in netstack mode if there are more than
  109. // 1 local addresses (e.g. both an IPv4 and IPv6). When it's nil, port
  110. // and urlStr are still populated.
  111. ln net.Listener
  112. // urlStr is the base URL to access the PeerAPI (http://ip:port/).
  113. urlStr string
  114. // port is just the port of urlStr.
  115. port int
  116. }
  117. func (pln *peerAPIListener) Close() error {
  118. if !buildfeatures.HasPeerAPIServer {
  119. return nil
  120. }
  121. if pln.ln != nil {
  122. return pln.ln.Close()
  123. }
  124. return nil
  125. }
  126. func (pln *peerAPIListener) serve() {
  127. if !buildfeatures.HasPeerAPIServer {
  128. return
  129. }
  130. if pln.ln == nil {
  131. return
  132. }
  133. defer pln.ln.Close()
  134. logf := pln.lb.logf
  135. for {
  136. c, err := pln.ln.Accept()
  137. if errors.Is(err, net.ErrClosed) {
  138. return
  139. }
  140. if err != nil {
  141. logf("peerapi.Accept: %v", err)
  142. return
  143. }
  144. ta, ok := c.RemoteAddr().(*net.TCPAddr)
  145. if !ok {
  146. c.Close()
  147. logf("peerapi: unexpected RemoteAddr %#v", c.RemoteAddr())
  148. continue
  149. }
  150. ipp := netaddr.Unmap(ta.AddrPort())
  151. if !ipp.IsValid() {
  152. logf("peerapi: bogus TCPAddr %#v", ta)
  153. c.Close()
  154. continue
  155. }
  156. pln.ServeConn(ipp, c)
  157. }
  158. }
  159. func (pln *peerAPIListener) ServeConn(src netip.AddrPort, c net.Conn) {
  160. logf := pln.lb.logf
  161. peerNode, peerUser, ok := pln.lb.WhoIs("tcp", src)
  162. if !ok {
  163. logf("peerapi: unknown peer %v", src)
  164. c.Close()
  165. return
  166. }
  167. nm := pln.lb.NetMap()
  168. if nm == nil || !nm.SelfNode.Valid() {
  169. logf("peerapi: no netmap")
  170. c.Close()
  171. return
  172. }
  173. h := &peerAPIHandler{
  174. ps: pln.ps,
  175. isSelf: nm.SelfNode.User() == peerNode.User(),
  176. remoteAddr: src,
  177. selfNode: nm.SelfNode,
  178. peerNode: peerNode,
  179. peerUser: peerUser,
  180. }
  181. httpServer := &http.Server{
  182. Handler: h,
  183. Protocols: new(http.Protocols),
  184. }
  185. httpServer.Protocols.SetHTTP1(true)
  186. httpServer.Protocols.SetUnencryptedHTTP2(true) // over WireGuard; "unencrypted" means no TLS
  187. go httpServer.Serve(netutil.NewOneConnListener(c, nil))
  188. }
  189. // peerAPIHandler serves the PeerAPI for a source specific client.
  190. type peerAPIHandler struct {
  191. ps *peerAPIServer
  192. remoteAddr netip.AddrPort
  193. isSelf bool // whether peerNode is owned by same user as this node
  194. selfNode tailcfg.NodeView // this node; always non-nil
  195. peerNode tailcfg.NodeView // peerNode is who's making the request
  196. peerUser tailcfg.UserProfile // profile of peerNode
  197. }
  198. // PeerAPIHandler is the interface implemented by [peerAPIHandler] and needed by
  199. // module features registered via tailscale.com/feature/*.
  200. type PeerAPIHandler interface {
  201. Peer() tailcfg.NodeView
  202. PeerCaps() tailcfg.PeerCapMap
  203. CanDebug() bool // can remote node can debug this node (internal state, etc)
  204. Self() tailcfg.NodeView
  205. LocalBackend() *LocalBackend
  206. IsSelfUntagged() bool // whether the peer is untagged and the same as this user
  207. RemoteAddr() netip.AddrPort
  208. Logf(format string, a ...any)
  209. }
  210. func (h *peerAPIHandler) IsSelfUntagged() bool {
  211. return !h.selfNode.IsTagged() && !h.peerNode.IsTagged() && h.isSelf
  212. }
  213. func (h *peerAPIHandler) Peer() tailcfg.NodeView { return h.peerNode }
  214. func (h *peerAPIHandler) Self() tailcfg.NodeView { return h.selfNode }
  215. func (h *peerAPIHandler) RemoteAddr() netip.AddrPort { return h.remoteAddr }
  216. func (h *peerAPIHandler) LocalBackend() *LocalBackend { return h.ps.b }
  217. func (h *peerAPIHandler) Logf(format string, a ...any) {
  218. h.logf(format, a...)
  219. }
  220. func (h *peerAPIHandler) logf(format string, a ...any) {
  221. h.ps.b.logf("peerapi: "+format, a...)
  222. }
  223. func (h *peerAPIHandler) logfv1(format string, a ...any) {
  224. h.ps.b.logf("[v1] peerapi: "+format, a...)
  225. }
  226. // isAddressValid reports whether addr is a valid destination address for this
  227. // node originating from the peer.
  228. func (h *peerAPIHandler) isAddressValid(addr netip.Addr) bool {
  229. if !addr.IsValid() {
  230. return false
  231. }
  232. v4MasqAddr, hasMasqV4 := h.peerNode.SelfNodeV4MasqAddrForThisPeer().GetOk()
  233. v6MasqAddr, hasMasqV6 := h.peerNode.SelfNodeV6MasqAddrForThisPeer().GetOk()
  234. if hasMasqV4 || hasMasqV6 {
  235. return addr == v4MasqAddr || addr == v6MasqAddr
  236. }
  237. pfx := netip.PrefixFrom(addr, addr.BitLen())
  238. return views.SliceContains(h.selfNode.Addresses(), pfx)
  239. }
  240. func (h *peerAPIHandler) validateHost(r *http.Request) error {
  241. if r.Host == "peer" {
  242. return nil
  243. }
  244. ap, err := netip.ParseAddrPort(r.Host)
  245. if err != nil {
  246. return err
  247. }
  248. if !h.isAddressValid(ap.Addr()) {
  249. return fmt.Errorf("%v not found in self addresses", ap.Addr())
  250. }
  251. return nil
  252. }
  253. func (h *peerAPIHandler) validatePeerAPIRequest(r *http.Request) error {
  254. if r.Referer() != "" {
  255. return errors.New("unexpected Referer")
  256. }
  257. if r.Header.Get("Origin") != "" {
  258. return errors.New("unexpected Origin")
  259. }
  260. return h.validateHost(r)
  261. }
  262. // peerAPIRequestShouldGetSecurityHeaders reports whether the PeerAPI request r
  263. // should get security response headers. It aims to report true for any request
  264. // from a browser and false for requests from tailscaled (Go) clients.
  265. //
  266. // PeerAPI is primarily an RPC mechanism between Tailscale instances. Some of
  267. // the HTTP handlers are useful for debugging with curl or browsers, but in
  268. // general the client is always tailscaled itself. Because PeerAPI only uses
  269. // HTTP/1 without HTTP/2 and its HPACK helping with repetitive headers, we try
  270. // to minimize header bytes sent in the common case when the client isn't a
  271. // browser. Minimizing bytes is important in particular with the ExitDNS service
  272. // provided by exit nodes, processing DNS clients from queries. We don't want to
  273. // waste bytes with security headers to non-browser clients. But if there's any
  274. // hint that the request is from a browser, then we do.
  275. func peerAPIRequestShouldGetSecurityHeaders(r *http.Request) bool {
  276. // Accept-Encoding is a forbidden header
  277. // (https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_header_name)
  278. // that Chrome, Firefox, Safari, etc send, but Go does not. So if we see it,
  279. // it's probably a browser and not a Tailscale PeerAPI (Go) client.
  280. if httpguts.HeaderValuesContainsToken(r.Header["Accept-Encoding"], "deflate") {
  281. return true
  282. }
  283. // Clients can mess with their User-Agent, but if they say Mozilla or have a bunch
  284. // of components (spaces) they're likely a browser.
  285. if ua := r.Header.Get("User-Agent"); strings.HasPrefix(ua, "Mozilla/") || strings.Count(ua, " ") > 2 {
  286. return true
  287. }
  288. // Tailscale/PeerAPI/Go clients don't have an Accept-Language.
  289. if r.Header.Get("Accept-Language") != "" {
  290. return true
  291. }
  292. return false
  293. }
  294. // RegisterPeerAPIHandler registers a PeerAPI handler.
  295. //
  296. // The path should be of the form "/v0/foo".
  297. //
  298. // It panics if the path is already registered.
  299. func RegisterPeerAPIHandler(path string, f func(PeerAPIHandler, http.ResponseWriter, *http.Request)) {
  300. if !buildfeatures.HasPeerAPIServer {
  301. return
  302. }
  303. if _, ok := peerAPIHandlers[path]; ok {
  304. panic(fmt.Sprintf("duplicate PeerAPI handler %q", path))
  305. }
  306. peerAPIHandlers[path] = f
  307. if strings.HasSuffix(path, "/") {
  308. peerAPIHandlerPrefixes[path] = f
  309. }
  310. }
  311. var (
  312. peerAPIHandlers = map[string]func(PeerAPIHandler, http.ResponseWriter, *http.Request){} // by URL.Path
  313. // peerAPIHandlerPrefixes are the subset of peerAPIHandlers where
  314. // the map key ends with a slash, indicating a prefix match.
  315. peerAPIHandlerPrefixes = map[string]func(PeerAPIHandler, http.ResponseWriter, *http.Request){}
  316. )
  317. func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  318. if !buildfeatures.HasPeerAPIServer {
  319. http.Error(w, feature.ErrUnavailable.Error(), http.StatusNotImplemented)
  320. return
  321. }
  322. if err := h.validatePeerAPIRequest(r); err != nil {
  323. metricInvalidRequests.Add(1)
  324. h.logf("invalid request from %v: %v", h.remoteAddr, err)
  325. http.Error(w, "invalid peerapi request", http.StatusForbidden)
  326. return
  327. }
  328. if peerAPIRequestShouldGetSecurityHeaders(r) {
  329. w.Header().Set("Content-Security-Policy", `default-src 'none'; frame-ancestors 'none'; script-src 'none'; script-src-elem 'none'; script-src-attr 'none'; style-src 'unsafe-inline'`)
  330. w.Header().Set("X-Frame-Options", "DENY")
  331. w.Header().Set("X-Content-Type-Options", "nosniff")
  332. }
  333. for pfx, ph := range peerAPIHandlerPrefixes {
  334. if strings.HasPrefix(r.URL.Path, pfx) {
  335. ph(h, w, r)
  336. return
  337. }
  338. }
  339. if buildfeatures.HasDNS && strings.HasPrefix(r.URL.Path, "/dns-query") {
  340. metricDNSCalls.Add(1)
  341. h.handleDNSQuery(w, r)
  342. return
  343. }
  344. if buildfeatures.HasDebug {
  345. switch r.URL.Path {
  346. case "/v0/goroutines":
  347. h.handleServeGoroutines(w, r)
  348. return
  349. case "/v0/env":
  350. h.handleServeEnv(w, r)
  351. return
  352. case "/v0/metrics":
  353. h.handleServeMetrics(w, r)
  354. return
  355. case "/v0/magicsock":
  356. h.handleServeMagicsock(w, r)
  357. return
  358. case "/v0/dnsfwd":
  359. h.handleServeDNSFwd(w, r)
  360. return
  361. case "/v0/interfaces":
  362. h.handleServeInterfaces(w, r)
  363. return
  364. case "/v0/sockstats":
  365. h.handleServeSockStats(w, r)
  366. return
  367. }
  368. }
  369. if ph, ok := peerAPIHandlers[r.URL.Path]; ok {
  370. ph(h, w, r)
  371. return
  372. }
  373. if r.URL.Path != "/" {
  374. http.Error(w, "unsupported peerapi path", http.StatusNotFound)
  375. return
  376. }
  377. who := h.peerUser.DisplayName
  378. fmt.Fprintf(w, `<html>
  379. <meta name="viewport" content="width=device-width, initial-scale=1">
  380. <body>
  381. <h1>Hello, %s (%v)</h1>
  382. This is my Tailscale device. Your device is %v.
  383. `, html.EscapeString(who), h.remoteAddr.Addr(), html.EscapeString(h.peerNode.ComputedName()))
  384. if h.isSelf {
  385. fmt.Fprintf(w, "<p>You are the owner of this node.\n")
  386. }
  387. }
  388. func (h *peerAPIHandler) handleServeInterfaces(w http.ResponseWriter, r *http.Request) {
  389. if !h.canDebug() {
  390. http.Error(w, "denied; no debug access", http.StatusForbidden)
  391. return
  392. }
  393. w.Header().Set("Content-Type", "text/html; charset=utf-8")
  394. fmt.Fprintln(w, "<h1>Interfaces</h1>")
  395. if dr, err := netmon.DefaultRoute(); err == nil {
  396. fmt.Fprintf(w, "<h3>Default route is %q(%d)</h3>\n", html.EscapeString(dr.InterfaceName), dr.InterfaceIndex)
  397. } else {
  398. fmt.Fprintf(w, "<h3>Could not get the default route: %s</h3>\n", html.EscapeString(err.Error()))
  399. }
  400. if hasCGNATInterface, err := h.ps.b.sys.NetMon.Get().HasCGNATInterface(); hasCGNATInterface {
  401. fmt.Fprintln(w, "<p>There is another interface using the CGNAT range.</p>")
  402. } else if err != nil {
  403. fmt.Fprintf(w, "<p>Could not check for CGNAT interfaces: %s</p>\n", html.EscapeString(err.Error()))
  404. }
  405. i, err := netmon.GetInterfaceList()
  406. if err != nil {
  407. fmt.Fprintf(w, "Could not get interfaces: %s\n", html.EscapeString(err.Error()))
  408. return
  409. }
  410. fmt.Fprintln(w, "<table style='border-collapse: collapse' border=1 cellspacing=0 cellpadding=2>")
  411. fmt.Fprint(w, "<tr>")
  412. for _, v := range []any{"Index", "Name", "MTU", "Flags", "Addrs", "Extra"} {
  413. fmt.Fprintf(w, "<th>%v</th> ", v)
  414. }
  415. fmt.Fprint(w, "</tr>\n")
  416. i.ForeachInterface(func(iface netmon.Interface, ipps []netip.Prefix) {
  417. fmt.Fprint(w, "<tr>")
  418. for _, v := range []any{iface.Index, iface.Name, iface.MTU, iface.Flags, ipps} {
  419. fmt.Fprintf(w, "<td>%s</td> ", html.EscapeString(fmt.Sprintf("%v", v)))
  420. }
  421. if extras, err := netmon.InterfaceDebugExtras(iface.Index); err == nil && extras != "" {
  422. fmt.Fprintf(w, "<td>%s</td> ", html.EscapeString(extras))
  423. } else if err != nil {
  424. fmt.Fprintf(w, "<td>%s</td> ", html.EscapeString(err.Error()))
  425. }
  426. fmt.Fprint(w, "</tr>\n")
  427. })
  428. fmt.Fprintln(w, "</table>")
  429. }
  430. func (h *peerAPIHandler) handleServeSockStats(w http.ResponseWriter, r *http.Request) {
  431. if !h.canDebug() {
  432. http.Error(w, "denied; no debug access", http.StatusForbidden)
  433. return
  434. }
  435. w.Header().Set("Content-Type", "text/html; charset=utf-8")
  436. fmt.Fprintln(w, "<!DOCTYPE html><h1>Socket Stats</h1>")
  437. if !sockstats.IsAvailable {
  438. fmt.Fprintln(w, "Socket stats are not available for this client")
  439. return
  440. }
  441. stats, interfaceStats, validation := sockstats.Get(), sockstats.GetInterfaces(), sockstats.GetValidation()
  442. if stats == nil {
  443. fmt.Fprintln(w, "No socket stats available")
  444. return
  445. }
  446. fmt.Fprintln(w, "<table border='1' cellspacing='0' style='border-collapse: collapse;'>")
  447. fmt.Fprintln(w, "<thead>")
  448. fmt.Fprintln(w, "<th>Label</th>")
  449. fmt.Fprintln(w, "<th>Tx</th>")
  450. fmt.Fprintln(w, "<th>Rx</th>")
  451. for _, iface := range interfaceStats.Interfaces {
  452. fmt.Fprintf(w, "<th>Tx (%s)</th>", html.EscapeString(iface))
  453. fmt.Fprintf(w, "<th>Rx (%s)</th>", html.EscapeString(iface))
  454. }
  455. fmt.Fprintln(w, "<th>Validation</th>")
  456. fmt.Fprintln(w, "</thead>")
  457. fmt.Fprintln(w, "<tbody>")
  458. labels := make([]sockstats.Label, 0, len(stats.Stats))
  459. for label := range stats.Stats {
  460. labels = append(labels, label)
  461. }
  462. slices.SortFunc(labels, func(a, b sockstats.Label) int {
  463. return strings.Compare(a.String(), b.String())
  464. })
  465. txTotal := uint64(0)
  466. rxTotal := uint64(0)
  467. txTotalByInterface := map[string]uint64{}
  468. rxTotalByInterface := map[string]uint64{}
  469. for _, label := range labels {
  470. stat := stats.Stats[label]
  471. fmt.Fprintln(w, "<tr>")
  472. fmt.Fprintf(w, "<td>%s</td>", html.EscapeString(label.String()))
  473. fmt.Fprintf(w, "<td align=right>%d</td>", stat.TxBytes)
  474. fmt.Fprintf(w, "<td align=right>%d</td>", stat.RxBytes)
  475. txTotal += stat.TxBytes
  476. rxTotal += stat.RxBytes
  477. if interfaceStat, ok := interfaceStats.Stats[label]; ok {
  478. for _, iface := range interfaceStats.Interfaces {
  479. fmt.Fprintf(w, "<td align=right>%d</td>", interfaceStat.TxBytesByInterface[iface])
  480. fmt.Fprintf(w, "<td align=right>%d</td>", interfaceStat.RxBytesByInterface[iface])
  481. txTotalByInterface[iface] += interfaceStat.TxBytesByInterface[iface]
  482. rxTotalByInterface[iface] += interfaceStat.RxBytesByInterface[iface]
  483. }
  484. }
  485. if validationStat, ok := validation.Stats[label]; ok && (validationStat.RxBytes > 0 || validationStat.TxBytes > 0) {
  486. fmt.Fprintf(w, "<td>Tx=%d (%+d) Rx=%d (%+d)</td>",
  487. validationStat.TxBytes,
  488. int64(validationStat.TxBytes)-int64(stat.TxBytes),
  489. validationStat.RxBytes,
  490. int64(validationStat.RxBytes)-int64(stat.RxBytes))
  491. } else {
  492. fmt.Fprintln(w, "<td></td>")
  493. }
  494. fmt.Fprintln(w, "</tr>")
  495. }
  496. fmt.Fprintln(w, "</tbody>")
  497. fmt.Fprintln(w, "<tfoot>")
  498. fmt.Fprintln(w, "<th>Total</th>")
  499. fmt.Fprintf(w, "<th>%d</th>", txTotal)
  500. fmt.Fprintf(w, "<th>%d</th>", rxTotal)
  501. for _, iface := range interfaceStats.Interfaces {
  502. fmt.Fprintf(w, "<th>%d</th>", txTotalByInterface[iface])
  503. fmt.Fprintf(w, "<th>%d</th>", rxTotalByInterface[iface])
  504. }
  505. fmt.Fprintln(w, "<th></th>")
  506. fmt.Fprintln(w, "</tfoot>")
  507. fmt.Fprintln(w, "</table>")
  508. fmt.Fprintln(w, "<h2>Debug Info</h2>")
  509. fmt.Fprintln(w, "<pre>")
  510. fmt.Fprintln(w, html.EscapeString(sockstats.DebugInfo()))
  511. fmt.Fprintln(w, "</pre>")
  512. }
  513. func (h *peerAPIHandler) CanDebug() bool { return h.canDebug() }
  514. // canDebug reports whether h can debug this node (goroutines, metrics,
  515. // magicsock internal state, etc).
  516. func (h *peerAPIHandler) canDebug() bool {
  517. if !h.selfNode.HasCap(tailcfg.CapabilityDebug) {
  518. // This node does not expose debug info.
  519. return false
  520. }
  521. if h.peerNode.UnsignedPeerAPIOnly() {
  522. // Unsigned peers can't debug.
  523. return false
  524. }
  525. return h.isSelf || h.peerHasCap(tailcfg.PeerCapabilityDebugPeer)
  526. }
  527. var allowSelfIngress = envknob.RegisterBool("TS_ALLOW_SELF_INGRESS")
  528. // canIngress reports whether h can send ingress requests to this node.
  529. func (h *peerAPIHandler) canIngress() bool {
  530. return h.peerHasCap(tailcfg.PeerCapabilityIngress) || (allowSelfIngress() && h.isSelf)
  531. }
  532. func (h *peerAPIHandler) peerHasCap(wantCap tailcfg.PeerCapability) bool {
  533. return h.PeerCaps().HasCapability(wantCap)
  534. }
  535. func (h *peerAPIHandler) PeerCaps() tailcfg.PeerCapMap {
  536. return h.ps.b.PeerCaps(h.remoteAddr.Addr())
  537. }
  538. func (h *peerAPIHandler) handleServeGoroutines(w http.ResponseWriter, r *http.Request) {
  539. if !h.canDebug() {
  540. http.Error(w, "denied; no debug access", http.StatusForbidden)
  541. return
  542. }
  543. var buf []byte
  544. for size := 4 << 10; size <= 2<<20; size *= 2 {
  545. buf = make([]byte, size)
  546. buf = buf[:runtime.Stack(buf, true)]
  547. if len(buf) < size {
  548. break
  549. }
  550. }
  551. w.Write(buf)
  552. }
  553. func (h *peerAPIHandler) handleServeEnv(w http.ResponseWriter, r *http.Request) {
  554. if !h.canDebug() {
  555. http.Error(w, "denied; no debug access", http.StatusForbidden)
  556. return
  557. }
  558. var data struct {
  559. Hostinfo *tailcfg.Hostinfo
  560. Uid int
  561. Args []string
  562. Env []string
  563. }
  564. data.Hostinfo = hostinfo.New()
  565. data.Uid = os.Getuid()
  566. data.Args = os.Args
  567. data.Env = os.Environ()
  568. w.Header().Set("Content-Type", "application/json")
  569. json.NewEncoder(w).Encode(data)
  570. }
  571. func (h *peerAPIHandler) handleServeMagicsock(w http.ResponseWriter, r *http.Request) {
  572. if !h.canDebug() {
  573. http.Error(w, "denied; no debug access", http.StatusForbidden)
  574. return
  575. }
  576. h.ps.b.MagicConn().ServeHTTPDebug(w, r)
  577. }
  578. func (h *peerAPIHandler) handleServeMetrics(w http.ResponseWriter, r *http.Request) {
  579. if !h.canDebug() {
  580. http.Error(w, "denied; no debug access", http.StatusForbidden)
  581. return
  582. }
  583. w.Header().Set("Content-Type", "text/plain")
  584. clientmetric.WritePrometheusExpositionFormat(w)
  585. }
  586. func (h *peerAPIHandler) handleServeDNSFwd(w http.ResponseWriter, r *http.Request) {
  587. if !buildfeatures.HasDNS {
  588. http.NotFound(w, r)
  589. return
  590. }
  591. if !h.canDebug() {
  592. http.Error(w, "denied; no debug access", http.StatusForbidden)
  593. return
  594. }
  595. dh := health.DebugHandler("dnsfwd")
  596. if dh == nil {
  597. http.Error(w, "not wired up", http.StatusInternalServerError)
  598. return
  599. }
  600. dh.ServeHTTP(w, r)
  601. }
  602. func (h *peerAPIHandler) replyToDNSQueries() bool {
  603. if !buildfeatures.HasDNS {
  604. return false
  605. }
  606. if h.isSelf {
  607. // If the peer is owned by the same user, just allow it
  608. // without further checks.
  609. return true
  610. }
  611. b := h.ps.b
  612. if !b.OfferingExitNode() && !b.OfferingAppConnector() {
  613. // If we're not an exit node or app connector, there's
  614. // no point to being a DNS server for somebody.
  615. return false
  616. }
  617. if !h.remoteAddr.IsValid() {
  618. // This should never be the case if the peerAPIHandler
  619. // was wired up correctly, but just in case.
  620. return false
  621. }
  622. // Otherwise, we're an exit node but the peer is not us, so
  623. // we need to check if they're allowed access to the internet.
  624. // As peerapi bypasses wgengine/filter checks, we need to check
  625. // ourselves. As a proxy for autogroup:internet access, we see
  626. // if we would've accepted a packet to 0.0.0.0:53. We treat
  627. // the IP 0.0.0.0 as being "the internet".
  628. //
  629. // Because of the way that filter checks work, rules are only
  630. // checked after ensuring the destination IP is part of the
  631. // local set of IPs. An exit node has 0.0.0.0/0 so its fine,
  632. // but an app connector explicitly adds 0.0.0.0/32 (and the
  633. // IPv6 equivalent) to make this work (see updateFilterLocked
  634. // in LocalBackend).
  635. f := b.currentNode().filter()
  636. if f == nil {
  637. return false
  638. }
  639. // Note: we check TCP here because the Filter type already had
  640. // a CheckTCP method (for unit tests), but it's pretty
  641. // arbitrary. DNS runs over TCP and UDP, so sure... we check
  642. // TCP.
  643. dstIP := netaddr.IPv4(0, 0, 0, 0)
  644. remoteIP := h.remoteAddr.Addr()
  645. if remoteIP.Is6() {
  646. // autogroup:internet for IPv6 is defined to start with 2000::/3,
  647. // so use 2000::0 as the probe "the internet" address.
  648. dstIP = netip.MustParseAddr("2000::")
  649. }
  650. verdict := f.CheckTCP(remoteIP, dstIP, 53)
  651. return verdict == filter.Accept
  652. }
  653. // handleDNSQuery implements a DoH server (RFC 8484) over the peerapi.
  654. // It's not over HTTPS as the spec dictates, but rather HTTP-over-WireGuard.
  655. func (h *peerAPIHandler) handleDNSQuery(w http.ResponseWriter, r *http.Request) {
  656. if !buildfeatures.HasDNS || h.ps.resolver == nil {
  657. http.Error(w, "DNS not wired up", http.StatusNotImplemented)
  658. return
  659. }
  660. if !h.replyToDNSQueries() {
  661. http.Error(w, "DNS access denied", http.StatusForbidden)
  662. return
  663. }
  664. pretty := false // non-DoH debug mode for humans
  665. q, publicError := dohQuery(r)
  666. if publicError != "" && r.Method == "GET" {
  667. if name := r.FormValue("q"); name != "" {
  668. pretty = true
  669. publicError = ""
  670. q = dnsQueryForName(name, r.FormValue("t"))
  671. }
  672. }
  673. if publicError != "" {
  674. http.Error(w, publicError, http.StatusBadRequest)
  675. return
  676. }
  677. // Some timeout that's short enough to be noticed by humans
  678. // but long enough that it's longer than real DNS timeouts.
  679. const arbitraryTimeout = 5 * time.Second
  680. ctx, cancel := context.WithTimeout(r.Context(), arbitraryTimeout)
  681. defer cancel()
  682. res, err := h.ps.resolver.HandlePeerDNSQuery(ctx, q, h.remoteAddr, h.ps.b.allowExitNodeDNSProxyToServeName)
  683. if err != nil {
  684. h.logf("handleDNS fwd error: %v", err)
  685. if err := ctx.Err(); err != nil {
  686. http.Error(w, err.Error(), http.StatusInternalServerError)
  687. } else {
  688. http.Error(w, "DNS forwarding error", http.StatusInternalServerError)
  689. }
  690. return
  691. }
  692. // TODO(raggi): consider pushing the integration down into the resolver
  693. // instead to avoid re-parsing the DNS response for improved performance in
  694. // the future.
  695. if buildfeatures.HasAppConnectors && h.ps.b.OfferingAppConnector() {
  696. if err := h.ps.b.ObserveDNSResponse(res); err != nil {
  697. h.logf("ObserveDNSResponse error: %v", err)
  698. // This is not fatal, we probably just failed to parse the upstream
  699. // response. Return it to the caller anyway.
  700. }
  701. }
  702. if pretty {
  703. // Non-standard response for interactive debugging.
  704. w.Header().Set("Content-Type", "application/json")
  705. writePrettyDNSReply(w, res)
  706. return
  707. }
  708. w.Header().Set("Content-Type", "application/dns-message")
  709. w.Header().Set("Content-Length", strconv.Itoa(len(res)))
  710. w.Write(res)
  711. }
  712. func dohQuery(r *http.Request) (dnsQuery []byte, publicErr string) {
  713. const maxQueryLen = 256 << 10
  714. switch r.Method {
  715. default:
  716. return nil, "bad HTTP method"
  717. case "GET":
  718. q64 := r.FormValue("dns")
  719. if q64 == "" {
  720. return nil, "missing ‘dns’ parameter; try '?dns=' (DoH standard) or use '?q=<name>' for JSON debug mode"
  721. }
  722. if base64.RawURLEncoding.DecodedLen(len(q64)) > maxQueryLen {
  723. return nil, "query too large"
  724. }
  725. q, err := base64.RawURLEncoding.DecodeString(q64)
  726. if err != nil {
  727. return nil, "invalid 'dns' base64 encoding"
  728. }
  729. return q, ""
  730. case "POST":
  731. if r.Header.Get("Content-Type") != "application/dns-message" {
  732. return nil, "unexpected Content-Type"
  733. }
  734. q, err := io.ReadAll(io.LimitReader(r.Body, maxQueryLen+1))
  735. if err != nil {
  736. return nil, "error reading post body with DNS query"
  737. }
  738. if len(q) > maxQueryLen {
  739. return nil, "query too large"
  740. }
  741. return q, ""
  742. }
  743. }
  744. func dnsQueryForName(name, typStr string) []byte {
  745. typ := dnsmessage.TypeA
  746. switch strings.ToLower(typStr) {
  747. case "aaaa":
  748. typ = dnsmessage.TypeAAAA
  749. case "txt":
  750. typ = dnsmessage.TypeTXT
  751. }
  752. b := dnsmessage.NewBuilder(nil, dnsmessage.Header{
  753. OpCode: 0, // query
  754. RecursionDesired: true,
  755. ID: 1, // arbitrary, but 0 is rejected by some servers
  756. })
  757. if !strings.HasSuffix(name, ".") {
  758. name += "."
  759. }
  760. b.StartQuestions()
  761. b.Question(dnsmessage.Question{
  762. Name: dnsmessage.MustNewName(name),
  763. Type: typ,
  764. Class: dnsmessage.ClassINET,
  765. })
  766. msg, _ := b.Finish()
  767. return msg
  768. }
  769. func writePrettyDNSReply(w io.Writer, res []byte) (err error) {
  770. defer func() {
  771. if err != nil {
  772. j, _ := json.Marshal(struct {
  773. Error string
  774. }{err.Error()})
  775. j = append(j, '\n')
  776. w.Write(j)
  777. return
  778. }
  779. }()
  780. var p dnsmessage.Parser
  781. hdr, err := p.Start(res)
  782. if err != nil {
  783. return err
  784. }
  785. if hdr.RCode != dnsmessage.RCodeSuccess {
  786. return fmt.Errorf("DNS RCode = %v", hdr.RCode)
  787. }
  788. if err := p.SkipAllQuestions(); err != nil {
  789. return err
  790. }
  791. var gotIPs []string
  792. for {
  793. h, err := p.AnswerHeader()
  794. if err == dnsmessage.ErrSectionDone {
  795. break
  796. }
  797. if err != nil {
  798. return err
  799. }
  800. if h.Class != dnsmessage.ClassINET {
  801. if err := p.SkipAnswer(); err != nil {
  802. return err
  803. }
  804. continue
  805. }
  806. switch h.Type {
  807. case dnsmessage.TypeA:
  808. r, err := p.AResource()
  809. if err != nil {
  810. return err
  811. }
  812. gotIPs = append(gotIPs, net.IP(r.A[:]).String())
  813. case dnsmessage.TypeAAAA:
  814. r, err := p.AAAAResource()
  815. if err != nil {
  816. return err
  817. }
  818. gotIPs = append(gotIPs, net.IP(r.AAAA[:]).String())
  819. case dnsmessage.TypeTXT:
  820. r, err := p.TXTResource()
  821. if err != nil {
  822. return err
  823. }
  824. gotIPs = append(gotIPs, r.TXT...)
  825. default:
  826. if err := p.SkipAnswer(); err != nil {
  827. return err
  828. }
  829. }
  830. }
  831. j, _ := json.Marshal(gotIPs)
  832. j = append(j, '\n')
  833. w.Write(j)
  834. return nil
  835. }
  836. // httpResponseWrapper wraps an http.ResponseWrite and
  837. // stores the status code and content length.
  838. type httpResponseWrapper struct {
  839. http.ResponseWriter
  840. statusCode int
  841. contentLength int64
  842. }
  843. // WriteHeader implements the WriteHeader interface.
  844. func (hrw *httpResponseWrapper) WriteHeader(status int) {
  845. hrw.statusCode = status
  846. hrw.ResponseWriter.WriteHeader(status)
  847. }
  848. // Write implements the Write interface.
  849. func (hrw *httpResponseWrapper) Write(b []byte) (int, error) {
  850. n, err := hrw.ResponseWriter.Write(b)
  851. hrw.contentLength += int64(n)
  852. return n, err
  853. }
  854. // requestBodyWrapper wraps an io.ReadCloser and stores
  855. // the number of bytesRead.
  856. type requestBodyWrapper struct {
  857. io.ReadCloser
  858. bytesRead int64
  859. }
  860. // Read implements the io.Reader interface.
  861. func (rbw *requestBodyWrapper) Read(b []byte) (int, error) {
  862. n, err := rbw.ReadCloser.Read(b)
  863. rbw.bytesRead += int64(n)
  864. return n, err
  865. }
  866. // peerAPIURL returns an HTTP URL for the peer's peerapi service,
  867. // without a trailing slash.
  868. //
  869. // If ip or port is the zero value then it returns the empty string.
  870. func peerAPIURL(ip netip.Addr, port uint16) string {
  871. if port == 0 || !ip.IsValid() {
  872. return ""
  873. }
  874. return fmt.Sprintf("http://%v", netip.AddrPortFrom(ip, port))
  875. }
  876. // peerAPIBase returns the "http://ip:port" URL base to reach peer's peerAPI.
  877. // It returns the empty string if the peer doesn't support the peerapi
  878. // or there's no matching address family based on the netmap's own addresses.
  879. func peerAPIBase(nm *netmap.NetworkMap, peer tailcfg.NodeView) string {
  880. if nm == nil || !peer.Valid() || !peer.Hostinfo().Valid() {
  881. return ""
  882. }
  883. var have4, have6 bool
  884. addrs := nm.GetAddresses()
  885. for _, a := range addrs.All() {
  886. if !a.IsSingleIP() {
  887. continue
  888. }
  889. switch {
  890. case a.Addr().Is4():
  891. have4 = true
  892. case a.Addr().Is6():
  893. have6 = true
  894. }
  895. }
  896. p4, p6 := peerAPIPorts(peer)
  897. switch {
  898. case have4 && p4 != 0:
  899. return peerAPIURL(nodeIP(peer, netip.Addr.Is4), p4)
  900. case have6 && p6 != 0:
  901. return peerAPIURL(nodeIP(peer, netip.Addr.Is6), p6)
  902. }
  903. return ""
  904. }
  905. // newFakePeerAPIListener creates a new net.Listener that acts like
  906. // it's listening on the provided IP address and on TCP port 1.
  907. //
  908. // See docs on fakePeerAPIListener.
  909. func newFakePeerAPIListener(ip netip.Addr) net.Listener {
  910. return &fakePeerAPIListener{
  911. addr: net.TCPAddrFromAddrPort(netip.AddrPortFrom(ip, 1)),
  912. closed: make(chan struct{}),
  913. }
  914. }
  915. // fakePeerAPIListener is a net.Listener that has an Addr method returning a TCPAddr
  916. // for a given IP on port 1 (arbitrary) and can be Closed, but otherwise Accept
  917. // just blocks forever until closed. The purpose of this is to let the rest
  918. // of the LocalBackend/PeerAPI code run and think it's talking to the kernel,
  919. // even if the kernel isn't cooperating (like on Android: Issue 4449, 4293, etc)
  920. // or we lack permission to listen on a port. It's okay to not actually listen via
  921. // the kernel because on almost all platforms (except iOS as of 2022-04-20) we
  922. // also intercept incoming netstack TCP requests to our peerapi port and hand them over
  923. // directly to peerapi, without involving the kernel. So this doesn't need to be
  924. // real. But the port number we return (1, in this case) is the port number we advertise
  925. // to peers and they connect to. 1 seems pretty safe to use. Even if the kernel's
  926. // using it, it doesn't matter, as we intercept it first in netstack and the kernel
  927. // never notices.
  928. //
  929. // Eventually we'll remove this code and do this on all platforms, when iOS also uses
  930. // netstack.
  931. type fakePeerAPIListener struct {
  932. addr net.Addr
  933. closeOnce sync.Once
  934. closed chan struct{}
  935. }
  936. func (fl *fakePeerAPIListener) Close() error {
  937. fl.closeOnce.Do(func() { close(fl.closed) })
  938. return nil
  939. }
  940. func (fl *fakePeerAPIListener) Accept() (net.Conn, error) {
  941. <-fl.closed
  942. return nil, net.ErrClosed
  943. }
  944. func (fl *fakePeerAPIListener) Addr() net.Addr { return fl.addr }
  945. var (
  946. metricInvalidRequests = clientmetric.NewCounter("peerapi_invalid_requests")
  947. // Non-debug PeerAPI endpoints.
  948. metricDNSCalls = clientmetric.NewCounter("peerapi_dns")
  949. )