hostinfo, tailcfg: add desktop detection on Linux to hostinfo

From the machines tab its hard to differenciate desktop Linux installs from
server Linux installs. Transmitting this information should make this
determination a lot easier.

Due to the reality that tailscaled is likely a system process, the standard
checks based on XDG_SESSION_TYPE or DISPLAY environment variables are not
possible (those variables won't be set). Instead, we look for listening
unix sockets that are typical of desktop installs.

Signed-off-by: Tom DNetto <tom@tailscale.com>
pull/4438/head
Tom DNetto 2 years ago committed by Brad Fitzpatrick
parent 9f1dd716e8
commit 24cd26534f

@ -17,11 +17,14 @@ import (
"go4.org/mem"
"tailscale.com/tailcfg"
"tailscale.com/types/opt"
"tailscale.com/util/dnsname"
"tailscale.com/util/lineread"
"tailscale.com/version"
)
var started = time.Now()
// New returns a partially populated Hostinfo for the current host.
func New() *tailcfg.Hostinfo {
hostname, _ := os.Hostname()
@ -31,6 +34,7 @@ func New() *tailcfg.Hostinfo {
Hostname: hostname,
OS: version.OS(),
OSVersion: GetOSVersion(),
Desktop: desktop(),
Package: packageTypeCached(),
GoArch: runtime.GOARCH,
DeviceModel: deviceModel(),
@ -97,6 +101,7 @@ func GetEnvType() EnvType {
var (
deviceModelAtomic atomic.Value // of string
osVersionAtomic atomic.Value // of string
desktopAtomic atomic.Value // of opt.Bool
packagingType atomic.Value // of string
)
@ -117,6 +122,31 @@ func deviceModel() string {
return s
}
func desktop() (ret opt.Bool) {
if runtime.GOOS != "linux" {
return opt.Bool("")
}
if v := desktopAtomic.Load(); v != nil {
v, _ := v.(opt.Bool)
return v
}
seenDesktop := false
lineread.File("/proc/net/unix", func(line []byte) error {
seenDesktop = seenDesktop || mem.Contains(mem.B(line), mem.S(" @/tmp/dbus-"))
seenDesktop = seenDesktop || mem.Contains(mem.B(line), mem.S(".X11-unix"))
seenDesktop = seenDesktop || mem.Contains(mem.B(line), mem.S("/wayland-1"))
return nil
})
ret.Set(seenDesktop)
// Only cache after a minute - compositors might not have started yet.
if time.Since(started) > time.Minute {
desktopAtomic.Store(ret)
}
return ret
}
func getEnvType() EnvType {
if inKnative() {
return KNative

@ -460,6 +460,7 @@ type Hostinfo struct {
BackendLogID string `json:",omitempty"` // logtail ID of backend instance
OS string `json:",omitempty"` // operating system the client runs on (a version.OS value)
OSVersion string `json:",omitempty"` // operating system version, with optional distro prefix ("Debian 10.4", "Windows 10 Pro 10.0.19041")
Desktop opt.Bool `json:",omitempty"` // if a desktop was detected on Linux
Package string `json:",omitempty"` // Tailscale package to disambiguate ("choco", "appstore", etc; "" for unknown)
DeviceModel string `json:",omitempty"` // mobile phone model ("Pixel 3a", "iPhone12,3")
Hostname string `json:",omitempty"` // name of the host the client runs on

@ -117,6 +117,7 @@ var _HostinfoCloneNeedsRegeneration = Hostinfo(struct {
BackendLogID string
OS string
OSVersion string
Desktop opt.Bool
Package string
DeviceModel string
Hostname string

@ -28,7 +28,7 @@ func fieldsOf(t reflect.Type) (fields []string) {
func TestHostinfoEqual(t *testing.T) {
hiHandles := []string{
"IPNVersion", "FrontendLogID", "BackendLogID",
"OS", "OSVersion", "Package", "DeviceModel", "Hostname",
"OS", "OSVersion", "Desktop", "Package", "DeviceModel", "Hostname",
"ShieldsUp", "ShareeNode",
"GoArch",
"RoutableIPs", "RequestTags",

Loading…
Cancel
Save