Toy Traceroute With Ping
  Here is an example of a toy traceroute using ping on
  Linux:
$ for ttl in {1..30}; do ping -4 -c 1 -t $ttl example.com && break; done | grep -i from | nl -s ' ' -w 2
 1 From router1-lon.linode.com (212.111.33.229) icmp_seq=1 Time to live exceeded
 2 From if-0-1-0-0-0.gw1.lon1.gb.linode.com (109.74.207.10) icmp_seq=1 Time to live exceeded
 3 From be5787.rcr51.lon10.atlas.cogentco.com (204.68.252.58) icmp_seq=1 Time to live exceeded
 4 From be2589.ccr41.lon13.atlas.cogentco.com (154.54.59.37) icmp_seq=1 Time to live exceeded
 5 From be2099.ccr31.bos01.atlas.cogentco.com (154.54.82.34) icmp_seq=1 Time to live exceeded
 6 From verizondms.bos01.atlas.cogentco.com (154.54.11.54) icmp_seq=1 Time to live exceeded
 7 From ae-66.core1.bsa.edgecastcdn.net (152.195.233.129) icmp_seq=1 Time to live exceeded
 8 64 bytes from 93.184.216.34 (93.184.216.34): icmp_seq=1 ttl=57 time=63.0 ms
  The output above was obtained on a Debian GNU/Linux 11.2 (bullseye)
  system.  The above loop sends multiple ICMP echo requests with
  different Time to Live (TTL) values to reach the host
  for example.com.  The TTL occurs as an 8-bit field in
  the Internet Protocol (IP) header of each packet.  It is the 9th
  octet in an IPv4 header and the 8th octet in an IPv6 header.
When a router on the path to the destination receives a packet, it decrements the TTL value in the IP header by one. If the TTL value becomes 0 after the decrement operation, the router responds with a "time-to-live exceeded" ICMP message. Thus an echo request with TTL value set to 1 gets us an ICMP "time-to-live exceeded" message from the first router in the path, the next echo request with TTL value 2 gets us a similar ICMP message from the second router in the path, and so on. The traceroute is complete when we receive a successful ICMP echo reply.
  For comparison, here is the output of the
  actual traceroute command:
$ traceroute example.com traceroute to example.com (93.184.216.34), 30 hops max, 60 byte packets 1 router1-lon.linode.com (212.111.33.229) 0.602 ms 1.202 ms 1.326 ms 2 if-0-1-0-1-0.gw1.lon1.gb.linode.com (109.74.207.14) 0.502 ms if-11-1-0-0-0.gw2.lon1.gb.linode.com (109.74.207.26) 0.401 ms if-11-0-0-0-0.gw2.lon1.gb.linode.com (109.74.207.30) 0.379 ms 3 be5787.rcr51.lon10.atlas.cogentco.com (204.68.252.58) 0.573 ms 0.563 ms 0.566 ms 4 be2589.ccr41.lon13.atlas.cogentco.com (154.54.59.37) 1.271 ms 1.311 ms ldn-bb1-link.ip.twelve99.net (62.115.122.188) 1.400 ms 5 be2099.ccr31.bos01.atlas.cogentco.com (154.54.82.34) 63.511 ms 63.540 ms nyk-bb1-link.ip.twelve99.net (62.115.112.244) 73.397 ms 6 nyk-b1-link.ip.twelve99.net (62.115.135.131) 70.113 ms verizondms.bos01.atlas.cogentco.com (154.54.11.54) 63.657 ms nyk-b1-link.ip.twelve99.net (62.115.135.131) 70.190 ms 7 ae-66.core1.bsa.edgecastcdn.net (152.195.233.129) 63.535 ms edgecast-ic317659-nyk-b6.ip.twelve99-cust.net (62.115.147.199) 77.802 ms ae-66.core1.bsa.edgecastcdn.net (152.195.233.129) 63.582 ms 8 93.184.216.34 (93.184.216.34) 62.895 ms ae-71.core1.nyb.edgecastcdn.net (152.195.69.139) 72.312 ms ae-70.core1.nyb.edgecastcdn.net (152.195.68.141) 69.419 ms 9 93.184.216.34 (93.184.216.34) 70.827 ms 62.896 ms 73.342 ms
  Each line in the output above corresponds to a hop.  Each line shows
  one or more addresses.  A maximum of three addresses can be seen in
  the result for each hop.  That is because there are multiple paths
  to the destination and the traceroute command sends 3
  UDP probe packets by default for each hop.  In this manner, it ends
  up discovering multiple routes to the destination.  It is worth
  noting here that by default traceroute sends UDP
  packets, not ICMP echo requests, with different TTL values as probe
  packets.  But the route discovery mechanism remains the same.  After
  sending each probe packet, it waits for ICMP "time-to-live exceeded
  messages" from the routers that fall in the path to the destination.
  By comparing the two outputs above, we can see that the route found
  by the toy traceroute using ping is one of the several
  routes found by the traceroute command.
  For those on macOS, the ping command options need to be
  modified as follows:
for ttl in {1..30}; do ping -c 1 -t 1 -m $ttl example.com && break; done | grep -i from | nl -s ' ' -w 2
  On macOS, the -t option of the ping
  command specifies a timeout (not IP TTL) that prevents it from
  waiting for too long for a successful echo reply which we don't
  expect to receive.  Further, on macOS, the -m option of
  the ping command specifies the IP TTL.