diff --git a/ipn/ipnlocal/local.go b/ipn/ipnlocal/local.go index 0b21c6bf5..f6173a763 100644 --- a/ipn/ipnlocal/local.go +++ b/ipn/ipnlocal/local.go @@ -1448,6 +1448,10 @@ func (b *LocalBackend) initPeerAPIListener() { } b.peerAPIListeners = nil + if len(b.netMap.Addresses) == 0 || b.netMap.SelfNode == nil { + return + } + var tunName string if ge, ok := b.e.(wgengine.InternalsGetter); ok { tunDev, _ := ge.GetInternals() @@ -1461,8 +1465,9 @@ func (b *LocalBackend) initPeerAPIListener() { continue } pln := &peerAPIListener{ - ln: ln, - lb: b, + ln: ln, + lb: b, + selfNode: b.netMap.SelfNode, } pln.urlStr = "http://" + net.JoinHostPort(a.IP.String(), strconv.Itoa(pln.Port())) diff --git a/ipn/ipnlocal/peerapi.go b/ipn/ipnlocal/peerapi.go index e04429840..390b45efc 100644 --- a/ipn/ipnlocal/peerapi.go +++ b/ipn/ipnlocal/peerapi.go @@ -67,9 +67,10 @@ func peerAPIListen(ip netaddr.IP, ifState *interfaces.State, tunIfName string) ( } type peerAPIListener struct { - ln net.Listener - lb *LocalBackend - urlStr string + ln net.Listener + lb *LocalBackend + urlStr string + selfNode *tailcfg.Node } func (pln *peerAPIListener) Port() int { @@ -110,14 +111,15 @@ func (pln *peerAPIListener) serve() { c.Close() continue } - pas := &peerAPIServer{ + h := &peerAPIHandler{ + isSelf: pln.selfNode.User == peerNode.User, remoteAddr: ipp, peerNode: peerNode, peerUser: peerUser, lb: pln.lb, } httpServer := &http.Server{ - Handler: pas, + Handler: h, } go httpServer.Serve(&oneConnListener{Listener: pln.ln, conn: c}) } @@ -141,19 +143,25 @@ func (l *oneConnListener) Accept() (c net.Conn, err error) { func (l *oneConnListener) Close() error { return nil } -type peerAPIServer struct { +// peerAPIHandler serves the Peer API for a source specific client. +type peerAPIHandler struct { remoteAddr netaddr.IPPort - peerNode *tailcfg.Node - peerUser tailcfg.UserProfile + isSelf bool // whether peerNode is owned by same user as this node + peerNode *tailcfg.Node // peerNode is who's making the request + peerUser tailcfg.UserProfile // profile of peerNode lb *LocalBackend } -func (s *peerAPIServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { +func (h *peerAPIHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { + who := h.peerUser.DisplayName fmt.Fprintf(w, `

Hello, %s (%v)

This is my Tailscale device. Your device is %v. -`, html.EscapeString(s.peerUser.DisplayName), s.remoteAddr.IP, html.EscapeString(s.peerNode.ComputedName)) +`, html.EscapeString(who), h.remoteAddr.IP, html.EscapeString(h.peerNode.ComputedName)) + if h.isSelf { + fmt.Fprintf(w, "

You are the owner of this node.\n") + } }