I tried to simplify my problem with the following setup.
- A simple netcat UDP listener on Port 1337 on my local interface (192.168.183.130)
- A simple netcat UDP client connecting to the listener on port 1337 (from 192.168.183.128)
- A very basic scapy sniffer running on 192.168.183.130
Scapy sniffer running with root privileges:
from scapy.all import sniff, IP, UDP
def print_package(packet):
packet.show()
sniff(filter="ip dst host 192.168.183.130 and dst port 1337", iface="ens33", prn=print_package)
Sending IP packets / UDP frames with the 1500 Bytes MTU limit works like a charm and the packets are printed to std-out as expected. As soon as I succeed the limit and the IP protocol creates fragments, the sniffer only catches the first packet (correct flags, len etc.)
In the following example I sent a simple string 'next message will be 3200 * "A"' from the nc client to the listener before sending 3200 * "A" with netcat. The packet gets fragmented into three IP packets and correctly reassembled by the stack, before the UDP socket netcat is using receives it, so everything works as i would expect it network-wise. Scapy only sniffs the first of the three packets and I do not understand why this happens.
The screenshot shows the expected/correct handling of the text message and the three IP fragments in wireshark:
The following snippet shows the scapy output to stdout:
sudo python3 scapy_test.py
###[ Ethernet ]###
dst = 00:0c:29:fa:93:72
src = 00:0c:29:15:2a:11
type = IPv4
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 59
id = 18075
flags = DF
frag = 0
ttl = 64
proto = udp
chksum = 0x3c3
src = 192.168.183.128
dst = 192.168.183.130
\options \
###[ UDP ]###
sport = 59833
dport = 1337
len = 39
chksum = 0xdaa0
###[ Raw ]###
load = 'next message will be 3200 * "A"\n'
###[ Ethernet ]###
dst = 00:0c:29:fa:93:72
src = 00:0c:29:15:2a:11
type = IPv4
###[ IP ]###
version = 4
ihl = 5
tos = 0x0
len = 1500
id = 20389
flags = MF
frag = 0
ttl = 64
proto = udp
chksum = 0x1518
src = 192.168.183.128
dst = 192.168.183.130
\options \
###[ UDP ]###
sport = 59833
dport = 1337
len = 3209
chksum = 0x25bd
###[ Raw ]###
load = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
Why are the other IP fragments missing and how can I sniff them?
I know about the session parameter in sniff but did I not have any luck with actually reassembling the packets with session=IPSession
. (This is not what I want to achieve anyway, for my application I want to sniff all fragments, change parts of them and forward them to another address/socket.)