GitHub - hervehildenbrand/gtrace: Advanced network path analysis tool with MPLS/ECMP detection, GlobalPing integration, and MTR mode

GitHub

8 min read Original article ↗

CI Go Version License Go Report Card Release Platform

Advanced network path analysis tool combining local traceroute with GlobalPing's distributed probe network.

gtrace demo

Why gtrace?

Feature gtrace mtr traceroute
MPLS label detection Yes No No
ECMP/load balancing detection Yes No No
Active ECMP probing (Paris-style) Yes No No
NAT detection Yes No No
Path MTU discovery Yes No No
GlobalPing integration Yes No No
ASN + geolocation enrichment Yes Partial No
IPv4/IPv6 dual-stack Yes Yes Yes
MTR-style continuous mode Yes Yes No
Latency jitter (StdDev) Yes Yes No
JSON/CSV export Yes Yes No
MCP server (AI integration) Yes No No
Built-in self-update Yes No No

Features

  • Multi-Protocol Traceroute: ICMP, UDP, and TCP probing
  • IPv4/IPv6 Support: Dual-stack with -4 and -6 flags
  • MPLS Detection: Extract and display MPLS label stacks from ICMP extensions
  • ECMP Detection: Passive detection of load-balanced paths with multiple IPs per hop
  • Active ECMP Probing: Paris traceroute-style flow variation to actively discover ECMP paths
  • NAT Detection: Identify NAT devices along the path via response TTL analysis
  • Path MTU Discovery: Active per-hop MTU discovery (tracepath-style) with PMTUD black-hole detection
  • Rich Enrichment: ASN lookup, reverse DNS, geolocation, IX detection
  • MTR Mode: Continuous monitoring with real-time statistics including latency jitter (StdDev)
  • GlobalPing Integration: Run traces from 500+ global probe locations
  • Export Formats: JSON, CSV, and text output
  • MCP Server: Expose all tools to AI assistants (Claude Code, Cursor, etc.) via Model Context Protocol

Installation

Precompiled Binaries

Download the latest release for your platform from the Releases page.

Available for Linux and macOS (amd64 and arm64).

# Linux amd64
VERSION=$(curl -sI https://github.com/hervehildenbrand/gtrace/releases/latest | grep -i location | sed 's/.*tag\/v//' | tr -d '\r')
curl -LO "https://github.com/hervehildenbrand/gtrace/releases/download/v${VERSION}/gtrace_${VERSION}_linux_amd64.tar.gz"
tar xzf "gtrace_${VERSION}_linux_amd64.tar.gz"
sudo mv gtrace /usr/local/bin/

# macOS Apple Silicon
VERSION=$(curl -sI https://github.com/hervehildenbrand/gtrace/releases/latest | grep -i location | sed 's/.*tag\/v//' | tr -d '\r')
curl -LO "https://github.com/hervehildenbrand/gtrace/releases/download/v${VERSION}/gtrace_${VERSION}_darwin_arm64.tar.gz"
tar xzf "gtrace_${VERSION}_darwin_arm64.tar.gz"
sudo mv gtrace /usr/local/bin/

From Source

go install github.com/hervehildenbrand/gtrace/cmd/gtrace@latest

Build Locally

git clone https://github.com/hervehildenbrand/gtrace.git
cd gtrace
go build -o gtrace ./cmd/gtrace

Quick Start

# Basic ICMP traceroute
sudo gtrace 8.8.8.8 --simple

# UDP traceroute with ECMP detection
sudo gtrace cloudflare.com --simple --protocol udp --packets 6

# Active ECMP probing (Paris traceroute-style)
sudo gtrace cloudflare.com --simple --protocol udp --ecmp-flows 8

# TCP traceroute to specific port
sudo gtrace example.com --simple --protocol tcp --port 443

# NAT detection
sudo gtrace 8.8.8.8 --simple --detect-nat

# Path MTU discovery (per-hop, with black-hole detection)
sudo gtrace mtu 8.8.8.8

# MTR-style continuous monitoring
sudo gtrace 8.8.8.8

# Compare local and remote traces
sudo gtrace 8.8.8.8 --compare --from "New York,London"

# Visual path graph (git-log style DAG): paths from multiple probes
# converging toward the destination, convergence points highlighted
gtrace 8.8.8.8 --graph --from "Paris;Frankfurt;Tokyo"

# Path graph of the local trace (shows ECMP forks)
sudo gtrace 8.8.8.8 --graph

# IPv6 traceroute
sudo gtrace -6 google.com --simple

# Compare IPv6 local vs remote
sudo gtrace -6 google.com --compare --from Paris

Usage

Basic Options

Flag Description Default
-4, --ipv4 Force IPv4 only false
-6, --ipv6 Force IPv6 only false
--protocol Protocol: icmp, udp, tcp icmp
--port Target port (TCP/UDP) 33434
--max-hops Maximum TTL 30
--packets Probes per hop 3
--timeout Per-hop timeout 500ms
--simple Simple output (no TUI) false
--graph Render path graph after trace (no TUI) false

Detection & Discovery

Flag Description Default
--detect-nat Enable NAT detection via TTL analysis false
--ecmp-flows ECMP flow variations per hop (0=disabled) 0
--mtu Active per-hop Path MTU Discovery with black-hole detection (icmp/udp) false
--probe-size Probe packet size in bytes 64

--discover-mtu remains as a deprecated alias for --mtu.

MTR Mode

Flag Description Default
--interval Time between cycles 1s
--cycles Number of cycles (0=infinite) 0

Keyboard shortcuts in MTR mode:

  • p - Pause/Resume
  • r - Reset statistics
  • n - Toggle DNS/IP display
  • q - Quit

GlobalPing Integration

Flag Description
--from Probe locations, comma-separated (max 5)
--compare Compare local trace with remote probes
--api-key GlobalPing API key for higher rate limits

Export

Flag Description
-o, --output Export to file (format auto-detected from extension)
--format Explicit format: json, csv, text (or txt)

Enrichment

Flag Description
--offline Use only local GeoIP databases
--db-status Show GeoIP database status
--download-db Instructions to download GeoIP databases

Self-Update

gtrace checks for new versions on startup and displays a notification after the trace completes. To upgrade in place:

gtrace upgrade          # Interactive prompt
gtrace upgrade --force  # Non-interactive
Environment Variable Description
GTRACE_NO_UPDATE_CHECK=1 Disable the automatic update check on startup

Examples

Detect MPLS Labels

sudo gtrace www.internet2.edu --simple

Output shows MPLS labels on backbone hops:

 8  129.250.2.106  [AS2914]  202ms  [MPLS: L=309833 E=0 S=1 TTL=1]
 9  129.250.6.6    [AS2914]  79ms   [MPLS: L=36001 E=0 S=1 TTL=1]

Detect Load Balancing (ECMP)

# Passive detection: send multiple probes and observe path divergence
sudo gtrace cloudflare.com --simple --protocol udp --packets 8

# Active probing: Paris traceroute-style flow variation
sudo gtrace google.com --simple --protocol udp --ecmp-flows 8

Multiple IPs at the same hop indicate ECMP:

 6  72.14.202.232  72.14.205.190  193.251.255.104  72.14.204.184  [AS15169]  3.44ms

Detect NAT Devices

sudo gtrace 8.8.8.8 --simple --detect-nat

NAT devices are identified by TTL anomalies in ICMP responses:

 3  10.0.0.1  [AS3215]  5.42ms 4.89ms 5.01ms  [NAT]
 7  72.14.236.73  [AS15169]  8.21ms 7.98ms 8.44ms  [NAT]

Path MTU Discovery

sudo gtrace mtu 8.8.8.8              # dedicated subcommand
sudo gtrace 8.8.8.8 --simple --mtu   # or as a flag on a normal trace

Actively discovers each hop's MTU (tracepath-style): probes carry the Don't Fragment bit starting at the egress interface MTU, and ICMP Fragmentation Needed / Packet Too Big replies (IPv4 and IPv6) shrink the probe until the path is measured. Works with --protocol icmp (default) and udp; TCP SYN probes have a fixed size and are not supported.

 1  192.168.1.1  0.87ms  [MTU:1500]
 2  80.10.255.25  [AS3215]  1.57ms  [MTU:1500]
 3  10.20.0.1  [AS3215]  5.42ms  [MTU:1400]

Trace complete: reached 8.8.8.8 in 9 hops
Path MTU: 1400

When a hop silently drops oversized packets without sending ICMP feedback (a PMTUD black hole - the classic cause of hanging TLS handshakes and stuck downloads), gtrace binary-searches the boundary and flags it:

 4  203.0.113.9  12.10ms  [MTU:1400 blackhole]

The TUI shows the same as a compact [MTU:1400!] marker.

IPv6 Traceroute

# Force IPv6
sudo gtrace -6 google.com --simple

# Compare IPv6 paths from different locations
sudo gtrace -6 cloudflare.com --compare --from "Frankfurt,Singapore"

Export to JSON

sudo gtrace 8.8.8.8 --simple -o trace.json

JSON includes full hop data with ASN, geolocation, timing, and detection results:

{
  "target": "8.8.8.8",
  "pathMtu": 1500,
  "hops": [
    {
      "ttl": 1,
      "ip": "192.168.1.1",
      "avgRtt": 0.5,
      "lossPercent": 0,
      "nat": true,
      "mtu": 1500,
      "mtuBlackhole": false
    }
  ]
}

pathMtu and mtuBlackhole appear when MTU discovery ran (--mtu).

Compare Local vs Remote

# Compare against a single remote location
sudo gtrace 8.8.8.8 --compare --from Paris

# Compare against multiple remote locations (up to 5)
sudo gtrace 8.8.8.8 --compare --from "Paris,Tokyo"

Each remote location produces its own side-by-side comparison against the local trace, separated by ===. Column headers show the actual probe location (e.g. "Paris, FR, OVH SAS").

MCP Server (AI Integration)

gtrace includes a built-in MCP server that exposes its tools to AI assistants like Claude Code, Cursor, and other MCP-aware clients.

Available Tools

Tool Description Needs Root
traceroute Full traceroute with ASN, geo, MPLS enrichment Yes
mtr MTR report with packet loss and latency stats Yes
globalping Remote traceroute from worldwide probe locations No
list_probes Discover GlobalPing probe locations (filter by country, city, ASN, network) No
ping Distributed ICMP/TCP ping via GlobalPing No
dns Distributed DNS lookup via GlobalPing (all record types, trace mode) No
asn_lookup ASN info for an IP (org, prefix, country) No
geo_lookup Geolocation for an IP (city, coords, timezone) No
reverse_dns Reverse DNS hostname lookup No

Output Formats

Every tool accepts format: "text" (default, human-readable) or format: "json", which returns machine-readable data in the MCP result's structuredContent field. traceroute and globalping also accept view: "graph" to render the visual path graph (forks, merges, per-source strands) instead of the classic table; view is ignored when format is json.

The traceroute tool's discover_mtu parameter runs active per-hop Path MTU Discovery (icmp/udp only): results include each hop's MTU, PMTUD black-hole flags, and the end-to-end pathMtu. GlobalPing probes cannot vary packet size, so the globalping tool does not support MTU discovery.

Setup with Claude Code

# Add gtrace as an MCP server (requires sudo for traceroute/mtr)
claude mcp add gtrace -- sudo gtrace mcp

# Or without sudo (only lookup + globalping tools will work)
claude mcp add gtrace -- gtrace mcp

# With a GlobalPing API key for higher rate limits
claude mcp add gtrace -- sudo gtrace mcp --api-key YOUR_KEY

Restart Claude Code after adding. The tools appear as mcp__gtrace__traceroute, mcp__gtrace__asn_lookup, etc.

Setup with Other MCP Clients

Add to your MCP client configuration:

{
  "gtrace": {
    "command": "sudo",
    "args": ["gtrace", "mcp"]
  }
}

Privilege Requirements

  • macOS: sudo is required for traceroute/mtr (raw socket access)
  • Linux: Either sudo or grant the binary CAP_NET_RAW:
    sudo setcap cap_net_raw+ep $(which gtrace)
    gtrace mcp  # no sudo needed
  • Lookup tools (asn_lookup, geo_lookup, reverse_dns) and globalping never need elevated privileges

Architecture

gtrace/
├── cmd/gtrace/          # CLI entry point
├── internal/
│   ├── trace/           # Traceroute engines (ICMP, UDP, TCP)
│   ├── display/         # TUI and simple output renderers
│   ├── enrich/          # ASN, geo, rDNS enrichment
│   ├── export/          # JSON, CSV, text exporters
│   ├── globalping/      # GlobalPing API client
│   ├── mcp/             # MCP server for AI integration
│   ├── monitor/         # Route change detection
│   └── update/          # Auto-update and self-upgrade
└── pkg/hop/             # Hop data structures

Requirements

  • Go 1.24+
  • Root/sudo privileges for raw socket access
  • Optional: MaxMind GeoIP databases for offline geolocation

License

MIT