diff --git a/intel/geoip/location.go b/intel/geoip/location.go index 964d7ea0..823aa05e 100644 --- a/intel/geoip/location.go +++ b/intel/geoip/location.go @@ -3,7 +3,9 @@ package geoip import ( "encoding/binary" "net" + "strings" + "github.com/safing/portbase/utils" "github.com/umahmood/haversine" ) @@ -56,11 +58,11 @@ type Coordinates struct { */ const ( - weightContinentMatch = 25 - weightCountryMatch = 20 - weightASOrgMatch = 15 - weightASNMatch = 10 - weightCoordinateDistance = 30 + weightContinentMatch = 20 + weightCountryMatch = 15 + weightASOrgMatch = 10 + weightASNMatch = 5 + weightCoordinateDistance = 50 ) /* @@ -94,11 +96,14 @@ func (l *Location) EstimateNetworkProximity(to *Location) (proximity float32) { } switch { - case l.AutonomousSystemNumber != 0 && l.AutonomousSystemNumber == to.AutonomousSystemNumber: + case l.AutonomousSystemNumber == to.AutonomousSystemNumber && + l.AutonomousSystemNumber != 0: // Rely more on the ASN data, as it is more accurate than the ASOrg data, // especially when combining location data from multiple sources. proximity += weightASOrgMatch + weightASNMatch - case l.AutonomousSystemOrganization != "" && l.AutonomousSystemOrganization == to.AutonomousSystemOrganization: + case l.AutonomousSystemOrganization == to.AutonomousSystemOrganization && + l.AutonomousSystemNumber != 0 && // Check if an ASN is set. If the ASOrg is known, the ASN must be too. + !ASOrgUnknown(l.AutonomousSystemOrganization): // Check if the ASOrg name is valid. proximity += weightASOrgMatch } @@ -183,3 +188,20 @@ func PrimitiveNetworkProximity(from net.IP, to net.IP, ipVersion uint8) int { return 0 } } + +var unknownASOrgNames = []string{ + "", // Expected default for unknown. + "not routed", // Observed as "Not routed" in data set. + "unknown", // Observed as "UNKNOWN" in online data set. + "nil", // Programmatic unknown value. + "null", // Programmatic unknown value. + "undef", // Programmatic unknown value. + "undefined", // Programmatic unknown value. +} + +func ASOrgUnknown(asOrg string) bool { + return utils.StringInSlice( + unknownASOrgNames, + strings.ToLower(asOrg), + ) +} diff --git a/netenv/addresses.go b/netenv/addresses.go index 206d174d..053b5cd0 100644 --- a/netenv/addresses.go +++ b/netenv/addresses.go @@ -76,14 +76,15 @@ func IsMyIP(ip net.IP) (yes bool, err error) { // Check if current data matches IP. // Matching on somewhat older data is not a problem, as these IPs would not // just randomly pop up somewhere else that fast. - mine, matched := checkIfMyIP(ip) - if matched { - return mine, nil - } - - // Check if the network changed. - if !myNetworksNetworkChangedFlag.IsSet() { - // Network did not change, return "no match". + mine, myNet := checkIfMyIP(ip) + switch { + case mine: + // IP matched. + return true, nil + case myNetworksNetworkChangedFlag.IsSet(): + // The network changed, so we need to refresh the data. + case myNet: + // IP is one of the networks and nothing changed, so this is not our IP. return false, nil } @@ -104,13 +105,13 @@ func IsMyIP(ip net.IP) (yes bool, err error) { } myNetworks = make([]*net.IPNet, 0, len(interfaceNetworks)) for _, ifNet := range interfaceNetworks { - net, ok := ifNet.(*net.IPNet) + ipNet, ok := ifNet.(*net.IPNet) if !ok { log.Warningf("netenv: interface network of unexpected type %T", ifNet) continue } - myNetworks = append(myNetworks, net) + myNetworks = append(myNetworks, ipNet) } // Reset error. @@ -126,7 +127,7 @@ func IsMyIP(ip net.IP) (yes bool, err error) { return false, nil } -func checkIfMyIP(ip net.IP) (mine bool, matched bool) { +func checkIfMyIP(ip net.IP) (mine bool, myNet bool) { // Check against assigned IPs. for _, myNet := range myNetworks { if ip.Equal(myNet.IP) { diff --git a/netenv/location.go b/netenv/location.go index d4c03604..dc089820 100644 --- a/netenv/location.go +++ b/netenv/location.go @@ -205,6 +205,7 @@ func SetInternetLocation(ip net.IP, source DeviceLocationSource) (dl *DeviceLoca geoLoc, err := geoip.GetLocation(ip) if err != nil { log.Warningf("netenv: failed to get geolocation data of %s (from %s): %s", ip, source, err) + return nil, false } else { loc.Location = geoLoc } @@ -214,6 +215,10 @@ func SetInternetLocation(ip net.IP, source DeviceLocationSource) (dl *DeviceLoca } func addLocation(dl *DeviceLocation) { + if dl == nil { + return + } + locationsLock.Lock() defer locationsLock.Unlock() diff --git a/netenv/network-change.go b/netenv/network-change.go index 642b534d..721ffd36 100644 --- a/netenv/network-change.go +++ b/netenv/network-change.go @@ -40,8 +40,8 @@ serviceLoop: for { trigger := false - timeout := time.Minute - if GetOnlineStatus() != StatusOnline { + timeout := 15 * time.Second + if !Online() { timeout = time.Second } // wait for trigger @@ -62,7 +62,7 @@ serviceLoop: hasher := sha1.New() //nolint:gosec // not used for security interfaces, err := net.Interfaces() if err != nil { - log.Warningf("environment: failed to get interfaces: %s", err) + log.Warningf("netenv: failed to get interfaces: %s", err) continue } for _, iface := range interfaces { @@ -72,7 +72,7 @@ serviceLoop: // log.Tracef("adding: %s", iface.Flags.String()) addrs, err := iface.Addrs() if err != nil { - log.Warningf("environment: failed to get addrs from interface %s: %s", iface.Name, err) + log.Warningf("netenv: failed to get addrs from interface %s: %s", iface.Name, err) continue } for _, addr := range addrs {