diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 741e4ce90..2d2d0f90d 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -3313,3 +3313,38 @@ func (b *LocalBackend) HandleSSHConn(c net.Conn) error { } return b.sshServer.HandleSSHConn(c) } + +// HandleQuad100Port80Conn serves http://100.100.100.100/ on port 80 (and +// the equivalent tsaddr.TailscaleServiceIPv6 address). +func (b *LocalBackend) HandleQuad100Port80Conn(c net.Conn) { + var s http.Server + s.Handler = http.HandlerFunc(b.handleQuad100Port80Conn) + s.Serve(netutil.NewOneConnListener(c, nil)) +} + +func (b *LocalBackend) handleQuad100Port80Conn(w http.ResponseWriter, r *http.Request) { + w.Header().Set("X-Frame-Options", "DENY") + w.Header().Set("Content-Security-Policy", "default-src 'self';") + if r.Method != "GET" && r.Method != "HEAD" { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + return + } + + b.mu.Lock() + defer b.mu.Unlock() + + io.WriteString(w, "

Tailscale

\n") + if b.netMap == nil { + io.WriteString(w, "No netmap.\n") + return + } + if len(b.netMap.Addresses) == 0 { + io.WriteString(w, "No local addresses.\n") + return + } + io.WriteString(w, "

Local addresses:

\n") +} diff --git a/wgengine/netstack/netstack.go b/wgengine/netstack/netstack.go index 03e03383a..7e6067b99 100644 --- a/wgengine/netstack/netstack.go +++ b/wgengine/netstack/netstack.go @@ -791,7 +791,12 @@ func (ns *Impl) acceptTCP(r *tcp.ForwarderRequest) { return } } + if reqDetails.LocalPort == 80 && (dialIP == magicDNSIP || dialIP == magicDNSIPv6) { + ns.lb.HandleQuad100Port80Conn(c) + return + } } + if ns.ForwardTCPIn != nil { ns.ForwardTCPIn(c, reqDetails.LocalPort) return