Some checks failed
Build Multi-Platform Binaries / build-frontend (push) Successful in 34s
Build Multi-Platform Binaries / build-binaries (amd64, linux, client, true) (push) Successful in 1m20s
Build Multi-Platform Binaries / build-binaries (amd64, darwin, server, false) (push) Successful in 1m33s
Build Multi-Platform Binaries / build-binaries (amd64, windows, client, true) (push) Successful in 1m16s
Build Multi-Platform Binaries / build-binaries (amd64, linux, server, true) (push) Successful in 1m48s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, client, true) (push) Successful in 1m7s
Build Multi-Platform Binaries / build-binaries (amd64, windows, server, true) (push) Successful in 1m46s
Build Multi-Platform Binaries / build-binaries (arm64, darwin, server, false) (push) Successful in 1m31s
Build Multi-Platform Binaries / build-binaries (arm, 7, linux, server, true) (push) Successful in 1m58s
Build Multi-Platform Binaries / build-binaries (arm64, linux, client, true) (push) Successful in 1m35s
Build Multi-Platform Binaries / build-binaries (arm64, linux, server, true) (push) Has been cancelled
Build Multi-Platform Binaries / build-binaries (arm64, windows, server, false) (push) Has been cancelled
153 lines
3.0 KiB
Go
153 lines
3.0 KiB
Go
package tunnel
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"net"
|
|
"os"
|
|
"os/exec"
|
|
"runtime"
|
|
"sort"
|
|
"strings"
|
|
)
|
|
|
|
// getMachineID builds a stable fingerprint from multiple host identifiers
|
|
// and hashes the combined result into the client ID we expose externally.
|
|
func getMachineID() string {
|
|
return hashID(strings.Join(collectMachineIDParts(), "|"))
|
|
}
|
|
|
|
func collectMachineIDParts() []string {
|
|
parts := []string{"os=" + runtime.GOOS, "arch=" + runtime.GOARCH}
|
|
|
|
if id := getSystemMachineID(); id != "" {
|
|
parts = append(parts, "system="+id)
|
|
}
|
|
|
|
if hostname, err := os.Hostname(); err == nil && hostname != "" {
|
|
parts = append(parts, "host="+hostname)
|
|
}
|
|
|
|
if macs := getMACAddresses(); len(macs) > 0 {
|
|
parts = append(parts, "macs="+strings.Join(macs, ","))
|
|
}
|
|
|
|
if names := getInterfaceNames(); len(names) > 0 {
|
|
parts = append(parts, "ifaces="+strings.Join(names, ","))
|
|
}
|
|
|
|
return parts
|
|
}
|
|
|
|
func getSystemMachineID() string {
|
|
switch runtime.GOOS {
|
|
case "linux":
|
|
return getLinuxMachineID()
|
|
case "darwin":
|
|
return getDarwinMachineID()
|
|
case "windows":
|
|
return getWindowsMachineID()
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func getLinuxMachineID() string {
|
|
if data, err := os.ReadFile("/etc/machine-id"); err == nil {
|
|
return strings.TrimSpace(string(data))
|
|
}
|
|
if data, err := os.ReadFile("/var/lib/dbus/machine-id"); err == nil {
|
|
return strings.TrimSpace(string(data))
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func getDarwinMachineID() string {
|
|
cmd := exec.Command("ioreg", "-rd1", "-c", "IOPlatformExpertDevice")
|
|
output, err := cmd.Output()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
for _, line := range strings.Split(string(output), "\n") {
|
|
if !strings.Contains(line, "IOPlatformUUID") {
|
|
continue
|
|
}
|
|
|
|
parts := strings.Split(line, "=")
|
|
if len(parts) != 2 {
|
|
continue
|
|
}
|
|
|
|
uuid := strings.TrimSpace(parts[1])
|
|
return strings.Trim(uuid, "\"")
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func getWindowsMachineID() string {
|
|
cmd := exec.Command("reg", "query", `HKLM\SOFTWARE\Microsoft\Cryptography`, "/v", "MachineGuid")
|
|
output, err := cmd.Output()
|
|
if err != nil {
|
|
return ""
|
|
}
|
|
|
|
for _, line := range strings.Split(string(output), "\n") {
|
|
if !strings.Contains(line, "MachineGuid") {
|
|
continue
|
|
}
|
|
|
|
fields := strings.Fields(line)
|
|
if len(fields) >= 3 {
|
|
return fields[len(fields)-1]
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func getMACAddresses() []string {
|
|
interfaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
macs := make([]string, 0, len(interfaces))
|
|
for _, iface := range interfaces {
|
|
if iface.Flags&net.FlagLoopback != 0 {
|
|
continue
|
|
}
|
|
if len(iface.HardwareAddr) == 0 {
|
|
continue
|
|
}
|
|
macs = append(macs, iface.HardwareAddr.String())
|
|
}
|
|
|
|
sort.Strings(macs)
|
|
return macs
|
|
}
|
|
|
|
func getInterfaceNames() []string {
|
|
interfaces, err := net.Interfaces()
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
names := make([]string, 0, len(interfaces))
|
|
for _, iface := range interfaces {
|
|
if iface.Flags&net.FlagLoopback != 0 {
|
|
continue
|
|
}
|
|
names = append(names, iface.Name)
|
|
}
|
|
|
|
sort.Strings(names)
|
|
return names
|
|
}
|
|
|
|
func hashID(id string) string {
|
|
hash := sha256.Sum256([]byte(id))
|
|
return hex.EncodeToString(hash[:])[:16]
|
|
}
|