yarrp
yarrp copied to clipboard
Destination IP is ignored
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.
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?
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.