Merge pull request #1134 from safing/fix/traceroute-location

Fix traceroute locating, improvements
This commit is contained in:
Daniel Hovie 2023-03-17 09:10:36 +01:00 committed by GitHub
commit 8ecb8a4156
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 12 deletions

View file

@ -135,8 +135,8 @@ func (l *Location) EstimateNetworkProximity(to *Location) (proximity float32) {
toCoords := haversine.Coord{Lat: to.Coordinates.Latitude, Lon: to.Coordinates.Longitude}
_, km := haversine.Distance(fromCoords, toCoords)
if km <= 50 && accuracy <= 100 {
// Give a flat out ten for highly accurate coordinates within 50km.
if km <= 100 && accuracy <= 100 {
// Give the full value for highly accurate coordinates within 100km.
proximity += weightCoordinateDistance
} else {
// Else, take a percentage.

View file

@ -6,7 +6,6 @@ import (
"net"
"sort"
"sync"
"syscall"
"time"
"github.com/google/gopacket/layers"
@ -108,6 +107,8 @@ func (dls *DeviceLocations) AddLocation(dl *DeviceLocation) {
// Sort locations.
sort.Sort(sortLocationsByAccuracy(dls.All))
log.Debugf("netenv: added new device location to IPv%d scope: %s from %s", dl.IPVersion, dl, dl.Source)
}
// DeviceLocation represents a single IP and metadata. It must not be changed
@ -288,6 +289,7 @@ func GetInternetLocation() (deviceLocations *DeviceLocations, ok bool) {
// Create new location list.
dls := &DeviceLocations{}
log.Debug("netenv: getting new device locations")
// Check interfaces for global addresses.
v4ok, v6ok := getLocationFromInterfaces(dls)
@ -359,11 +361,11 @@ func getLocationFromUPnP() (ok bool) {
func getLocationFromTraceroute(dls *DeviceLocations) (dl *DeviceLocation, err error) {
// Create connection.
conn, err := net.ListenPacket("ip4:icmp", "")
conn, err := icmp.ListenPacket("ip4:icmp", "")
if err != nil {
return nil, fmt.Errorf("failed to open icmp conn: %w", err)
}
v4Conn := ipv4.NewPacketConn(conn)
v4Conn := conn.IPv4PacketConn()
// Generate a random ID for the ICMP packets.
generatedID, err := rng.Number(0xFFFF) // uint16
@ -393,7 +395,7 @@ nextHop:
for i := 1; i <= maxHops; i++ {
minSeq := msgSeq + 1
repeat:
repeatHop:
for j := 1; j <= 2; j++ { // Try every hop twice.
// Increase sequence number.
msgSeq++
@ -412,11 +414,16 @@ nextHop:
}
// Send ICMP packet.
if _, err := conn.WriteTo(pingPacket, locationTestingIPv4Addr); err != nil {
var opErr *net.OpError
if errors.As(err, &opErr) && errors.Is(opErr.Err, syscall.ENOBUFS) {
continue
// Try to send three times, as this can be flaky.
sendICMP:
for i := 0; i < 3; i++ {
_, err = conn.WriteTo(pingPacket, locationTestingIPv4Addr)
if err == nil {
break sendICMP
}
time.Sleep(30 * time.Millisecond)
}
if err != nil {
return nil, fmt.Errorf("failed to send icmp packet: %w", err)
}
@ -425,7 +432,8 @@ nextHop:
for {
remoteIP, icmpPacket, ok := recvICMP(i, icmpPacketsViaFirewall)
if !ok {
continue repeat
// Timed out.
continue repeatHop
}
// Pre-filter by message type.
@ -485,6 +493,9 @@ nextHop:
return dl, nil
}
// Add one max hop for every reply that was not global.
maxHops++
// Otherwise, continue.
continue nextHop
}

View file

@ -419,7 +419,7 @@ resolveLoop:
return nil, err
default:
resolver.Conn.ReportFailure()
log.Tracer(ctx).Debugf("resolver: query to %s failed: %s", resolver.Info.ID(), err)
log.Tracer(ctx).Warningf("resolver: query to %s failed: %s", resolver.Info.ID(), err)
continue
}
}