mirror of
https://github.com/gravitl/netmaker.git
synced 2026-02-04 18:18:56 +08:00
NM-214: Expect GeoInfo to come from Netclient (#3833)
* feat(go): expect geoinfo from netclient; * feat(go): add geoinfo util;
This commit is contained in:
parent
635d47ec3d
commit
f723fc5202
8 changed files with 128 additions and 71 deletions
|
|
@ -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{})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
128
utils/geoinfo.go
Normal file
128
utils/geoinfo.go
Normal file
|
|
@ -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
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue