cmd/hello: make whois client work on macOS against GUI client
"net"
"net/http"
"net/url"
+ "os"
+ "strconv"
"strings"
"tailscale.com/safesocket"
var (
httpAddr = flag.String("http", ":80", "address to run an HTTP server on, or empty for none")
httpsAddr = flag.String("https", ":443", "address to run an HTTPS server on, or empty for none")
+ testIP = flag.String("test-ip", "", "if non-empty, look up IP and exit before running a server")
)
func main() {
flag.Parse()
+ if *testIP != "" {
+ res, err := whoIs(*testIP)
+ if err != nil {
+ log.Fatal(err)
+ }
+ e := json.NewEncoder(os.Stdout)
+ e.SetIndent("", "\t")
+ e.Encode(res)
+ return
+ }
if !devMode() {
tmpl = template.Must(template.New("home").Parse(slurpHTML()))
}
@@ -113,6 +126,7 @@ func root(w http.ResponseWriter, r *http.Request) {
var data tmplData
if err != nil {
if devMode() {
+ log.Printf("warning: using fake data in dev mode due to whois lookup error: %v", err)
data = tmplData{
DisplayName: "Taily Scalerson",
LoginName: "taily@scaler.son",
@@ -153,13 +167,28 @@ func firstLabel(s string) string {
var tsSockClient = &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
+ // On macOS, when dialing from non-sandboxed program to sandboxed GUI running
+ // a TCP server on a random port, find the random port. For HTTP connections,
+ // we don't send the token. It gets added in an HTTP Basic-Auth header.
+ if port, _, err := safesocket.LocalTCPPortAndToken(); err == nil {
+ var d net.Dialer
+ return d.DialContext(ctx, "tcp", "localhost:"+strconv.Itoa(port))
+ }
return safesocket.ConnectDefault()
},
},
}
func whoIs(ip string) (*tailcfg.WhoIsResponse, error) {
- res, err := tsSockClient.Get("http://local-tailscaled.sock/localapi/v0/whois?ip=" + url.QueryEscape(ip))
+ ctx := context.Background()
+ req, err := http.NewRequestWithContext(ctx, "GET", "http://local-tailscaled.sock/localapi/v0/whois?ip="+url.QueryEscape(ip), nil)
+ if err != nil {
+ return nil, err
+ }
+ if _, token, err := safesocket.LocalTCPPortAndToken(); err == nil {
+ req.SetBasicAuth("", token)
+ }
+ res, err := tsSockClient.Do(req)
if err != nil {
return nil, err
}
