peerapi.go 34 KB

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