Skip to content
tkjaerPublic

About

ECMP-aware traceroute

Topics

Resources

Contributing

Stars

145 stars

Watchers

3 watching

Forks

Repository files navigation

ETR - ECMP Traceroute

An MTR-like tool for discovering and analyzing ECMP (Equal-Cost Multi-Path) network routes.

Features

ETR discovers multiple network paths by running parallel traceroute probes with different source ports, causing routers to select different ECMP routes. Each probe maintains a consistent 5-tuple (src IP, src port, dst IP, dst port, protocol) to repeatedly test the same path.

  • Real-time TUI: MTR-like interface with live statistics (RTT, delay variation, packet loss per hop)
  • Parallel probes: Run multiple simultaneous probes to discover different ECMP paths
  • Path discovery: Automatically discover all ECMP paths with --discover
  • Protocol support: TCP SYN and UDP probes (UDP payload length encodes probe details)
  • JSON export: Stream results to stdout or file for analysis and integration
  • Path identification: CRC32 or SHA256 hashing to identify unique routes
  • Automatic destination detection: Stops probing beyond the final destination

Use cases: Network troubleshooting, ECMP path discovery, finding specific paths for tools like iperf

Demo

etr tui demo

Installation

  • Homebrew (macOS/Linux):
    brew tap tkjaer/tap
    brew install etr
  • Releases: Download the latest macOS/Linux binary from the releases page.
  • APT repository (Debian/Ubuntu):
    sudo mkdir -p /etc/apt/keyrings
    curl -fsSL https://tkjaer.github.io/etr/etr.gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/etr.gpg
    echo "deb [signed-by=/etc/apt/keyrings/etr.gpg] https://tkjaer.github.io/etr stable main" | sudo tee /etc/apt/sources.list.d/etr.list
    sudo apt update
    sudo apt install etr
  • Source: go install github.com/tkjaer/etr/cmd/etr@latest (requires libpcap headers).
  • BSD: Supported via source builds (OpenBSD/NetBSD limited to Ethernet source interfaces).

Detailed platform notes (Gatekeeper prompts, package installs, raw-socket permissions) live in docs/install.md. The APT repository is signed and requires the published repository key.

Usage

# Basic TCP traceroute
etr example.com

# UDP with 10 parallel probes to discover multiple paths
etr -U -P 10 example.com

# Export JSON while showing TUI
etr -j output.json example.com

# JSON-only output (no TUI)
etr -J example.com > results.json

# Custom port and extended monitoring
etr -p 80 -c 1000 -d 5s target.example.com

# Discover all ECMP paths to a destination
etr --discover example.com

Common options:

  • -4/-6: Force IPv4 or IPv6 routing
  • -T/-U: TCP (default) or UDP probes
  • -n: Skip DNS lookups (show IPs only)
  • -c <n>: Probe iterations (default: unlimited)
  • -P <n>: Number of parallel probes (default: 5)
  • -p <port>: Destination port (default: 443 for TCP, 33434 for UDP)
  • -s <port>: Base source port (default: 50000)
  • -j <file>: JSON output to file (keeps TUI)
  • -J: JSON output to stdout (disables TUI)
  • -B: Print a tcpdump-compatible BPF filter for the current options
  • -a, --asn: Enable ASN (Autonomous System Number) lookups for each hop
  • --help: Full option list

TUI controls: ↑/↓ scroll, ←/→ or Tab switch views, q quit

Styling: set the NO_COLOR environment variable to disable ANSI styling in the TUI.

Example: Finding ECMP Paths for iperf Testing

# Discover ECMP paths automatically
etr --discover target.example.com
# Output shows each unique path with its source port and hop chain:
#   path e82729e8  src-port :50001  10.0.1.1 → 91.100.34.1 → ... → 142.250.180.14
#   path 1a7507c3  src-port :50004  10.0.1.1 → 91.100.34.1 → ... → 142.250.180.14

# Use iperf with a discovered source port to test that exact ECMP path
iperf3 -c target.example.com --cport 50001

--discover probes with sequential source ports, confirms each path is stable, then moves on. It defaults to -P 2 -d 500ms to reduce ICMP pressure on routers. Run etr --help for tuning flags.

JSON Output Format

Each probe iteration outputs one line of JSON (newline-delimited):

{
  "probe_id": 0,
  "probe_num": 1,
  "path_hash": "a3f5c2d1",
  "source_ip": "198.51.100.1",
  "source_port": 50000,
  "destination_ip": "203.0.113.1",
  "destination_port": 443,
  "destination_ptr": "example.com",
  "protocol": "TCP",
  "reached_dest": true,
  "hops": [
    {
      "ttl": 1,
      "ip": "192.0.2.1",
      "rtt": 1234567,
      "timeout": false,
      "ptr": "gateway.local",
      "recv_time": "2025-10-27T12:00:00Z"
    }
  ],
  "timestamp": "2025-10-27T12:00:00Z"
}

Key fields:

  • path_hash: Unique identifier for this network path (CRC32 or SHA256)
  • probe_id: Which parallel probe (0 to N-1)
  • probe_num: Iteration number (0, 1, 2, ...)
  • reached_dest: Whether the final destination was reached
  • rtt: Round-trip time in microseconds

Using -B with tcpdump

ETR can print the exact BPF filter it uses for capturing probe responses. This is useful if you want to:

  • Watch traffic live alongside ETR:

    tcpdump -i eth0 "$(etr -B example.com)"

  • Capture a trace for troubleshooting or sharing with others:

    tcpdump -i eth0 -w etr-trace.pcap "$(etr -B example.com)"

This keeps capture focused on the probe traffic ETR cares about and makes it easier to share evidence during debugging.

License

MIT License - see LICENSE file for details.

Further Reading

About

ECMP-aware traceroute

Topics

Resources

Contributing

Stars

145 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages