Hacker News new | past | comments | ask | show | jobs | submit login
Writing a toy traceroute from scratch (alexanderell.is)
50 points by otras on Feb 1, 2022 | hide | past | favorite | 6 comments



Note that OpenBSD recently rewrote it to enable performance increases.

https://undeadly.org/cgi?action=article;sid=20210903094704


A fun thing to do with traceroute implementations is to try to set speed records. The classic traceroute loop is unnecessarily slow, because it waits for the response from probe n before sending probe n+1; you can just send them all at once. You can traceroute with a variety of different protocols (Windows uses TCP, IIRC, because it gets through more firewalls). There are more esoteric tricks, too; for instance, there was a time when you could get the IP Record Route option to work.


When i was a youngster, back in linux kernel 2.0.33 days, I hacked my kernel so that it spoofed traceroute.

When it was going to send an ICMP time exceeded, it would change the source ip to the next one in a list of curious ips. Simple change but taught me heaps about network programming, the kernel, c, etc..


I added a timeout using:

receiving_socket.settimeout(1)

and then caught the exception.


Toy traceroute using ping on Linux (Debian, in my case):

  $ for ttl in {1..30}; do ping -4 -c 1 -t $ttl example.com; done | grep -i from | nl -s ' ' -w 2
   1 From router2-lon.linode.com (212.111.33.230) icmp_seq=1 Time to live exceeded
   2 From if-11-0-0-1-0.gw2.lon1.gb.linode.com (109.74.207.48) icmp_seq=1 Time to live exceeded
   3 From ldn-b2-link.ip.twelve99.net (62.115.41.64) icmp_seq=1 Time to live exceeded
   4 From ldn-bb1-link.ip.twelve99.net (62.115.122.188) icmp_seq=1 Time to live exceeded
   5 From nyk-bb2-link.ip.twelve99.net (62.115.113.20) icmp_seq=1 Time to live exceeded
   6 From nyk-b1-link.ip.twelve99.net (62.115.135.133) icmp_seq=1 Time to live exceeded
   7 From edgecast-ic317659-nyk-b6.ip.twelve99-cust.net (62.115.147.199) icmp_seq=1 Time to live exceeded
   8 From ae-65.core1.nyb.edgecastcdn.net (152.195.68.131) icmp_seq=1 Time to live exceeded
   9 64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=56 time=73.7 ms
  10 64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=56 time=73.6 ms
  11 64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=56 time=73.7 ms
  12 64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=56 time=73.6 ms
  ...
This loop sends out multiple ICMP echo requests with different TTL values (1, 2, 3, etc.). Each router on the path decrements the TTL by one. Everytime a router finds that the TTL is 0, we get an ICMP TTL exceeded message from that router. The traceroute is complete when we see the ping responses appearing. For comparison, here is the output of the actual traceroute command:

  $ traceroute -4 example.com
  traceroute to example.com (93.184.216.34), 30 hops max, 60 byte packets
   1  router2-lon.linode.com (212.111.33.230)  0.550 ms router1-lon.linode.com (212.111.33.229)  0.525 ms router2-lon.linode.com (212.111.33.230)  0.694 ms
   2  if-0-1-0-1-0.gw2.lon1.gb.linode.com (109.74.207.6)  0.503 ms  0.491 ms if-11-0-0-1-0.gw1.lon1.gb.linode.com (109.74.207.24)  0.417 ms
   3  be5787.rcr51.lon10.atlas.cogentco.com (204.68.252.58)  0.969 ms  1.029 ms ldn-b2-link.ip.twelve99.net (62.115.41.64)  1.281 ms
   4  be2589.ccr41.lon13.atlas.cogentco.com (154.54.59.37)  1.351 ms  1.404 ms  1.474 ms
   5  nyk-bb1-link.ip.twelve99.net (62.115.112.244)  70.847 ms  70.802 ms be2099.ccr31.bos01.atlas.cogentco.com (154.54.82.34)  63.580 ms
   6  verizondms.bos01.atlas.cogentco.com (154.54.11.54)  63.639 ms  64.945 ms nyk-b1-link.ip.twelve99.net (62.115.135.133)  76.193 ms
   7  edgecast-ic317660-nyk-b6.ip.twelve99-cust.net (62.115.147.201)  73.460 ms ae-65.core1.bsa.edgecastcdn.net (152.195.232.129)  63.659 ms edgecast-ic317660-nyk-b6.ip.twelve99-cust.net (62.115.147.201)  71.224 ms
   8  ae-70.core1.nyb.edgecastcdn.net (152.195.68.141)  72.759 ms 93.184.216.34 (93.184.216.34)  62.964 ms ae-71.core1.nyb.edgecastcdn.net (152.195.69.139)  74.359 ms
   9  93.184.216.34 (93.184.216.34)  63.023 ms  70.599 ms  73.223 ms
On macOS, the ping loop would look like this due to differences in what the ping option names mean:

  for ttl in {1..30}; do ping -c 1 -t 1 -m $ttl example.com; done | grep -i from | nl -s ' ' -w 2
On macOS, the -t option of ping specifies a timeout (not ICMP TTL) which we need to specify to prevent ping from waiting for too long. The -m option specifies the ICMP TTL on macOS.


The traceroute picked up that you have multiple paths to the Internet.

I guess you could wait a few seconds and run the ping script again to see what changes.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: