diff --git a/cmd/hello/hello.go b/cmd/hello/hello.go index 1f7439c0c..b88a93244 100644 --- a/cmd/hello/hello.go +++ b/cmd/hello/hello.go @@ -6,6 +6,7 @@ package main // import "tailscale.com/cmd/hello" import ( + "context" "encoding/json" "flag" "fmt" @@ -101,16 +102,35 @@ func root(w http.ResponseWriter, r *http.Request) { }) } +// tsSockClient does HTTP requests to the local tailscaled by dialing +// its Unix socket or whatever type of connection is required on the local +// system. +// TODO(bradfitz): do the macOS dial-the-sandbox dance like cmd/tailscale does. +var tsSockClient = &http.Client{ + Transport: &http.Transport{ + DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) { + var d net.Dialer + return d.DialContext(ctx, "unix", "/var/run/tailscale/tailscaled.sock") + }, + }, +} + func whoIs(ip string) (*tailcfg.WhoIsResponse, error) { - res, err := http.Get("http://127.0.0.1:4242/whois?ip=" + url.QueryEscape(ip)) + res, err := tsSockClient.Get("http://local-tailscaled.sock/localapi/v0/whois?ip=" + url.QueryEscape(ip)) if err != nil { return nil, err } defer res.Body.Close() + slurp, _ := ioutil.ReadAll(res.Body) if res.StatusCode != 200 { - slurp, _ := ioutil.ReadAll(res.Body) return nil, fmt.Errorf("HTTP %s: %s", res.Status, slurp) } r := new(tailcfg.WhoIsResponse) - return r, json.NewDecoder(res.Body).Decode(r) + if err := json.Unmarshal(slurp, r); err != nil { + if max := 200; len(slurp) > max { + slurp = slurp[:max] + } + return nil, fmt.Errorf("failed to parse JSON WhoIsResponse from %q", slurp) + } + return r, nil } diff --git a/ipn/ipnserver/server.go b/ipn/ipnserver/server.go index 69d160d52..dd8a39ab6 100644 --- a/ipn/ipnserver/server.go +++ b/ipn/ipnserver/server.go @@ -115,10 +115,11 @@ type server struct { // connIdentity represents the owner of a localhost TCP connection. type connIdentity struct { - Unknown bool - Pid int - UserID string - User *user.User + Unknown bool + Pid int + UserID string + User *user.User + IsUnixSock bool } // getConnIdentity returns the localhost TCP connection's identity information @@ -127,7 +128,9 @@ type connIdentity struct { // to be able to map it and couldn't. func (s *server) getConnIdentity(c net.Conn) (ci connIdentity, err error) { if runtime.GOOS != "windows" { // for now; TODO: expand to other OSes - return connIdentity{Unknown: true}, nil + ci = connIdentity{Unknown: true} + _, ci.IsUnixSock = c.(*net.UnixConn) + return ci, nil } la, err := netaddr.ParseIPPort(c.LocalAddr().String()) if err != nil { @@ -622,7 +625,7 @@ func Run(ctx context.Context, logf logger.Logf, logid string, getEngine func() ( opts.DebugMux.HandleFunc("/debug/ipn", func(w http.ResponseWriter, r *http.Request) { serveHTMLStatus(w, b) }) - opts.DebugMux.Handle("/whois", whoIsHandler{b}) + opts.DebugMux.Handle("/localapi/v0/whois", whoIsHandler{b}) } server.b = b @@ -863,6 +866,10 @@ func (psc *protoSwitchConn) Close() error { func (s *server) localhostHandler(ci connIdentity) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if ci.IsUnixSock && r.URL.Path == "/localapi/v0/whois" { + whoIsHandler{s.b}.ServeHTTP(w, r) + return + } if ci.Unknown { io.WriteString(w, "Tailscale

Tailscale

This is the local Tailscale daemon.") return