diff --git a/controllers/enrollmentkeys.go b/controllers/enrollmentkeys.go index fab92dc4..4b1c322c 100644 --- a/controllers/enrollmentkeys.go +++ b/controllers/enrollmentkeys.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "net/http" - "os" "slices" "time" @@ -360,11 +359,6 @@ func handleHostRegister(w http.ResponseWriter, r *http.Request) { ) return } - if newHost.EndpointIP != nil { - newHost.Location, newHost.CountryCode = logic.GetHostLocInfo(newHost.EndpointIP.String(), os.Getenv("IP_INFO_TOKEN")) - } else if newHost.EndpointIPv6 != nil { - newHost.Location, newHost.CountryCode = logic.GetHostLocInfo(newHost.EndpointIPv6.String(), os.Getenv("IP_INFO_TOKEN")) - } pcviolations := []models.Violation{} skipViolatedNetworks := []string{} keyTags := make(map[models.TagID]struct{}) diff --git a/controllers/ext_client.go b/controllers/ext_client.go index c5f97426..b4aef2b2 100644 --- a/controllers/ext_client.go +++ b/controllers/ext_client.go @@ -7,7 +7,6 @@ import ( "fmt" "net" "net/http" - "os" "reflect" "strconv" "strings" @@ -784,9 +783,6 @@ func createExtClient(w http.ResponseWriter, r *http.Request) { } extclient.PublicEndpoint = customExtClient.PublicEndpoint extclient.Country = customExtClient.Country - if customExtClient.RemoteAccessClientID != "" && customExtClient.Location == "" { - extclient.Location, extclient.Country = logic.GetHostLocInfo(logic.GetClientIP(r), os.Getenv("IP_INFO_TOKEN")) - } extclient.Location = customExtClient.Location // JIT enforcement: Check if user has access (only for desktop app users) hasAccess, grant, err := logic.CheckJITAccess(extclient.Network, userName) @@ -956,9 +952,6 @@ func updateExtClient(w http.ResponseWriter, r *http.Request) { //remove old peer entry replacePeers = true } - if update.RemoteAccessClientID != "" && update.Location == "" { - update.Location, update.Country = logic.GetHostLocInfo(logic.GetClientIP(r), os.Getenv("IP_INFO_TOKEN")) - } newclient := logic.UpdateExtClient(&oldExtClient, &update) if newclient.DeviceID != "" && newclient.Enabled { // check for violations connecting from desktop app diff --git a/logic/hosts.go b/logic/hosts.go index 6816aa4d..fa814b4f 100644 --- a/logic/hosts.go +++ b/logic/hosts.go @@ -5,7 +5,6 @@ import ( "encoding/json" "errors" "fmt" - "os" "sort" "strings" "sync" @@ -34,8 +33,6 @@ var ( ErrInvalidHostID error = errors.New("invalid host id") ) -var GetHostLocInfo = func(ip, token string) (string, string) { return "", "" } - var CheckPostureViolations = func(d models.PostureCheckDeviceInfo, network models.NetworkID) (v []models.Violation, level models.Severity) { return []models.Violation{}, models.SeverityUnknown } @@ -261,11 +258,6 @@ func CreateHost(h *models.Host) error { } else { h.DNS = "no" } - if h.EndpointIP != nil { - h.Location, h.CountryCode = GetHostLocInfo(h.EndpointIP.String(), os.Getenv("IP_INFO_TOKEN")) - } else if h.EndpointIPv6 != nil { - h.Location, h.CountryCode = GetHostLocInfo(h.EndpointIPv6.String(), os.Getenv("IP_INFO_TOKEN")) - } if !GetFeatureFlags().EnableFlowLogs || !GetServerSettings().EnableFlowLogs { h.EnableFlowLogs = false diff --git a/migrate/migrate.go b/migrate/migrate.go index 109339e9..52430653 100644 --- a/migrate/migrate.go +++ b/migrate/migrate.go @@ -9,7 +9,6 @@ import ( "log" "math/big" "net" - "os" "time" "golang.org/x/exp/slog" @@ -618,16 +617,6 @@ func updateHosts() { host.AutoUpdate = true logic.UpsertHost(&host) } - if servercfg.IsPro && (host.Location == "" || host.CountryCode == "") { - if host.EndpointIP != nil { - host.Location, host.CountryCode = logic.GetHostLocInfo(host.EndpointIP.String(), os.Getenv("IP_INFO_TOKEN")) - } else if host.EndpointIPv6 != nil { - host.Location, host.CountryCode = logic.GetHostLocInfo(host.EndpointIPv6.String(), os.Getenv("IP_INFO_TOKEN")) - } - if host.Location != "" && host.CountryCode != "" { - logic.UpsertHost(&host) - } - } } } diff --git a/mq/handlers.go b/mq/handlers.go index 199b84de..84eb2afc 100644 --- a/mq/handlers.go +++ b/mq/handlers.go @@ -2,7 +2,6 @@ package mq import ( "encoding/json" - "os" mqtt "github.com/eclipse/paho.mqtt.golang" "github.com/google/uuid" @@ -300,13 +299,6 @@ func HandleHostCheckin(h, currentHost *models.Host) bool { (!h.EndpointIPv6.Equal(currentHost.EndpointIPv6)) || (h.OSFamily != currentHost.OSFamily) || (h.OSVersion != currentHost.OSVersion) || (h.KernelVersion != currentHost.KernelVersion) if ifaceDelta { // only save if something changes - if !h.EndpointIP.Equal(currentHost.EndpointIP) || !h.EndpointIPv6.Equal(currentHost.EndpointIPv6) || currentHost.Location == "" { - if h.EndpointIP != nil { - h.Location, h.CountryCode = logic.GetHostLocInfo(h.EndpointIP.String(), os.Getenv("IP_INFO_TOKEN")) - } else if h.EndpointIPv6 != nil { - h.Location, h.CountryCode = logic.GetHostLocInfo(h.EndpointIPv6.String(), os.Getenv("IP_INFO_TOKEN")) - } - } currentHost.EndpointIP = h.EndpointIP currentHost.EndpointIPv6 = h.EndpointIPv6 currentHost.Interfaces = h.Interfaces diff --git a/pro/initialize.go b/pro/initialize.go index 8e7a4e02..1b865d13 100644 --- a/pro/initialize.go +++ b/pro/initialize.go @@ -195,7 +195,6 @@ func InitPro() { logic.MigrateToGws = proLogic.MigrateToGws logic.GetFwRulesForNodeAndPeerOnGw = proLogic.GetFwRulesForNodeAndPeerOnGw logic.GetFwRulesForUserNodesOnGw = proLogic.GetFwRulesForUserNodesOnGw - logic.GetHostLocInfo = proLogic.GetHostLocInfo logic.GetFeatureFlags = proLogic.GetFeatureFlags logic.GetDeploymentMode = proLogic.GetDeploymentMode logic.GetNameserversForHost = proLogic.GetNameserversForHost diff --git a/pro/logic/metrics.go b/pro/logic/metrics.go index a850e80a..3b34046c 100644 --- a/pro/logic/metrics.go +++ b/pro/logic/metrics.go @@ -2,7 +2,6 @@ package logic import ( "encoding/json" - "net/http" "sync" "time" @@ -239,32 +238,3 @@ func updateNodeMetrics(currentNode *models.Node, newMetrics *models.Metrics) { slog.Debug("[metrics] node metrics data", "node ID", currentNode.ID, "metrics", newMetrics) } - -func GetHostLocInfo(ip, token string) (loc, country string) { - url := "https://ipinfo.io/" - if ip != "" { - url += ip - } - url += "/json" - if token != "" { - url += "?token=" + token - } - - client := http.Client{Timeout: 3 * time.Second} - resp, err := client.Get(url) - if err != nil { - return "", "" - } - defer resp.Body.Close() - - var data struct { - Loc string `json:"loc"` // Format: "lat,lon" - Country string `json:"country"` - } - if err := json.NewDecoder(resp.Body).Decode(&data); err != nil { - return "", "" - } - loc = data.Loc - country = data.Country - return -} diff --git a/utils/geoinfo.go b/utils/geoinfo.go new file mode 100644 index 00000000..38915048 --- /dev/null +++ b/utils/geoinfo.go @@ -0,0 +1,128 @@ +package utils + +import ( + "encoding/json" + "fmt" + "net/http" +) + +type GeoInfo struct { + IP string + CountryCode string + Location string +} + +// GetGeoInfo returns the ip, location and country code of the host it's called on. +func GetGeoInfo() (*GeoInfo, error) { + geoInfo, err := getGeoInfoFromIPAPI() + if err == nil { + return geoInfo, nil + } + + geoInfo, err = getGeoInfoFromCloudFlare() + if err == nil { + return geoInfo, nil + } + + return getGeoInfoFromIpInfo() +} + +func getGeoInfoFromIPAPI() (*GeoInfo, error) { + resp, err := http.Get("https://api.ipapi.is") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var data struct { + IP string `json:"ip"` + Location struct { + CountryCode string `json:"country_code"` + Latitude string `json:"latitude"` + Longitude string `json:"longitude"` + } `json:"location"` + } + + if resp.StatusCode != 200 { + return nil, fmt.Errorf("status code %d", resp.StatusCode) + } + + err = json.NewDecoder(resp.Body).Decode(&data) + if err != nil { + return nil, err + } + + return &GeoInfo{ + IP: data.IP, + Location: data.Location.Latitude + "," + data.Location.Longitude, + CountryCode: data.Location.CountryCode, + }, nil +} + +func getGeoInfoFromCloudFlare() (*GeoInfo, error) { + var geoInfo GeoInfo + resp, err := http.Get("https://speed.cloudflare.com/meta") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + respMap := make(map[string]interface{}) + err = json.NewDecoder(resp.Body).Decode(&respMap) + if err != nil { + return nil, err + } + + _, ok := respMap["clientIp"] + if ok { + geoInfo.IP = respMap["clientIp"].(string) + } + + _, ok = respMap["country"] + if ok { + geoInfo.CountryCode = respMap["country"].(string) + } + + var latitude, longitude string + _, ok = respMap["latitude"] + if ok { + latitude = respMap["latitude"].(string) + } + + _, ok = respMap["longitude"] + if ok { + longitude = respMap["longitude"].(string) + } + + if latitude != "" && longitude != "" { + geoInfo.Location = latitude + "," + longitude + } + + return &geoInfo, nil +} + +func getGeoInfoFromIpInfo() (*GeoInfo, error) { + var geoInfo GeoInfo + resp, err := http.Get("https://ipinfo.io/json") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var data struct { + IP string `json:"ip"` + Loc string `json:"loc"` + Country string `json:"country"` + } + + err = json.NewDecoder(resp.Body).Decode(&data) + if err != nil { + return nil, err + } + + geoInfo.IP = data.IP + geoInfo.CountryCode = data.Country + geoInfo.Location = data.Loc + + return &geoInfo, nil +}