Analysis of IP fragmentation and common fragment attacks

Source: Internet
Author: User

Preface

This article analyzes the linux IP assembly algorithm. Because IP fragments are often used for DOS attacks, I will further describe them in combination with some attack methods. The kernel version is 2.2.16, and some changes in 2.4.0-test3 are briefly introduced.

II directory

1-Overview
2-Key Data Structure
3-important functions
4-2.4 series changes
5-common fragment attacks


1. Overview

In the linux source code, almost all the ip Fragment programs are in the etipv4ip_fragment.c file. It provides an external function interface ip_defrag (). The function prototype is as follows:

Struct sk_buff * ip_defrag (struct sk_buff * skb)

As we all know, network datagram is transmitted in the linux network stack in the sk_buff structure. The ip_defrag () function is to accept the sharded data packets (sk_buff) and try to combine them, when the complete package combination is good, the new sk_buff is returned. Otherwise, a null pointer is returned.

This function is called in other files as follows:

The main function for receiving data at the ip layer is ip_rcv () (etipv4ip_input.c). All ip packets must be processed by this function. If this package is sent to the local machine, call the ip_local_deliver () function (etipv4ip_input.c) for processing, generally, system fragments are reorganized only when the final purpose is reached (although they may be further divided into smaller slices during transmission ). In ip_local_deliver (), we can find the following code:

If (sysctl_ip_always_defrag = 0 &/* pre-assembly is not set during compilation */
(Iph-> frag_off & htons (IP_MF | IP_OFFSET) {/* determine whether the package is a multipart package */
Skb = ip_defrag (skb);/* assemble if conditions are met */
If (! Skb)/* If assembled, proceed to the next step. An error occurs.
Return 0; or return after assembly */
Iph = skb-> nh. iph;/* reposition the ip header pointer */
}

Iph-> frag_off is only set in MF (more fragment) or offset! = 0 indicates that a multipart package is used. Therefore, the test here is taken for granted. But why does it mean sysctl_ip_always_defrag = 0? When we look at ip_rcv (), we should have noticed the following code after the version number, length, checksum, and other judgments are made:

If (sysctl_ip_always_defrag! = 0 &&
Iph-> frag_off & htons (IP_MF | IP_OFFSET )){
Skb = ip_defrag (skb );
If (! Skb)
Return 0;
Iph = skb-> nh. iph;
Ip_send_check (iph );
}

That is, if sysctl_ip_always_defrag = 1, the call location of ip_defrag () will change, and any incoming IP segments will be reorganized. As you can imagine, if this machine is used as a router, all parts are assembled before forwarding. This is generally unnecessary. This value can be dynamically set using the sysctl command. You can see that in a general system, this value is set to 0:

# Sysctl-
......
Net. ipv4.ip _ always_defrag = 0
......


2. Key Data Structures (Series 2.2)

Each part is represented in the ipfrag structure:

/* Describe an IP fragment .*/
Struct ipfrag {
Int offset;/* offset of fragment in IP datasync */
Int end;/* last byte of data in datax */
Int len;/* length of this fragment */
Struct sk_buff * skb;/* complete completed ed fragment */
Unsigned char * ptr;/* pointer into real fragment data */
Struct ipfrag * next;/* linked list pointers */
Struct ipfrag * prev;
};

These shards form a two-way linked list (if you need to use a linked list in the Linux kernel, the two-way linked list is recommended unless you have special requirements, see documentCodingStyle ), indicates An unassembled shard Queue (which belongs to an IP package ).
The head pointer of this linked list should be placed in the ipq structure:

/* Describe an entry in the "incomplete into Rams" queue .*/
Struct ipq {
Struct iphdr * iph;/* pointer to IP header */
Struct ipq * next;/* linked list pointers */
Struct ipfrag * fragments;/* linked list of existing ed fragments */
Int len;/* total length of original datasync */
Short ihlen;/* length of the IP header */
Struct timer_list timer;/* when will this queue expire? */
Struct ipq ** pprev;
Struct device * dev;/* Device-for icmp replies */
};

Note that each ipq retains a timer (struct timer_list timer ;).

Ipq also forms a linked list, which is all the IP packages not fully assembled by the kernel. A
Hash table:
# Define IPQ_HASHSZ 64
Struct ipq * ipq_hash [IPQ_HASHSZ];
# Define ipqhashfn (id, saddr, daddr, prot)
(Id) >>1) ^ (saddr) ^ (daddr) ^ (prot) & (IPQ_HASHSZ-1 ))

--------_____________
| 1 |
-------------------------------------------
Hash Table | 2 | ipq1 | ----> | ipfrag1 | -----> | ipfrag2 | ------> ------〉.......
---------------------------------------------
... |
--------/
| 63 | ------------------------------------
-------- | Ipq2 | ----> | ipfrag1 | -----> | ipfrag2 | ------> ------〉.......
------------------------------------
|
/
------------------------------------
| Ipq3 | ----> | ipfrag1 | -----> | ipfrag2 | ------> ------〉.......
------------------------------------
|
/
........

Each IP package is represented by the following four tuples: (id, saddr, daddr, protocol). fragments with the same values are retained in an IPQ to form a complete IP package.

This structure has been modified in the 2.4 kernel and will be declared in the following section.

3. Description of important functions (Series 2.2)

3.1 ip_defrag ()
Ip_defrag () is the entrance to the entire process. Next we will first describe ip_defrag.

(1) In order to prevent excessive memory consumption caused by retaining parts, linux sets a boundary to prevent this situation. If the memory usage limit is exceeded, the oldest Queue (ipq) in the memory is cleared ). the size of the memory used is stored in the variable ip_frag_mem. Of course, the read and write operations on it should be "Atomic" (atomic_sub, atomic_add, atomic_read, etc ).
It is defined in the front of the ip_fragment.c file:

Atomic_t ip_frag_mem = ATOMIC_INIT (0);/* Memory used for fragments */

If (atomic_read (& ip_frag_mem)> sysctl_ipfrag_high_thresh)
Ip_evictor ();

The specific operation of ip_evicator is described below.

(2) Use id, saddr, daddr, and protocol as the marker to check whether the corresponding ipq has been created. If yes, the ipq pointer is returned and the timer is reset.

Qp = ip_find (iph, skb-> dst );

(3) There is an if/else pair at this time, and its role is:
If ipq already exists, it indicates that other parts of the same package have arrived. Check whether this slice is the first slice (because the order of arrival of the slice may be disordered). If so, keep the ip header information and header length in the ipq structure ();
If (offset = 0 ){
/* Fragmented frame replaced by unfragmented copy? */
If (flags & IP_MF) = 0)
Goto out_freequeue;
Qp-> ihlen = ihl;
Memcpy (qp-> iph, iph, (ihl + 8 ));
}

If it does not exist, you must create one:
Qp = ip_create (skb, iph );
If (! Qp)
Goto out_freeskb;

Ip_create allocates a piece of memory, initializes this ipq, and registers in the hash table.

So far, ipq already exists, whether it already exists or what we just generated.

(4) The length of the packet is checked. If the maximum range of the IP packet is exceeded, an alarm is triggered and the packet is discarded. Jolt2 uses this method to paralyze the window system. Linux does this check, so it is basically immune from it.

(5) Adjust the end value (the end position of the data). If it is the last package, the length of the entire IP package will be known. For the convenience of assembly, record it to ipq.
/* Determine the position of this fragment .*/
End = offset + ntohs (iph-> tot_len)-ihl;

/* Is this the final fragment? */
If (flags & IP_MF) = 0)
Qp-> len = end;

(6) The next long piece of code (line481-line586) is to position the shard in the entire packet. If there is overlap between shards (malicious attacks and other exceptions), the shards can be merged. This issue will be discussed in detail later (in common fragment attacks.

(7) Now we know the specific location of the shard. We need to generate a new ipfrag structure and place it in
The correct position we just found goes up.
Tfp = ip_frag_create (offset, end, skb, ptr );
If (! Tfp)
Goto out_freeskb;

/* Insert this fragment in the chain of fragments .*/
Tfp-> prev = prev;
Tfp-> next = next;
If (prev! = NULL)
Prev-> next = tfp;
Else
Qp-> fragments = tfp;

If (next! = NULL)
Next-> prev = tfp;

(8) The ip_done function checks whether all the parts have been completed. If yes, it is assembled into a new sk_buff (call ip_glue) and finally returned to the place where ip_defrag is called.

If (ip_done (qp) {/* are all complete? */
/* Glue together the fragments .*/
Skb = ip_glue (qp );
/* Free the queue entry .*/
Out_freequeue:
Ip_free (qp);/* The original ipq structure is no longer required and released. */
Out_skb:
Return skb;/* after assembly is complete, you can return */
}

If not, NULL is returned.

So far, the entire assembly process has ended.

3.2 ip_evictor ()

When the memory used by the shard exceeds the upper limit (sysctl_ipfrag_high_thresh), ip_evicator is called to release the memory.
Ip_evicator searches for IPQ that can be cleared and clears it until it reaches the lower limit (sysctl_ipfrag_low_thresh)
.

This value is defined as follows in ip_fragment.c:
Int sysctl_ipfrag_high_thresh = 256*1024;
Int sysctl_ipfrag_low

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.