yarrp icon indicating copy to clipboard operation
yarrp copied to clipboard

Destination IP is ignored

Open svbatalov opened this issue 4 years ago • 2 comments

Hello.

I noticed that traces produced by yarrp do not include destination IP even when using ICMP probes and destination responses to ping. For example:

$ sudo yarrp -t ICMP -i - <<<139.130.4.5
>> Listener: timeout 1/10
>> Listener: timeout 2/10
>> Listener: timeout 3/10
>> Listener: timeout 4/10
>> Listener: timeout 5/10
>> Listener: timeout 6/10
>> Listener: timeout 7/10
>> Listener: timeout 8/10
>> Listener: timeout 9/10
>> Listener: timeout 10/10

$ yrp2warts -i output.yrp -o /tmp/output.warts
Opening Yarrp file: output.yrp
Processed 21 Yarrp records
Created 1 traces
Opening output file /tmp/output.warts
Writing cycle start
Writing cycle stop

$ sc_warts2text /tmp/output.warts
traceroute from 192.168.2.162 to 139.130.4.5
 1  192.168.2.1  2.325 ms
 2  192.168.1.1  2.085 ms
 3  10.140.0.1  3.652 ms
 4  85.235.63.162  14.677 ms
 5  212.188.18.130  6.003 ms
 6  212.188.29.249  7.833 ms
 7  212.188.29.85  20.924 ms
 8  195.34.50.161  31.803 ms
 9  212.188.2.37  89.928 ms
10  212.188.54.2  49.383 ms
11  62.115.146.178  47.144 ms
12  62.115.123.26  219.209 ms
13  62.115.139.169  223.352 ms
14  213.155.134.50  159.106 ms
15  213.155.130.129  217.790 ms
16  80.239.128.77  266.369 ms
17  202.84.247.18  221.273 ms
18  202.84.141.26  353.336 ms
19  203.50.13.89  355.261 ms
20  203.50.6.60  355.373 ms
21  203.50.11.221  353.067 ms

Regular traceroute includes the destination:

$ sudo traceroute -I 139.130.4.5
traceroute to 139.130.4.5 (139.130.4.5), 30 hops max, 60 byte packets
 1  OpenWrt.lan (192.168.2.1)  5.835 ms  7.381 ms  16.784 ms
 2  192.168.1.1 (192.168.1.1)  17.045 ms  18.309 ms  18.519 ms
 3  10.140.0.1 (10.140.0.1)  56.319 ms  90.790 ms  141.986 ms
 4  85-235-63-162.rev.utk.ru (85.235.63.162)  121.019 ms  121.223 ms  121.423 ms
 5  asb-cr01-ae19.0.ekt.mts-internet.net (212.188.18.130)  128.661 ms  129.474 ms  129.502 ms
 6  zoo-cr01-be1.66.ekt.mts-internet.net (212.188.29.249)  152.927 ms  9.834 ms  16.167 ms
 7  pob-cr02-be7.66.kaz.mts-internet.net (212.188.29.85)  29.793 ms  30.403 ms  30.448 ms
 8  mag9-cr01-be6.16.msk.mts-internet.net (195.34.50.161)  40.386 ms  48.343 ms  50.022 ms
 9  oct-cr03-be1.78.spb.mts-internet.net (212.188.2.37)  60.694 ms  61.700 ms  80.641 ms
10  kivi-cr02-ae8.78.hel.mts-internet.net (212.188.54.2)  87.671 ms  109.981 ms  110.829 ms
11  hls-b2-link.telia.net (62.115.146.178)  110.850 ms  50.887 ms  52.387 ms
12  s-bb3-link.telia.net (62.115.123.26)  230.409 ms  231.200 ms  231.229 ms
13  kbn-bb3-link.telia.net (62.115.139.169)  231.231 ms  231.248 ms  231.251 ms
14  nyk-bb3-link.telia.net (213.155.134.50)  158.885 ms  160.885 ms  160.923 ms
15  sjo-b21-link.telia.net (213.155.130.129)  231.153 ms  217.066 ms  215.983 ms
16  telstra-ic-326434-sjo-b21.c.telia.net (80.239.128.77)  219.706 ms  222.440 ms  218.051 ms
17  i-92.eqnx-core02.telstraglobal.net (202.84.247.18)  225.953 ms  219.395 ms  218.012 ms
18  i-20208.sydp-core04.telstraglobal.net (202.84.141.26)  354.557 ms  353.809 ms  356.581 ms
19  bundle-ether3.pad-gw11.sydney.telstra.net (203.50.13.89)  359.426 ms  359.763 ms  356.776 ms
20  bundle-ether3.ken-core10.sydney.telstra.net (203.50.6.60)  360.148 ms  360.588 ms  360.929ms
21  bundle-ether2.ken-ncprouter101.sydney.telstra.net (203.50.11.221)  355.469 ms  375.893 ms 379.293 ms
22  139.130.4.5 (139.130.4.5)  379.603 ms  385.109 ms  386.120 ms

In my use-case it is necessary to know the distance (in hops) between router and destination, which requires knowing TTL of the destination.

From the quick look at the code it seems that ICMP_ECHOREPLY, which is expected from destination IP, is not handled: https://github.com/cmand/yarrp/blob/ec16b8e541fdccb8e31134b9025bb2f8283de52f/icmp.cpp#L35-L36

Is this something that can be fixed or by design?

Thanks.

svbatalov avatar Jun 22 '20 11:06 svbatalov

Hi @svbatalov, short answer is that it's by design but we don't ignore all responses from the destination, just echo replies. yarrp ignores ICMP echo replies because they don't quote the original probe packet headers (which yarrp requires to reconstruct state since it's stateless). If, for example, you run a UDP yarrp trace that reaches the destination, and the destination replies with an ICMP destination/port unreachable message, yarrp will record that it reached the destination. Does that work for your use case, or do you have to use ICMP probes?

robertbeverly avatar Jun 27 '20 17:06 robertbeverly

Hey Robert, thank you for the response!

yarrp ignores ICMP echo replies because they don't quote the original probe packet header

I see, so request headers are only included in ICMP error messages, not echo_reply so one would need to include all necessary data into request's payload, not its headers, to handle ICMP_ECHOREPLY. Makes sense.

Does that work for your use case, or do you have to use ICMP probes?

One reason to prefer ICMP probes was this scamper paper mentioning that ICMP traceroute reaches more destinations compared to other methods. Also, I encountered some problems with UDP scans, described below.

When doing UDP scans yarrp first yields a ton of ** IP dst in ICMP reply quote invalid! messages and, a bit later, a never-ending flow of messages like this

probeUDP(): error: Message too long
>> UDP probe: 113.30.35.178 ttl: 21 t=255340416

The output file stops increasing once these errors appear.

After some experimentation with various sysctl settings, which didn't help, I tried to find the reason in the code and came across this: https://github.com/cmand/yarrp/blob/049d3aeb2fdc840a2a22be4bc295814767b94472/trace4.cpp#L100-L104

So looks like two higher bytes of timestamp are encoded in UDP payload length, hence as time passes the UDP packet sizes will increase "without limit". I tweaked the code a bit and found that first error happens when payloadlen=1473. Apparently, UDP packets of this "size" are too big for my system (Ubuntu 16.04 on Linode VM) or some intermediate router. Indeed, at this specific packet size nping starts to yield the same error (with and without --df):

# nping --udp -p 11111 144.193.94.175 --data-length 1473 -c 1 --df
WARNING: Payload exceeds maximum recommended payload (1400)

Starting Nping 0.7.01 ( https://nmap.org/nping ) at 2020-06-28 18:06 UTC
sendto in send_ip_packet_sd: sendto(4, packet, 1501, 0, 144.193.94.175, 16) => Message too long
Offending packet: UDP 172.104.12.12:53 > 144.193.94.175:11111 ttl=64 id=58220 iplen=1501
SENT (0.0236s) UDP 172.104.12.12:53 > 144.193.94.175:11111 ttl=64 id=58220 iplen=1501

Max rtt: N/A | Min rtt: N/A | Avg rtt: N/A
Raw packets sent: 1 (1.501KB) | Rcvd: 0 (0B) | Lost: 1 (100.00%)
Nping done: 1 IP address pinged in 1.05 seconds

My understanding is that one can not send IP packets bigger than MTU (1500 in this case) with fragmenting prohibited (which seem to be the case here). How is this supposed to work? Maybe one should not include this fake payload length into IP header length, as actual UDP payload size is only 2 bytes? https://github.com/cmand/yarrp/blob/049d3aeb2fdc840a2a22be4bc295814767b94472/trace4.cpp#L110 Shouldn't it be something like this

diff --git a/trace4.cpp b/trace4.cpp
index 0f769f5..3365b0f 100644
--- a/trace4.cpp
+++ b/trace4.cpp
@@ -107,7 +107,7 @@ Traceroute4::probeUDP(struct sockaddr_in *target, int ttl) {
         probePrint(&target->sin_addr, ttl);
     }

-    packlen = sizeof(struct ip) + sizeof(struct udphdr) + payloadlen;
+    packlen = sizeof(struct ip) + sizeof(struct udphdr) + 2;

     outip->ip_p = IPPROTO_UDP;
 #ifdef _BSD
@@ -128,7 +128,7 @@ Traceroute4::probeUDP(struct sockaddr_in *target, int ttl) {

     /* compute UDP checksum */
     memset(data, 0, 2);
-    u_short len = sizeof(struct udphdr) + payloadlen;
+    u_short len = sizeof(struct udphdr) + 2;
     udp->uh_sum = p_cksum(outip, (u_short *) udp, len);

     /* encode LSB of timestamp in checksum */

As another workaround, I found an undocumented command-line option -C (for coarse) which changes timestamps from microsecond to millisecond accuracy, thus reducing its numerical values and payloadlen. However, resulting traces have millisecond RTT accuracy, which is not good.

Thanks, Sergey.

svbatalov avatar Jun 28 '20 21:06 svbatalov