MCPcopy
hub / github.com/tailscale/tailscale / requireTailscaleIP

Method requireTailscaleIP

client/web/web.go:393–436  ·  view source on GitHub ↗

requireTailscaleIP redirects an incoming request if the HTTP request was not made to a bare Tailscale IP address. The request will be redirected to the Tailscale IP, port 5252, with the original request path. This allows any custom hostname to be used to access the device, but protects against DNS r

(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

391// This allows any custom hostname to be used to access the device, but protects against DNS rebinding attacks.
392// Returns true if the request has been fully handled, either be returning a redirect or an HTTP error.
393func (s *Server) requireTailscaleIP(w http.ResponseWriter, r *http.Request) (handled bool) {
394 const (
395 ipv4ServiceHost = tsaddr.TailscaleServiceIPString
396 ipv6ServiceHost = "[" + tsaddr.TailscaleServiceIPv6String + "]"
397 )
398 // allow requests on quad-100 (or ipv6 equivalent)
399 host := strings.TrimSuffix(r.Host, ":80")
400 if host == ipv4ServiceHost || host == ipv6ServiceHost {
401 return false
402 }
403
404 st, err := s.lc.StatusWithoutPeers(r.Context())
405 if err != nil {
406 s.logf("error getting status: %v", err)
407 http.Error(w, "internal error", http.StatusInternalServerError)
408 return true
409 }
410
411 ipv4, ipv6 := s.selfNodeAddresses(r, st)
412 if r.Host == fmt.Sprintf("%s:%d", ipv4.String(), ListenPort) {
413 return false // already accessing over Tailscale IP
414 }
415 if r.Host == fmt.Sprintf("[%s]:%d", ipv6.String(), ListenPort) {
416 return false // already accessing over Tailscale IP
417 }
418
419 // Not currently accessing via Tailscale IP,
420 // redirect them.
421
422 var preferV6 bool
423 if ap, err := netip.ParseAddrPort(r.Host); err == nil {
424 // If Host was already ipv6, keep them on same protocol.
425 preferV6 = ap.Addr().Is6()
426 }
427
428 newURL := *r.URL
429 if (preferV6 && ipv6.IsValid()) || !ipv4.IsValid() {
430 newURL.Host = fmt.Sprintf("[%s]:%d", ipv6.String(), ListenPort)
431 } else {
432 newURL.Host = fmt.Sprintf("%s:%d", ipv4.String(), ListenPort)
433 }
434 http.Redirect(w, r, newURL.String(), http.StatusMovedPermanently)
435 return true
436}
437
438// selfNodeAddresses return the Tailscale IPv4 and IPv6 addresses for the self node.
439// st is expected to be a status with peers included.

Callers 2

serveMethod · 0.95
TestRequireTailscaleIPFunction · 0.95

Calls 9

logfMethod · 0.95
selfNodeAddressesMethod · 0.95
RedirectMethod · 0.80
StatusWithoutPeersMethod · 0.65
ContextMethod · 0.65
ErrorMethod · 0.65
StringMethod · 0.65
AddrMethod · 0.45
IsValidMethod · 0.45

Tested by 1

TestRequireTailscaleIPFunction · 0.76