Fragmented IP packet forwarding

I couldn’t really find a suitable topic for this post actually but I will try to find answers for the following questions:

  • How can we fragment an IP packet manually in scapy
  • How does a fragmented packet look like and how the transport layer (TCP/UDP) header is located
  • How do we forward fragmented packets, do we reassemle them?
  • If we don’t reassemble, can we force reassembly?

First of all a bit of a theory: if an incoming IP packet is to be forwarded to another next hop and the MTU of this new path is smaller than the packet to be transmitted, we must find a way to forward the packet. If the packet has DF (Don’t Fragment) bit on i.e we are instructed not to fragment the packet most probably by the source, then normally we are expected to send an ICMP packet with type “Fragmentation needed” and pray that on the way back to the source no devices block all ICMP type of traffic. Second scenario is that what if the source lets us fragment the packet. Then we need to fragment it and story from now on is about this part of the scenario and the topology we will use is something like below.


Scapy is a fantastic tool to generate your own packets. It is exremely flexible and in our example, we will perform the fragmentation of a packet via our script.

Once you install scapy, you create the following lovely script.

What do we do here? In a nutshell, we create an IP packet transport protocol of which is UDP.  Our payload contains only characters A and B:) I put 496 A and 500 B character so we have around ~1000bytes of payload and we instruct scapy to devide this total IP packet in 500 byte segments by fragmenting it and send it to IP address Isn’t it so cool?

Now we will run the script and capture(tcpdump) on Debian1 device to see how the fragmented packets look like.

We have run the script and 496bytes of A characters are transmitted on packet 1 and all 500bytes of B characters are transmitted on the second packet i.e we split the packet into two. Let’s see how the packet looks like on the wire.

Let me explain each line what happens here.

1st Packet

We pushed 496A+500B bytes of payload of data to scapy. Dear scapy took 496bytes of this data which is all A characters and encapsulated with 8  bytes of UDP header + 20 bytes of IP header which is in total = 524 bytes. Pay attention to the port numbers. Those are the UDP port numbers we set in the code. UDP length shows 996bytes since our payload is this number of bytes in total. ID number is 12345 and it is the same on 1st and 2nd packet. Offset is also 0 as this is the first packet. Although we can’t see on this output, we have also More Fragment bit is on.

2nd packet

Real fun begins here. Where are the port numbers? We don’t have them on the second packet as the UDP header is on the first packet. You can see this from the packet size. 500bytes(B) payload + 20 bytes IP header i.e no room for header. The evidence of fragmentation is the offset but why is it 504? This field specifies how far we are from the beginning of the unfragmented IP packet and I believe it counts UDP header too:) so our offset should be 496A + 8bytes UDP header = 504.

Note: If you display the same packets in Wireshark, due to the default setting “Reassemble fragmented IPv4 datagrams“, it misleads you to think that UDP header is on the second packet instead of the first one. Be careful!

3rd packet

This isn’t even a UDP segment. Because we are sending UDP traffic to a port on which there isn’t any listening socket, remote side sends back an ICMP (Destination port unreachable) notification message.

So far we have found the answers to first two questions. Now we need to see how our stateful firewall forwards these packets. I am running tcpdump on hostE destination device this time.

We can see that we have received 2 fragmented packets first of which has the UDP header.

Note: You don’t see the ICMP destination reachable message as I blocked it via iptables otherwise, it clears SRX session immediately and we can’t display the session.

and the one above is the flow session entry. 2 packets have been forwarded in total 1044 bytes. We don’t have return packet as it is one way traffic.

IP fragmentation reassembly normally is performed at the destination host unless there is a device in the path which needs this reassembly (e.g IDP) but there is a command which does this for us. This is just to demonstrate the option. You don’t really need to use it

You can see reassembly being done if you enable flow traceoptions as the firewall forwards fragmented packets as is to the destination host.

I have tried to give a bit of information about fragmentation and its relation to transport layer protocol UDP. I hope this was helpful!

7 thoughts on “Fragmented IP packet forwarding

  1. talf

    Somehow, you post new stuff just a 1 week beofre I actually need it – and it’s not the first time 🙂
    Love your posts. Make things clear in the junos land.

    Thanks for that!

    1. rtoodtoo Post author

      I am not psychic:) but happy to hear that it helped. Thanks for the feedback.

    1. rodomonte

      same question here, seems that doesn’t works for ICMP, that doens’t support fragment at all I just discover!!

  2. Robert

    Thanks! Exactly what i’ve been looking for, good information about getting the packets fragmented.

  3. Sandeep

    I used the following code to send out-of-order fragments to my destination.


    from scapy.all import *

    for fragment in frags:
    print “Packet no#”+str(counter)
    print “===============================================”
    if counter == 2:

    I am able to achieve what I want with this (send fragment 2 at the last). However, on the linux interface, the proto is not being detected as ICMP. On Wireshark, proto field is like below:

    Protocol: IPv6 Hop-by-Hop Option (0)

    What could be the issue?

    Note: If I don’t fragment and just say send(packet), all is fine.



You have a feedback?