|
|
|
|
@ -16,6 +16,8 @@ import ( |
|
|
|
|
"net" |
|
|
|
|
"net/http" |
|
|
|
|
"net/url" |
|
|
|
|
"os" |
|
|
|
|
"strconv" |
|
|
|
|
"strings" |
|
|
|
|
|
|
|
|
|
"tailscale.com/safesocket" |
|
|
|
|
@ -25,10 +27,21 @@ import ( |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
|