Traceroute
View SourceA (partial) Traceroute re-implementation in Elixir.
Simply start the project with iex -S mix and run a trace:
iex> Traceroute.run("google.com", protocol: :udp, ip_protocol: :ipv4, probes: 3)
1 --redacted-- (--redacted--) 11.235ms 6.939ms 9.518ms
2 192.0.0.1 (192.0.0.1) 11.847ms 12.264ms 13.771ms
3 --redacted-- (--redacted--) 12.738ms 12.677ms 13.035ms
4 fra1901aihb001.versatel.de (62.214.42.58) 14.249ms 16.758ms
89.246.109.249 (89.246.109.249) 21.941ms
5 72.14.217.70 (72.14.217.70) 21.549ms 20.049ms
6 192.178.109.235 (192.178.109.235) 46.902ms 18.17ms 30.988ms
7 142.250.225.76 (142.250.225.76) 98.751ms
142.251.64.184 (142.251.64.184) 107.648ms
142.251.241.75 (142.251.241.75) 18.124ms
8 lcfraa-bt-in-f14.1e100.net (142.251.140.174) 16.132ms 16.391ms
For comparison, here's the output from traceroute:
$ traceroute -P udp -w 1 google.com
traceroute to google.com (142.251.140.174), 64 hops max, 40 byte packets
1 --redacted-- (--redacted--) 3.647 ms 3.184 ms 2.751 ms
2 192.0.0.1 (192.0.0.1) 8.222 ms 8.685 ms 8.126 ms
3 --redacted-- (--redacted--) 10.286 ms 9.180 ms 8.877 ms
4 fra1901aihb001.versatel.de (62.214.42.58) 14.209 ms
89.246.109.249 (89.246.109.249) 15.354 ms 15.556 ms
5 72.14.217.70 (72.14.217.70) 16.226 ms * 18.405 ms
6 192.178.109.153 (192.178.109.153) 17.366 ms *
192.178.109.235 (192.178.109.235) 19.176 ms
7 142.251.241.75 (142.251.241.75) 17.459 ms 16.791 ms
142.251.241.77 (142.251.241.77) 15.151 ms
8 142.251.241.75 (142.251.241.75) 15.695 ms 16.032 ms 18.588 ms
9 lcfraa-bt-in-f14.1e100.net (142.251.140.174) 14.811 ms
108.170.236.249 (108.170.236.249) 17.687 ms *
Features
- Sends probes as
ICMP,UDP, andTCPpackets - Supports
IPv4andIPv6(useip_protocol: :ipv6) - Sends multiple probes in parallel with request staggering
- Automatically resolves hostnames for each hop's IP address
- Returns all the data in a structured format
Configurable Options
protocol- Choose between:icmp,:udp, or:tcp(default::udp)ip_protocol- Choose between:ipv4or:ipv6(default::ipv4)max_hops- Maximum number of hops before aborting (default:20)max_retries- Retry count per hop before moving on (default:3)timeout- Response timeout in seconds (default:1)probes- Number of parallel probes per TTL (default:3)print_output- Toggle console output (default:true)
Caveats and Considerations
- This library is untested on Windows. Please report any issues for investigation.
- You may need to run as
sudodepending on your OS. MacOS can runICMP,UDP, andTCPwithout root for IPv4, but IPv6 requires root permissions forICMPpackets. Linux always requires root permissions because we need to run onerawsocket for sending and receiving theICMPpackets. Generally, if you get:epermerrors, usesudo. - Running many parallel probes can cause performance issues since each ICMP socket receives (but filters) all ICMP replies. Contact me if this affects you. I have a potential fix which is not yet implemented.
Testing IPv6 using WireGuard
Not every routers have IPv6-support, so if you run a traceroute with ip_protocol: :ipv6 and receive the {:error, :ehostunreach} error, try the following:
- Install
wireguard(e.g.brew install wireguard-tools) - Sign up for an
IPv6 Tunnel(e.g.route64.org) - Create a
Tunnelbrokerby going to:IPv6 TunnelbrokerAdd Tunnelbroker(underList tunnelbrokers)- Select a region close to you. Select
Wireguard. - Add your home IP (as shown on e.g. ip.me) into
Remote Endpoint - Click
Create Tunnelbroker
- Navigate back to
List Tunnelbrokerand click on theExample Configaction button next to your newly created tunnelbroker. - Copy the config (starting with
[Interface]) to a localw0.conffile. - Enable WireGuard through
wg-quick up w0.conf - Now, you should be able to run traceroutes through IPv6!
- To disable WireGuard again, run
wg-quick down w0.conf
Useful traceroute commands to run comparisons
IPv4
# Use 1s timeout and the ICMP protocol
traceroute -w 1 -P ICMP fly.io
# Use 1s timeout and the UDP protocol
traceroute -w 1 -P UDP fly.io
# Use 1s timeout and the TCP protocol
# First try without `sudo` but you most likely need elevated permissions
sudo traceroute -w 1 -P tcp google.com
IPv6
# Use 1s timout and the ICMP protocol
traceroute6 -I -w 1 google.com
# Use 1s timeout and the UDP protocol
traceroute6 -U -w 1 google.com
# Use 1s timeout and the TCP protocol (might need sudo permissions)
traceroute6 -T -w 1 google.com
TODOs
- [ ] Support incrementing UDP ports with every probe/retry