From ced17bdecdbe9ee514299ced4016990edc959d8b Mon Sep 17 00:00:00 2001 From: Niklas Treml Date: Fri, 26 Jul 2024 11:06:55 +0200 Subject: [PATCH] feat: check permissions for icmp Signed-off-by: Niklas Treml --- pkg/checks/traceroute/traceroute.go | 36 ++++++++++++++++-------- pkg/checks/traceroute/traceroute_test.go | 16 +++++++++++ 2 files changed, 41 insertions(+), 11 deletions(-) create mode 100644 pkg/checks/traceroute/traceroute_test.go diff --git a/pkg/checks/traceroute/traceroute.go b/pkg/checks/traceroute/traceroute.go index e5e70477..938fe9a8 100644 --- a/pkg/checks/traceroute/traceroute.go +++ b/pkg/checks/traceroute/traceroute.go @@ -116,7 +116,7 @@ func TraceRoute(ctx context.Context, host string, port, timeout, maxHops int, rc return errors.New("failed to reach target") } return nil - }, rc) + }, rc)(ctx) if err != nil { log.Error("traceroute could not reach target", "ttl", ttl) } @@ -148,11 +148,21 @@ func ipFromAddr(remoteAddr net.Addr) net.IP { } func traceroute(results chan Hop, addr net.Addr, ttl int, timeout time.Duration) (bool, error) { + canIcmp := true icmpListener, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { - return false, err + if !errors.Is(err, syscall.EPERM) { + return false, err + } + fmt.Println("no permission to create icmp sockets. continuing without") + canIcmp = false } - defer icmpListener.Close() + + defer func() { + if canIcmp { + icmpListener.Close() + } + }() start := time.Now() conn, clientPort, err := tcpHop(addr, ttl, timeout) latency := time.Since(start) @@ -181,18 +191,22 @@ func traceroute(results chan Hop, addr net.Addr, ttl int, timeout time.Duration) deadline := time.Now().Add(5 * time.Second) for time.Now().Unix() < deadline.Unix() && !found { - gotPort, addr, err := readIcmpMessage(icmpListener, timeout) - if err != nil { - results <- Hop{ - Latency: latency, - Ttl: ttl, - Reached: false, + gotPort := -1 + var addr net.Addr + if canIcmp { + gotPort, addr, err = readIcmpMessage(icmpListener, timeout) + if err != nil { + results <- Hop{ + Latency: latency, + Ttl: ttl, + Reached: false, + } + return false, nil } - return false, nil } // Check if the destination port matches our dialer's source port - if gotPort == clientPort { + if canIcmp && gotPort == clientPort { ipaddr := ipFromAddr(addr) names, _ := net.LookupAddr(ipaddr.String()) // we don't really care if this lookup works, so ignore the error diff --git a/pkg/checks/traceroute/traceroute_test.go b/pkg/checks/traceroute/traceroute_test.go new file mode 100644 index 00000000..c4c5c4ad --- /dev/null +++ b/pkg/checks/traceroute/traceroute_test.go @@ -0,0 +1,16 @@ +package traceroute + +import ( + "errors" + "syscall" + "testing" + + "golang.org/x/net/icmp" +) + +func TestTR(t *testing.T) { + _, err := icmp.ListenPacket("ip4:icmp", "0.0.0.0") + if !errors.Is(err, syscall.EPERM) { + t.Errorf("err is not eperm") + } +}