peerapi.go 31 KB

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