tsweb.go 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. // Package tsweb contains code used in various Tailscale webservers.
  4. package tsweb
  5. import (
  6. "bufio"
  7. "bytes"
  8. "cmp"
  9. "context"
  10. "errors"
  11. "expvar"
  12. "fmt"
  13. "io"
  14. "net"
  15. "net/http"
  16. "net/netip"
  17. "net/url"
  18. "os"
  19. "path/filepath"
  20. "regexp"
  21. "runtime"
  22. "strconv"
  23. "strings"
  24. "sync"
  25. "time"
  26. "go4.org/mem"
  27. "tailscale.com/envknob"
  28. "tailscale.com/metrics"
  29. "tailscale.com/net/tsaddr"
  30. "tailscale.com/tsweb/varz"
  31. "tailscale.com/types/logger"
  32. "tailscale.com/util/ctxkey"
  33. "tailscale.com/util/vizerror"
  34. )
  35. // DevMode controls whether extra output in shown, for when the binary is being run in dev mode.
  36. var DevMode bool
  37. func DefaultCertDir(leafDir string) string {
  38. cacheDir, err := os.UserCacheDir()
  39. if err == nil {
  40. return filepath.Join(cacheDir, "tailscale", leafDir)
  41. }
  42. return ""
  43. }
  44. // IsProd443 reports whether addr is a Go listen address for port 443.
  45. func IsProd443(addr string) bool {
  46. _, port, _ := net.SplitHostPort(addr)
  47. return port == "443" || port == "https"
  48. }
  49. // AllowDebugAccess reports whether r should be permitted to access
  50. // various debug endpoints.
  51. func AllowDebugAccess(r *http.Request) bool {
  52. if allowDebugAccessWithKey(r) {
  53. return true
  54. }
  55. if r.Header.Get("X-Forwarded-For") != "" {
  56. // TODO if/when needed. For now, conservative:
  57. return false
  58. }
  59. ipStr, _, err := net.SplitHostPort(r.RemoteAddr)
  60. if err != nil {
  61. return false
  62. }
  63. ip, err := netip.ParseAddr(ipStr)
  64. if err != nil {
  65. return false
  66. }
  67. if tsaddr.IsTailscaleIP(ip) || ip.IsLoopback() || ipStr == envknob.String("TS_ALLOW_DEBUG_IP") {
  68. return true
  69. }
  70. return false
  71. }
  72. func allowDebugAccessWithKey(r *http.Request) bool {
  73. if r.Method != "GET" {
  74. return false
  75. }
  76. urlKey := r.FormValue("debugkey")
  77. keyPath := envknob.String("TS_DEBUG_KEY_PATH")
  78. if urlKey != "" && keyPath != "" {
  79. slurp, err := os.ReadFile(keyPath)
  80. if err == nil && string(bytes.TrimSpace(slurp)) == urlKey {
  81. return true
  82. }
  83. }
  84. return false
  85. }
  86. // AcceptsEncoding reports whether r accepts the named encoding
  87. // ("gzip", "br", etc).
  88. func AcceptsEncoding(r *http.Request, enc string) bool {
  89. h := r.Header.Get("Accept-Encoding")
  90. if h == "" {
  91. return false
  92. }
  93. if !strings.Contains(h, enc) && !mem.ContainsFold(mem.S(h), mem.S(enc)) {
  94. return false
  95. }
  96. remain := h
  97. for len(remain) > 0 {
  98. var part string
  99. part, remain, _ = strings.Cut(remain, ",")
  100. part = strings.TrimSpace(part)
  101. part, _, _ = strings.Cut(part, ";")
  102. if part == enc {
  103. return true
  104. }
  105. }
  106. return false
  107. }
  108. // Protected wraps a provided debug handler, h, returning a Handler
  109. // that enforces AllowDebugAccess and returns forbidden replies for
  110. // unauthorized requests.
  111. func Protected(h http.Handler) http.Handler {
  112. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  113. if !AllowDebugAccess(r) {
  114. msg := "debug access denied"
  115. if DevMode {
  116. ipStr, _, _ := net.SplitHostPort(r.RemoteAddr)
  117. msg += fmt.Sprintf("; to permit access, set TS_ALLOW_DEBUG_IP=%v", ipStr)
  118. }
  119. http.Error(w, msg, http.StatusForbidden)
  120. return
  121. }
  122. h.ServeHTTP(w, r)
  123. })
  124. }
  125. // Port80Handler is the handler to be given to
  126. // autocert.Manager.HTTPHandler. The inner handler is the mux
  127. // returned by NewMux containing registered /debug handlers.
  128. type Port80Handler struct {
  129. Main http.Handler
  130. // FQDN is used to redirect incoming requests to https://<FQDN>.
  131. // If it is not set, the hostname is calculated from the incoming
  132. // request.
  133. FQDN string
  134. }
  135. func (h Port80Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  136. path := r.RequestURI
  137. if path == "/debug" || strings.HasPrefix(path, "/debug") {
  138. h.Main.ServeHTTP(w, r)
  139. return
  140. }
  141. if r.Method != "GET" && r.Method != "HEAD" {
  142. http.Error(w, "Use HTTPS", http.StatusBadRequest)
  143. return
  144. }
  145. if path == "/" && AllowDebugAccess(r) {
  146. // Redirect authorized user to the debug handler.
  147. path = "/debug/"
  148. }
  149. host := cmp.Or(h.FQDN, r.Host)
  150. target := "https://" + host + path
  151. http.Redirect(w, r, target, http.StatusFound)
  152. }
  153. // ReturnHandler is like net/http.Handler, but the handler can return an
  154. // error instead of writing to its ResponseWriter.
  155. type ReturnHandler interface {
  156. // ServeHTTPReturn is like http.Handler.ServeHTTP, except that
  157. // it can choose to return an error instead of writing to its
  158. // http.ResponseWriter.
  159. //
  160. // If ServeHTTPReturn returns an error, it caller should handle
  161. // an error by serving an HTTP 500 response to the user. The
  162. // error details should not be sent to the client, as they may
  163. // contain sensitive information. If the error is an
  164. // HTTPError, though, callers should use the HTTP response
  165. // code and message as the response to the client.
  166. ServeHTTPReturn(http.ResponseWriter, *http.Request) error
  167. }
  168. // BucketedStatsOptions describes tsweb handler options surrounding
  169. // the generation of metrics, grouped into buckets.
  170. type BucketedStatsOptions struct {
  171. // Bucket returns which bucket the given request is in.
  172. // If nil, [NormalizedPath] is used to compute the bucket.
  173. Bucket func(req *http.Request) string
  174. // If non-nil, Started maintains a counter of all requests which
  175. // have begun processing.
  176. Started *metrics.LabelMap
  177. // If non-nil, Finished maintains a counter of all requests which
  178. // have finished processing with success (that is, the HTTP handler has
  179. // returned).
  180. Finished *metrics.LabelMap
  181. }
  182. // normalizePathRegex matches components in a HTTP request path
  183. // that should be replaced.
  184. //
  185. // See: https://regex101.com/r/WIfpaR/3 for the explainer and test cases.
  186. var normalizePathRegex = regexp.MustCompile("([a-fA-F0-9]{9,}|([^\\/])+\\.([^\\/]){2,}|((n|k|u|L|t|S)[a-zA-Z0-9]{5,}(CNTRL|Djz1H|LV5CY|mxgaY|jNy1b))|(([^\\/])+\\@passkey))")
  187. // NormalizedPath returns the given path with the following modifications:
  188. //
  189. // - any query parameters are removed
  190. // - any path component with a hex string of 9 or more characters is
  191. // replaced by an ellipsis
  192. // - any path component containing a period with at least two characters
  193. // after the period (i.e. an email or domain)
  194. // - any path component consisting of a common Tailscale Stable ID
  195. // - any path segment *@passkey.
  196. func NormalizedPath(p string) string {
  197. // Fastpath: No hex sequences in there we might have to trim.
  198. // Avoids allocating.
  199. if normalizePathRegex.FindStringIndex(p) == nil {
  200. b, _, _ := strings.Cut(p, "?")
  201. return b
  202. }
  203. // If we got here, there's at least one hex sequences we need to
  204. // replace with an ellipsis.
  205. replaced := normalizePathRegex.ReplaceAllString(p, "…")
  206. b, _, _ := strings.Cut(replaced, "?")
  207. return b
  208. }
  209. func (o *BucketedStatsOptions) bucketForRequest(r *http.Request) string {
  210. if o.Bucket != nil {
  211. return o.Bucket(r)
  212. }
  213. return NormalizedPath(r.URL.Path)
  214. }
  215. // HandlerOptions are options used by [StdHandler], containing both [LogOptions]
  216. // used by [LogHandler] and [ErrorOptions] used by [ErrorHandler].
  217. type HandlerOptions struct {
  218. QuietLoggingIfSuccessful bool // if set, do not log successfully handled HTTP requests (200 and 304 status codes)
  219. Logf logger.Logf
  220. Now func() time.Time // if nil, defaults to time.Now
  221. // If non-nil, StatusCodeCounters maintains counters
  222. // of status codes for handled responses.
  223. // The keys are "1xx", "2xx", "3xx", "4xx", and "5xx".
  224. StatusCodeCounters *expvar.Map
  225. // If non-nil, StatusCodeCountersFull maintains counters of status
  226. // codes for handled responses.
  227. // The keys are HTTP numeric response codes e.g. 200, 404, ...
  228. StatusCodeCountersFull *expvar.Map
  229. // If non-nil, BucketedStats computes and exposes statistics
  230. // for each bucket based on the contained parameters.
  231. BucketedStats *BucketedStatsOptions
  232. // OnStart is called inline before ServeHTTP is called. Optional.
  233. OnStart OnStartFunc
  234. // OnError is called if the handler returned a HTTPError. This
  235. // is intended to be used to present pretty error pages if
  236. // the user agent is determined to be a browser.
  237. OnError ErrorHandlerFunc
  238. // OnCompletion is called inline when ServeHTTP is finished and gets
  239. // useful data that the implementor can use for metrics. Optional.
  240. OnCompletion OnCompletionFunc
  241. }
  242. // LogOptions are the options used by [LogHandler].
  243. // These options are a subset of [HandlerOptions].
  244. type LogOptions struct {
  245. // Logf is used to log HTTP requests and responses.
  246. Logf logger.Logf
  247. // Now is a function giving the current time. Defaults to [time.Now].
  248. Now func() time.Time
  249. // QuietLogging suppresses all logging of handled HTTP requests, even if
  250. // there are errors or status codes considered unsuccessful. Use this option
  251. // to add your own logging in OnCompletion.
  252. QuietLogging bool
  253. // QuietLoggingIfSuccessful suppresses logging of handled HTTP requests
  254. // where the request's response status code is 200 or 304.
  255. QuietLoggingIfSuccessful bool
  256. // StatusCodeCounters maintains counters of status code classes.
  257. // The keys are "1xx", "2xx", "3xx", "4xx", and "5xx".
  258. // If nil, no counting is done.
  259. StatusCodeCounters *expvar.Map
  260. // StatusCodeCountersFull maintains counters of status codes.
  261. // The keys are HTTP numeric response codes e.g. 200, 404, ...
  262. // If nil, no counting is done.
  263. StatusCodeCountersFull *expvar.Map
  264. // BucketedStats computes and exposes statistics for each bucket based on
  265. // the contained parameters. If nil, no counting is done.
  266. BucketedStats *BucketedStatsOptions
  267. // OnStart is called inline before ServeHTTP is called. Optional.
  268. OnStart OnStartFunc
  269. // OnCompletion is called inline when ServeHTTP is finished and gets
  270. // useful data that the implementor can use for metrics. Optional.
  271. OnCompletion OnCompletionFunc
  272. }
  273. func (o HandlerOptions) logOptions() LogOptions {
  274. return LogOptions{
  275. QuietLoggingIfSuccessful: o.QuietLoggingIfSuccessful,
  276. Logf: o.Logf,
  277. Now: o.Now,
  278. StatusCodeCounters: o.StatusCodeCounters,
  279. StatusCodeCountersFull: o.StatusCodeCountersFull,
  280. BucketedStats: o.BucketedStats,
  281. OnStart: o.OnStart,
  282. OnCompletion: o.OnCompletion,
  283. }
  284. }
  285. func (opts LogOptions) withDefaults() LogOptions {
  286. if opts.Logf == nil {
  287. opts.Logf = logger.Discard
  288. }
  289. if opts.Now == nil {
  290. opts.Now = time.Now
  291. }
  292. return opts
  293. }
  294. // ErrorOptions are options used by [ErrorHandler].
  295. type ErrorOptions struct {
  296. // Logf is used to record unexpected behaviours when returning HTTPError but
  297. // different error codes have already been written to the client.
  298. Logf logger.Logf
  299. // OnError is called if the handler returned a HTTPError. This
  300. // is intended to be used to present pretty error pages if
  301. // the user agent is determined to be a browser.
  302. OnError ErrorHandlerFunc
  303. }
  304. func (opts ErrorOptions) withDefaults() ErrorOptions {
  305. if opts.Logf == nil {
  306. opts.Logf = logger.Discard
  307. }
  308. if opts.OnError == nil {
  309. opts.OnError = WriteHTTPError
  310. }
  311. return opts
  312. }
  313. func (opts HandlerOptions) errorOptions() ErrorOptions {
  314. return ErrorOptions{
  315. OnError: opts.OnError,
  316. }
  317. }
  318. // ErrorHandlerFunc is called to present a error response.
  319. type ErrorHandlerFunc func(http.ResponseWriter, *http.Request, HTTPError)
  320. // OnStartFunc is called before ServeHTTP is called.
  321. type OnStartFunc func(*http.Request, AccessLogRecord)
  322. // OnCompletionFunc is called when ServeHTTP is finished and gets
  323. // useful data that the implementor can use for metrics.
  324. type OnCompletionFunc func(*http.Request, AccessLogRecord)
  325. // ReturnHandlerFunc is an adapter to allow the use of ordinary
  326. // functions as ReturnHandlers. If f is a function with the
  327. // appropriate signature, ReturnHandlerFunc(f) is a ReturnHandler that
  328. // calls f.
  329. type ReturnHandlerFunc func(http.ResponseWriter, *http.Request) error
  330. // A Middleware is a function that wraps an http.Handler to extend or modify
  331. // its behaviour.
  332. //
  333. // The implementation of the wrapper is responsible for delegating its input
  334. // request to the underlying handler, if appropriate.
  335. type Middleware func(h http.Handler) http.Handler
  336. // MiddlewareStack combines multiple middleware into a single middleware for
  337. // decorating a [http.Handler]. The first middleware argument will be the first
  338. // to process an incoming request, before passing the request onto subsequent
  339. // middleware and eventually the wrapped handler.
  340. //
  341. // For example:
  342. //
  343. // MiddlewareStack(A, B)(h).ServeHTTP(w, r)
  344. //
  345. // calls in sequence:
  346. //
  347. // a.ServeHTTP(w, r)
  348. // -> b.ServeHTTP(w, r)
  349. // -> h.ServeHTTP(w, r)
  350. //
  351. // (where the lowercase handlers were generated by the uppercase middleware).
  352. func MiddlewareStack(mw ...Middleware) Middleware {
  353. if len(mw) == 1 {
  354. return mw[0]
  355. }
  356. return func(h http.Handler) http.Handler {
  357. for i := len(mw) - 1; i >= 0; i-- {
  358. h = mw[i](h)
  359. }
  360. return h
  361. }
  362. }
  363. // ServeHTTPReturn calls f(w, r).
  364. func (f ReturnHandlerFunc) ServeHTTPReturn(w http.ResponseWriter, r *http.Request) error {
  365. return f(w, r)
  366. }
  367. // StdHandler converts a ReturnHandler into a standard http.Handler.
  368. // Handled requests are logged using opts.Logf, as are any errors.
  369. // Errors are handled as specified by the ReturnHandler interface.
  370. // Short-hand for LogHandler(ErrorHandler()).
  371. func StdHandler(h ReturnHandler, opts HandlerOptions) http.Handler {
  372. return LogHandler(ErrorHandler(h, opts.errorOptions()), opts.logOptions())
  373. }
  374. // LogHandler returns an http.Handler that logs to opts.Logf.
  375. // It logs both successful and failing requests.
  376. // The log line includes the first error returned to [ErrorHandler] within.
  377. // The outer-most LogHandler(LogHandler(...)) does all of the logging.
  378. // Inner LogHandler instance do nothing.
  379. // Panics are swallowed and their stack traces are put in the error.
  380. func LogHandler(h http.Handler, opts LogOptions) http.Handler {
  381. return logHandler{h, opts.withDefaults()}
  382. }
  383. // ErrorHandler converts a [ReturnHandler] into a standard [http.Handler].
  384. // Errors are handled as specified by the [ReturnHandler.ServeHTTPReturn] method.
  385. // When wrapped in a [LogHandler], panics are added to the [AccessLogRecord];
  386. // otherwise, panics continue up the stack.
  387. func ErrorHandler(h ReturnHandler, opts ErrorOptions) http.Handler {
  388. return errorHandler{h, opts.withDefaults()}
  389. }
  390. // errCallback is added to logHandler's request context so that errorHandler can
  391. // pass errors back up the stack to logHandler.
  392. var errCallback = ctxkey.New[func(HTTPError)]("tailscale.com/tsweb.errCallback", nil)
  393. // logHandler is a http.Handler which logs the HTTP request.
  394. // It injects an errCallback for errorHandler to augment the log message with
  395. // a specific error.
  396. type logHandler struct {
  397. h http.Handler
  398. opts LogOptions
  399. }
  400. func (h logHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  401. // If there's already a logHandler up the chain, skip this one.
  402. ctx := r.Context()
  403. if errCallback.Has(ctx) {
  404. h.h.ServeHTTP(w, r)
  405. return
  406. }
  407. msg := AccessLogRecord{
  408. Time: h.opts.Now(),
  409. RemoteAddr: r.RemoteAddr,
  410. Proto: r.Proto,
  411. TLS: r.TLS != nil,
  412. Host: r.Host,
  413. Method: r.Method,
  414. RequestURI: r.URL.RequestURI(),
  415. UserAgent: r.UserAgent(),
  416. Referer: r.Referer(),
  417. RequestID: RequestIDFromContext(r.Context()),
  418. }
  419. if bs := h.opts.BucketedStats; bs != nil && bs.Started != nil && bs.Finished != nil {
  420. bucket := bs.bucketForRequest(r)
  421. var startRecorded bool
  422. switch v := bs.Started.Map.Get(bucket).(type) {
  423. case *expvar.Int:
  424. // If we've already seen this bucket for, count it immediately.
  425. // Otherwise, for newly seen paths, only count retroactively
  426. // (so started-finished doesn't go negative) so we don't fill
  427. // this LabelMap up with internet scanning spam.
  428. v.Add(1)
  429. startRecorded = true
  430. }
  431. defer func() {
  432. // Only increment metrics for buckets that result in good HTTP statuses
  433. // or when we know the start was already counted.
  434. // Otherwise they get full of internet scanning noise. Only filtering 404
  435. // gets most of the way there but there are also plenty of URLs that are
  436. // almost right but result in 400s too. Seem easier to just only ignore
  437. // all 4xx and 5xx.
  438. if startRecorded {
  439. bs.Finished.Add(bucket, 1)
  440. } else if msg.Code < 400 {
  441. // This is the first non-error request for this bucket,
  442. // so count it now retroactively.
  443. bs.Started.Add(bucket, 1)
  444. bs.Finished.Add(bucket, 1)
  445. }
  446. }()
  447. }
  448. if fn := h.opts.OnStart; fn != nil {
  449. fn(r, msg)
  450. }
  451. // Let errorHandler tell us what error it wrote to the client.
  452. r = r.WithContext(errCallback.WithValue(ctx, func(e HTTPError) {
  453. // Keep the deepest error.
  454. if msg.Err != "" {
  455. return
  456. }
  457. // Log the error.
  458. if e.Msg != "" && e.Err != nil {
  459. msg.Err = e.Msg + ": " + e.Err.Error()
  460. } else if e.Err != nil {
  461. msg.Err = e.Err.Error()
  462. } else if e.Msg != "" {
  463. msg.Err = e.Msg
  464. }
  465. // We log the code from the loggingResponseWriter, except for
  466. // cancellation where we override with 499.
  467. if reqCancelled(r, e.Err) {
  468. msg.Code = 499
  469. }
  470. }))
  471. lw := newLogResponseWriter(h.opts.Logf, w, r)
  472. defer func() {
  473. // If the handler panicked then make sure we include that in our error.
  474. // Panics caught up errorHandler shouldn't appear here, unless the panic
  475. // originates in one of its callbacks.
  476. recovered := recover()
  477. if recovered != nil {
  478. if msg.Err == "" {
  479. msg.Err = panic2err(recovered).Error()
  480. } else {
  481. msg.Err += "\n\nthen " + panic2err(recovered).Error()
  482. }
  483. }
  484. h.logRequest(r, lw, msg)
  485. }()
  486. h.h.ServeHTTP(lw, r)
  487. }
  488. func (h logHandler) logRequest(r *http.Request, lw *loggingResponseWriter, msg AccessLogRecord) {
  489. // Complete our access log from the loggingResponseWriter.
  490. msg.Bytes = lw.bytes
  491. msg.Seconds = h.opts.Now().Sub(msg.Time).Seconds()
  492. switch {
  493. case msg.Code != 0:
  494. // Keep explicit codes from a few particular errors.
  495. case lw.hijacked:
  496. // Connection no longer belongs to us, just log that we
  497. // switched protocols away from HTTP.
  498. msg.Code = http.StatusSwitchingProtocols
  499. case lw.code == 0:
  500. // If the handler didn't write and didn't send a header, that still means 200.
  501. // (See https://play.golang.org/p/4P7nx_Tap7p)
  502. msg.Code = 200
  503. default:
  504. msg.Code = lw.code
  505. }
  506. // Keep track of the original response code when we've overridden it.
  507. if lw.code != 0 && msg.Code != lw.code {
  508. if msg.Err == "" {
  509. msg.Err = fmt.Sprintf("(original code %d)", lw.code)
  510. } else {
  511. msg.Err = fmt.Sprintf("%s (original code %d)", msg.Err, lw.code)
  512. }
  513. }
  514. if !h.opts.QuietLogging && !(h.opts.QuietLoggingIfSuccessful && (msg.Code == http.StatusOK || msg.Code == http.StatusNotModified)) {
  515. h.opts.Logf("%s", msg)
  516. }
  517. if h.opts.OnCompletion != nil {
  518. h.opts.OnCompletion(r, msg)
  519. }
  520. // Closing metrics.
  521. if h.opts.StatusCodeCounters != nil {
  522. h.opts.StatusCodeCounters.Add(responseCodeString(msg.Code/100), 1)
  523. }
  524. if h.opts.StatusCodeCountersFull != nil {
  525. h.opts.StatusCodeCountersFull.Add(responseCodeString(msg.Code), 1)
  526. }
  527. }
  528. func responseCodeString(code int) string {
  529. if v, ok := responseCodeCache.Load(code); ok {
  530. return v.(string)
  531. }
  532. var ret string
  533. if code < 10 {
  534. ret = fmt.Sprintf("%dxx", code)
  535. } else {
  536. ret = strconv.Itoa(code)
  537. }
  538. responseCodeCache.Store(code, ret)
  539. return ret
  540. }
  541. // responseCodeCache memoizes the string form of HTTP response codes,
  542. // so that the hot request-handling codepath doesn't have to allocate
  543. // in strconv/fmt for every request.
  544. //
  545. // Keys are either full HTTP response code ints (200, 404) or "family"
  546. // ints representing entire families (e.g. 2 for 2xx codes). Values
  547. // are the string form of that code/family.
  548. var responseCodeCache sync.Map
  549. // loggingResponseWriter wraps a ResponseWriter and record the HTTP
  550. // response code that gets sent, if any.
  551. type loggingResponseWriter struct {
  552. http.ResponseWriter
  553. ctx context.Context
  554. code int
  555. bytes int
  556. hijacked bool
  557. logf logger.Logf
  558. }
  559. // newLogResponseWriter returns a loggingResponseWriter which uses's the logger
  560. // from r, or falls back to logf. If a nil logger is given, the logs are
  561. // discarded.
  562. func newLogResponseWriter(logf logger.Logf, w http.ResponseWriter, r *http.Request) *loggingResponseWriter {
  563. if lg, ok := logger.LogfKey.ValueOk(r.Context()); ok && lg != nil {
  564. logf = lg
  565. }
  566. if logf == nil {
  567. logf = logger.Discard
  568. }
  569. return &loggingResponseWriter{
  570. ResponseWriter: w,
  571. ctx: r.Context(),
  572. logf: logf,
  573. }
  574. }
  575. // WriteHeader implements [http.ResponseWriter].
  576. func (lg *loggingResponseWriter) WriteHeader(statusCode int) {
  577. if lg.code != 0 {
  578. lg.logf("[unexpected] HTTP handler set statusCode twice (%d and %d)", lg.code, statusCode)
  579. return
  580. }
  581. if lg.ctx.Err() == nil {
  582. lg.code = statusCode
  583. }
  584. lg.ResponseWriter.WriteHeader(statusCode)
  585. }
  586. // Write implements [http.ResponseWriter].
  587. func (lg *loggingResponseWriter) Write(bs []byte) (int, error) {
  588. if lg.code == 0 {
  589. lg.code = 200
  590. }
  591. n, err := lg.ResponseWriter.Write(bs)
  592. lg.bytes += n
  593. return n, err
  594. }
  595. // Hijack implements http.Hijacker. Note that hijacking can still fail
  596. // because the wrapped ResponseWriter is not required to implement
  597. // Hijacker, as this breaks HTTP/2.
  598. func (lg *loggingResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
  599. h, ok := lg.ResponseWriter.(http.Hijacker)
  600. if !ok {
  601. return nil, nil, errors.New("ResponseWriter is not a Hijacker")
  602. }
  603. conn, buf, err := h.Hijack()
  604. if err == nil {
  605. lg.hijacked = true
  606. }
  607. return conn, buf, err
  608. }
  609. func (lg loggingResponseWriter) Flush() {
  610. f, _ := lg.ResponseWriter.(http.Flusher)
  611. if f == nil {
  612. lg.logf("[unexpected] tried to Flush a ResponseWriter that can't flush")
  613. return
  614. }
  615. f.Flush()
  616. }
  617. func (lg *loggingResponseWriter) Unwrap() http.ResponseWriter {
  618. return lg.ResponseWriter
  619. }
  620. // errorHandler is an http.Handler that wraps a ReturnHandler to render the
  621. // returned errors to the client and pass them back to any logHandlers.
  622. type errorHandler struct {
  623. rh ReturnHandler
  624. opts ErrorOptions
  625. }
  626. // ServeHTTP implements the http.Handler interface.
  627. func (h errorHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  628. // Keep track of whether a response gets written.
  629. lw, ok := w.(*loggingResponseWriter)
  630. if !ok {
  631. lw = newLogResponseWriter(h.opts.Logf, w, r)
  632. }
  633. var err error
  634. defer func() {
  635. // In case the handler panics, we want to recover and continue logging
  636. // the error before logging it (or re-panicking if we couldn't log).
  637. rec := recover()
  638. if rec != nil {
  639. err = panic2err(rec)
  640. }
  641. if err == nil {
  642. return
  643. }
  644. if h.handleError(w, r, lw, err) {
  645. return
  646. }
  647. if rec != nil {
  648. // If we weren't able to log the panic somewhere, throw it up the
  649. // stack to someone who can.
  650. panic(rec)
  651. }
  652. }()
  653. err = h.rh.ServeHTTPReturn(lw, r)
  654. }
  655. func (h errorHandler) handleError(w http.ResponseWriter, r *http.Request, lw *loggingResponseWriter, err error) bool {
  656. var logged bool
  657. // Extract a presentable, loggable error.
  658. var hOK bool
  659. var hErr HTTPError
  660. if errors.As(err, &hErr) {
  661. hOK = true
  662. if hErr.Code == 0 {
  663. lw.logf("[unexpected] HTTPError %v did not contain an HTTP status code, sending internal server error", hErr)
  664. hErr.Code = http.StatusInternalServerError
  665. }
  666. } else if v, ok := vizerror.As(err); ok {
  667. hErr = Error(http.StatusInternalServerError, v.Error(), nil)
  668. } else if reqCancelled(r, err) {
  669. // 499 is the Nginx convention meaning "Client Closed Connection".
  670. if errors.Is(err, context.Canceled) || errors.Is(err, http.ErrAbortHandler) {
  671. hErr = Error(499, "", err)
  672. } else {
  673. hErr = Error(499, "", fmt.Errorf("%w: %w", context.Canceled, err))
  674. }
  675. } else {
  676. // Omit the friendly message so HTTP logs show the bare error that was
  677. // returned and we know it's not a HTTPError.
  678. hErr = Error(http.StatusInternalServerError, "", err)
  679. }
  680. // Tell the logger what error we wrote back to the client.
  681. if pb := errCallback.Value(r.Context()); pb != nil {
  682. pb(hErr)
  683. logged = true
  684. }
  685. if r.Context().Err() != nil {
  686. return logged
  687. }
  688. if lw.code != 0 {
  689. if hOK && hErr.Code != lw.code {
  690. lw.logf("[unexpected] handler returned HTTPError %v, but already sent response with code %d", hErr, lw.code)
  691. }
  692. return logged
  693. }
  694. // Set a default error message from the status code. Do this after we pass
  695. // the error back to the logger so that `return errors.New("oh")` logs as
  696. // `"err": "oh"`, not `"err": "Internal Server Error: oh"`.
  697. if hErr.Msg == "" {
  698. switch hErr.Code {
  699. case 499:
  700. hErr.Msg = "Client Closed Request"
  701. default:
  702. hErr.Msg = http.StatusText(hErr.Code)
  703. }
  704. }
  705. // If OnError panics before a response is written, write a bare 500 back.
  706. // OnError panics are thrown further up the stack.
  707. defer func() {
  708. if lw.code == 0 {
  709. if rec := recover(); rec != nil {
  710. w.WriteHeader(http.StatusInternalServerError)
  711. panic(rec)
  712. }
  713. }
  714. }()
  715. h.opts.OnError(w, r, hErr)
  716. return logged
  717. }
  718. // panic2err converts a recovered value to an error containing the panic stack trace.
  719. func panic2err(recovered any) error {
  720. if recovered == nil {
  721. return nil
  722. }
  723. if recovered == http.ErrAbortHandler {
  724. return http.ErrAbortHandler
  725. }
  726. // Even if r is an error, do not wrap it as an error here as
  727. // that would allow things like panic(vizerror.New("foo"))
  728. // which is really hard to define the behavior of.
  729. var stack [10000]byte
  730. n := runtime.Stack(stack[:], false)
  731. return &panicError{
  732. rec: recovered,
  733. stack: stack[:n],
  734. }
  735. }
  736. // panicError is an error that contains a panic.
  737. type panicError struct {
  738. rec any
  739. stack []byte
  740. }
  741. func (e *panicError) Error() string {
  742. return fmt.Sprintf("panic: %v\n\n%s", e.rec, e.stack)
  743. }
  744. func (e *panicError) Unwrap() error {
  745. err, _ := e.rec.(error)
  746. return err
  747. }
  748. // reqCancelled returns true if err is http.ErrAbortHandler or r.Context.Err()
  749. // is context.Canceled.
  750. func reqCancelled(r *http.Request, err error) bool {
  751. return errors.Is(err, http.ErrAbortHandler) || r.Context().Err() == context.Canceled
  752. }
  753. // WriteHTTPError is the default error response formatter.
  754. func WriteHTTPError(w http.ResponseWriter, r *http.Request, e HTTPError) {
  755. // Don't write a response if we've hit a cancellation/abort.
  756. if r.Context().Err() != nil || errors.Is(e.Err, http.ErrAbortHandler) {
  757. return
  758. }
  759. // Default headers set by http.Error.
  760. h := w.Header()
  761. h.Set("Content-Type", "text/plain; charset=utf-8")
  762. h.Set("X-Content-Type-Options", "nosniff")
  763. // Custom headers from the error.
  764. for k, vs := range e.Header {
  765. h[k] = vs
  766. }
  767. // Write the msg back to the user.
  768. w.WriteHeader(e.Code)
  769. fmt.Fprint(w, e.Msg)
  770. // If it's a plaintext message, add line breaks and RequestID.
  771. if strings.HasPrefix(h.Get("Content-Type"), "text/plain") {
  772. io.WriteString(w, "\n")
  773. if id := RequestIDFromContext(r.Context()); id != "" {
  774. io.WriteString(w, id.String())
  775. io.WriteString(w, "\n")
  776. }
  777. }
  778. }
  779. // HTTPError is an error with embedded HTTP response information.
  780. //
  781. // It is the error type to be (optionally) used by Handler.ServeHTTPReturn.
  782. type HTTPError struct {
  783. Code int // HTTP response code to send to client; 0 means 500
  784. Msg string // Response body to send to client
  785. Err error // Detailed error to log on the server
  786. Header http.Header // Optional set of HTTP headers to set in the response
  787. }
  788. // Error implements the error interface.
  789. func (e HTTPError) Error() string { return fmt.Sprintf("httperror{%d, %q, %v}", e.Code, e.Msg, e.Err) }
  790. func (e HTTPError) Unwrap() error { return e.Err }
  791. // Error returns an HTTPError containing the given information.
  792. func Error(code int, msg string, err error) HTTPError {
  793. return HTTPError{Code: code, Msg: msg, Err: err}
  794. }
  795. // VarzHandler writes expvar values as Prometheus metrics.
  796. // TODO: migrate all users to varz.Handler or promvarz.Handler and remove this.
  797. func VarzHandler(w http.ResponseWriter, r *http.Request) {
  798. varz.Handler(w, r)
  799. }
  800. // CleanRedirectURL ensures that urlStr is a valid redirect URL to the
  801. // current server, or one of allowedHosts. Returns the cleaned URL or
  802. // a validation error.
  803. func CleanRedirectURL(urlStr string, allowedHosts []string) (*url.URL, error) {
  804. if urlStr == "" {
  805. return &url.URL{}, nil
  806. }
  807. // In some places, we unfortunately query-escape the redirect URL
  808. // too many times, and end up needing to redirect to a URL that's
  809. // still escaped by one level. Try to unescape the input.
  810. unescaped, err := url.QueryUnescape(urlStr)
  811. if err == nil && unescaped != urlStr {
  812. urlStr = unescaped
  813. }
  814. // Go's URL parser and browser URL parsers disagree on the meaning
  815. // of malformed HTTP URLs. Given the input https:/evil.com, Go
  816. // parses it as hostname="", path="/evil.com". Browsers parse it
  817. // as hostname="evil.com", path="". This means that, using
  818. // malformed URLs, an attacker could trick us into approving of a
  819. // "local" redirect that in fact sends people elsewhere.
  820. //
  821. // This very blunt check enforces that we'll only process
  822. // redirects that are definitely well-formed URLs.
  823. //
  824. // Note that the check for just / also allows URLs of the form
  825. // "//foo.com/bar", which are scheme-relative redirects. These
  826. // must be handled with care below when determining whether a
  827. // redirect is relative to the current host. Notably,
  828. // url.URL.IsAbs reports // URLs as relative, whereas we want to
  829. // treat them as absolute redirects and verify the target host.
  830. if !hasSafeRedirectPrefix(urlStr) {
  831. return nil, fmt.Errorf("invalid redirect URL %q", urlStr)
  832. }
  833. url, err := url.Parse(urlStr)
  834. if err != nil {
  835. return nil, fmt.Errorf("invalid redirect URL %q: %w", urlStr, err)
  836. }
  837. // Redirects to self are always allowed. A self redirect must
  838. // start with url.Path, all prior URL sections must be empty.
  839. isSelfRedirect := url.Scheme == "" && url.Opaque == "" && url.User == nil && url.Host == ""
  840. if isSelfRedirect {
  841. return url, nil
  842. }
  843. for _, allowed := range allowedHosts {
  844. if strings.EqualFold(allowed, url.Hostname()) {
  845. return url, nil
  846. }
  847. }
  848. return nil, fmt.Errorf("disallowed target host %q in redirect URL %q", url.Hostname(), urlStr)
  849. }
  850. // hasSafeRedirectPrefix reports whether url starts with a slash, or
  851. // one of the case-insensitive strings "http://" or "https://".
  852. func hasSafeRedirectPrefix(url string) bool {
  853. if len(url) >= 1 && url[0] == '/' {
  854. return true
  855. }
  856. const http = "http://"
  857. if len(url) >= len(http) && strings.EqualFold(url[:len(http)], http) {
  858. return true
  859. }
  860. const https = "https://"
  861. if len(url) >= len(https) && strings.EqualFold(url[:len(https)], https) {
  862. return true
  863. }
  864. return false
  865. }
  866. // AddBrowserHeaders sets various HTTP security headers for browser-facing endpoints.
  867. //
  868. // The specific headers:
  869. // - require HTTPS access (HSTS)
  870. // - disallow iframe embedding
  871. // - mitigate MIME confusion attacks
  872. //
  873. // These headers are based on
  874. // https://infosec.mozilla.org/guidelines/web_security
  875. func AddBrowserHeaders(w http.ResponseWriter) {
  876. w.Header().Set("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
  877. w.Header().Set("Content-Security-Policy", "default-src 'self'; frame-ancestors 'none'; form-action 'self'; base-uri 'self'; block-all-mixed-content; object-src 'none'")
  878. w.Header().Set("X-Frame-Options", "DENY")
  879. w.Header().Set("X-Content-Type-Options", "nosniff")
  880. }
  881. // BrowserHeaderHandler wraps the provided http.Handler with a call to
  882. // AddBrowserHeaders.
  883. func BrowserHeaderHandler(h http.Handler) http.Handler {
  884. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  885. AddBrowserHeaders(w)
  886. h.ServeHTTP(w, r)
  887. })
  888. }
  889. // BrowserHeaderHandlerFunc wraps the provided http.HandlerFunc with a call to
  890. // AddBrowserHeaders.
  891. func BrowserHeaderHandlerFunc(h http.HandlerFunc) http.HandlerFunc {
  892. return func(w http.ResponseWriter, r *http.Request) {
  893. AddBrowserHeaders(w)
  894. h.ServeHTTP(w, r)
  895. }
  896. }