A pure-Go traceroute library supporting ICMP and UDP probe protocols.
Traceroute discovers the network path to a destination by sending probe packets with incrementing IP Time-To-Live (TTL) values, starting at 1. Each router along the path decrements the TTL; when it hits zero the router drops the packet and sends back an ICMP Time Exceeded message, revealing its address. When the probe finally reaches the destination, the response changes (ICMP Echo Reply for ICMP probes, ICMP Destination Unreachable for UDP probes), signaling the trace is complete.
Sends ICMP Echo Request packets. Each probe carries a unique identifier and sequence number used to match replies. The same ICMP socket is used for both sending probes and receiving replies.
Sends UDP packets to incrementing high-numbered destination ports (starting at 33434). A separate ICMP socket listens for Time Exceeded and Destination Unreachable errors. The destination port embedded in the ICMP error payload is used to match replies back to probes.
The library first attempts to open an unprivileged ICMP datagram socket (udp4), which works without root on macOS and on Linux when net.ipv4.ping_group_range includes the current user's GID. If that fails, it falls back to raw sockets (ip4:icmp), which require root or CAP_NET_RAW.
go get github.com/migfernandes01/traceroute
import "github.com/migfernandes01/traceroute/traceroute"
result, err := traceroute.Trace("google.com", nil)
if err != nil {
log.Fatal(err)
}
fmt.Println(result)result, err := traceroute.Trace("google.com", &traceroute.Config{
Protocol: traceroute.UDP,
MaxHops: 20,
NumProbes: 1,
Timeout: 2 * time.Second,
})For multiple traces, use a Client to open the ICMP listener once and reuse it:
client, err := traceroute.NewClient(&traceroute.Config{
MaxHops: 20,
NumProbes: 1,
Timeout: 2 * time.Second,
})
if err != nil {
log.Fatal(err)
}
defer client.Close()
for _, host := range []string{"google.com", "cloudflare.com"} {
result, err := client.Trace(host)
if err != nil {
log.Printf("%s: %v", host, err)
continue
}
fmt.Println(result)
}A Client is not safe for concurrent use. Sequential Trace() calls on the same Client reuse the listener socket.
| Field | Default | Description |
|---|---|---|
Protocol |
ICMP |
traceroute.ICMP or traceroute.UDP |
MaxHops |
30 |
Maximum TTL value |
NumProbes |
3 |
Probes sent per hop |
Timeout |
3s |
Per-probe reply timeout |
ResolveHostnames |
true |
Reverse DNS lookup on hop addresses |
Port |
33434 |
Initial destination port (UDP only) |
Pass nil for sensible defaults.
Unit tests (no network or privileges required):
go test -short ./traceroute/
Integration tests (require network access; unprivileged sockets work on macOS, may need root or CAP_NET_RAW on Linux):
go test -v ./traceroute/
Run specific integration tests:
go test -v -run TestTraceICMPGoogle ./traceroute/
go test -v -run TestTraceMSSQLServer ./traceroute/
go test -v -run TestClientMultipleTraces ./traceroute/
If unprivileged sockets aren't available on your system:
sudo go test -v ./traceroute/