-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Packet Timestamps being overwritten - Identified a Solution #2423
Description
Brief description
I have installed the latest commit of scapy with the "Rework Timestamp Detection" commit:
#2401
I have determined that the packet received timestamp is being overwritten.
Environment
- Scapy version:
v2.4.3-237.g90c8d820 - Python version:
e.g. 3.7 - Operating System:
e.g. Fedora 30 (NST 30)
How to reproduce
Use the following script to send four (4) TCP sync packets to your default gateway. On a typical LAN you should get sub-milliseconds round-trip-time results. Substitute your default gateway for the 'dest' variable.
#
# Scapy script to compute Round Trip Times (rrt)...
from scapy.all import *
dest = "Your Gateway IPv4 Address"
pkt = []
pkt_rst = []
for i in range(1, 5):
a = IP(dst=dest) / TCP(flags="S", seq=i, sport=65000+i, dport=55556)
b = IP(dst=dest) / TCP(flags="R", seq=i, sport=65000+i, dport=55556)
pkt.append(a)
pkt_rst.append(b)
ans, unans = sr(pkt, filter="host {0}".format(dest), inter=0, timeout=1)
send(pkt_rst, inter=0)
print("scapy version: {}".format(conf.version))
for pkt in ans:
sent = pkt[0]
received = pkt[1]
res = (received.time - sent.sent_time) * 1000
print(res)
if res < 0:
breakpoint()
Actual result
My source address: 10.222.222.10 (shopper2) and my gateway: 10.222.222.1:
[root@shopper2 opt]# python3 ./rrt-scapy.py
Begin emission:
Finished sending 4 packets.
Received 5 packets, got 4 answers, remaining 0 packets
....
Sent 4 packets.
scapy version: v2.4.3-237.g90c8d820
9.302377700805664
7.546901702880859
5.416631698608398
3.2846927642822266
[root@shopper2 opt]#
As you can see the round-trip-times are way to big.
The Problem Area and Solution
After much debugging I found that the received packet was being overwritten in the "L3PacketSocket" class. Normally I would submit a Pull Request. But in this case I am only solving for the Linux platform and I am uncertain if the fix will be the permanent solution.
In file "arch/linux.py" I have preserved the received timestamp before assigning the "pkt" with the "pkt.payload" value:
Before:
class L3PacketSocket(L2Socket):
desc = "read/write packets at layer 3 using Linux PF_PACKET sockets"
def recv(self, x=MTU):
pkt = SuperSocket.recv(self, x)
if pkt and self.lvl == 2:
pkt = pkt.payload
return pkt
After:
class L3PacketSocket(L2Socket):
desc = "read/write packets at layer 3 using Linux PF_PACKET sockets"
def recv(self, x=MTU):
pkt = SuperSocket.recv(self, x)
if pkt and self.lvl == 2:
ts = pkt.time
pkt = pkt.payload
pkt.time = ts
return pkt
Suggestion: The "pkt.time" may could be renamed to "pkt.recv_time"
Expected result
After the modification is in place the following are the results:
[root@shopper2 opt]# python3 ./rrt-scapy.py
Begin emission:
Finished sending 4 packets.
Received 5 packets, got 4 answers, remaining 0 packets
....
Sent 4 packets.
scapy version: v2.4.3-237.g90c8d820
0.43010711669921875
0.34427642822265625
0.28777122497558594
0.2853870391845703
[root@shopper2 opt]#
Now sub-millisecond round-trip-times are measured using TCP Sync packets. To verify lets do a ping to the gateway (10.222.222.1):
[root@shopper2 opt]# ping -c 4 -nv 10.222.222.1
PING 10.222.222.1 (10.222.222.1) 56(84) bytes of data.
64 bytes from 10.222.222.1: icmp_seq=1 ttl=64 time=0.413 ms
64 bytes from 10.222.222.1: icmp_seq=2 ttl=64 time=0.327 ms
64 bytes from 10.222.222.1: icmp_seq=3 ttl=64 time=0.339 ms
64 bytes from 10.222.222.1: icmp_seq=4 ttl=64 time=0.331 ms
--- 10.222.222.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 100ms
rtt min/avg/max/mdev = 0.327/0.352/0.413/0.039 ms
[root@shopper2 opt]#
As you can see the ICMP round-trip-time results agree nicely with the TCP Sync packets.
Scapy Multi-Traceroute Add On: mtraceroute
I will be announcing this scapy Multi-Traceroute add on feature: mtraceroute once we get the packet timestamps corrected.
---Ron Henderson
CoAuthor of NST (Network Security Toolkit)