IP-фрагментация

ОГЛАВЛЕНИЕ

В данном документе мы рассмотрим, что такое IP фрагментация, как она происходит и почему является нежелательным явлением в сетях, а также рассмотрим пару сценариев как ее предотвратить.

IP-фрагментация и реассемблирование

IP Протокол был спроектирован для использования на широком разнообразии каналов передачи данных. Хотя максимальная длина датаграммы IP - 64 КБ, большинство каналов передачи данных устанавливают максимальный предел длины пакета, названный MTU.

Значение MTU зависит от типа канала передачи данных. Дизайн IP протокола приспосабливается к различным MTU, разрешая маршрутизаторам фрагментировать IP датаграммы по мере необходимости. За сборку (реассемблирование) фрагментов обратно в оригинальную IP датаграмму полного размера ответственна принимающая сторона.

IP-фрагментация это разбиение датаграммы на множество частей, которые могут быть повторно собраны позже. Для IP-фрагментации и повторной сборки используются такие поля из IP заголовка как источник, адресат, идентификация, полная длина, и смещение фрагмента, наряду с флажками "больше фрагментов" (MF) и "не фрагментировать" (DF).

Изображение ниже изображает расположение IP заголовка



Идентификация это 16 битовое поле и есть значение, назначенное отправителем IP датаграммы. Используется для последующей сборки фрагментов датаграммы.
Смещение фрагмента это поле 13 битов и указывает, какому месту принадлежит фрагмент в оригинальной IP датаграмме. Это значение всегда кратно восьми байтам.
В области флажков заголовка IP, есть три бита для флажков управления. Важно отметить, что бит "не фрагментировать" (DF) играет основную роль во фрагментации, потому что он определяет, можно ли фрагментировать пакет.

Бит 0 – зарезервирован и всегда сброшен в 0. Бит 1 – это бит DF (0 – можно фрагментировать, 1 – нельзя). Бит 2 – это бит MF (0 – это последний фрагмент, 1 = есть еще фрагменты)

На график ниже показ пример фрагментации.



Если вы сложите все длины IP-фрагментов, то полученное значение превысит оригинальную длину IP датаграммы на 60 байт. Причина,такого увеличения состоит в том, что были созданы три дополнительных IP заголовка, по одному для каждого фрагмента после первого.
  • Первый фрагмент имеет смещение 0, длина этого фрагмента - 1500; она включает 20 байтов для немного измененного оригинального IP заголовка.
  • Второй фрагмент имеет смещение 185 (185 x 8 = 1480), которое означает, что порция данных этого фрагмента начинается с 1480 байта в оригинальной IP датаграмме. Длина этого фрагмента - 1500; она включает дополнительный IP заголовок, созданный для этого фрагмента.
  • Третий фрагмент имеет смещение 370 (370 x 8 = 2960), которое означает, что данные этого фрагмента начинаются с 2960 байта в оригинальной IP датаграмме. Длина этого фрагмента - 1500; она включает дополнительный заголовок IP, созданный для этого фрагмента.
  • Четвертый фрагмент имеет смещение 555 (555 x 8 = 4440), которое означает, что часть данных этого фрагмента начинается с 4440 байтов в оригинальной IP датаграмме. Длина этого фрагмента - 700 байтов; это включает дополнительный заголовок IP, созданный для этого фрагмента.
Только, когда получен последний фрагмент, может быть определен размер оригинальной IP датаграммы. Смещение фрагмента в последнем фрагменте (555) дает смещение данных в 4440 байтов в оригинальной IP датаграмме. Если вы добавите байты данных от последнего фрагмента (680 = 700 - 20), это даст вам 5120 байтов, что является порцией данных оригинальной IP датаграммы. Затем, добавляя 20 байтов для IP заголовка мы получим размер оригинальной IP датаграммы (4440 + 680 + 20 = 5140).


Проблемы IP-фрагментации

Существуют несколько проблем, когда IP-фрагментация нежелательна. Чтобы фрагментировать IP датаграмму требуются больше ресурсов CPU и памяти. Это справедливо как для отправителя так и для маршрутизатора между отправителем и получателем. Создание фрагментов просто влечет за собой создание заголовков для IP-фрагментов и копирование оригинальной датаграммы во фрагменты. Это может быть сделано достаточно эффективно, потому что вся информация для создания фрагментов уже доступна.

Фрагментация накладывает больше расходов для получателя, когда он повторно собирает фрагменты, потому что получатель должен выделять память для прибывающих фрагментов и соединять их обратно в одну датаграмму после того, как получены все фрагменты. Реассемблирование на хосте это не проблема, потому что хост имеет время и ресурсы памяти, чтобы посвятить их этой задаче.

Но, реассемблирование очень неэффективно на маршрутизаторе, основная работа которого - пересылать пакеты как можно быстрее. Маршрутизатор не спроектирован, чтобы удерживать пакеты в течение любого отрезка времени. Также маршрутизатор, делающий реассемблирование выбирает наибольший доступный буфер (18 КБ), для этой работы, потому что это у него нет никакого способа узнать размер оригинального IP пакета, пока не получен последний фрагмент.

Другая проблема фрагментации это обработка отброшенных фрагментов. Если один фрагмент IP датаграммы отброшен, то вся оригинальная датаграмма должна быть послана повторно, и она будет также фрагментирована. В качестве примера, можно посмотреть на NFS. NFS, по умолчанию, читает и пишет блоки данных по 8192 байт, таким образом NFS IP/UDP датаграмма будет приблизительно 8500 байтов (включая NFS, UDP, и IP заголовки). Станция отправитель, связанная с Сетью Ethernet (MTU 1500) должна будет фрагментировать 8500-байтовую датаграмму на шесть частей; пять 1500-байтовых фрагментов и один 1100-байтовый фрагмент. Если любой из этих шести фрагментов будет отброшен из-за перегрузки канала связи, полная оригинальная датаграмма должна быть повторно передана, а это означает, что еще должны быть созданы шесть фрагментов. Если снова один из шести пакетов потеряется в канале, то вероятнось того, что любые данные NFS могут быть переданы по этому каналу связи стремится к нулю, так как по крайней мере будет отброшен один IP-фрагмент от каждой 8500-байтовая NFS датаграммы.

У межсетевых экранов, которые фильтруют или управляют пакетами, основываясь на информации уровня 4 (L4) до уровеня 7 (L7), могут возникать трудности с корректной обработкой IP-фрагментов. Если IP-фрагменты - не упорядочены, межсетевая защита может блокировать не начальные фрагменты, потому что они не несут информацию, которая соответствовала бы фильтру пакета. Это означает, что оригинальная IP датаграмма не может быть повторно собрана хостом при получении. Если межсетевой экран конфигурирован так, чтобы разрешать прохождение неначальных фрагментов с недостаточной информацией, которая не соответствует правилам фильтрации должным образом, то межсетевой экран может пропустить атаку, основанную на неначальных фрагментах. Кроме того, некоторые сетевые устройства (типа Контентных Движков) направляют пакеты, основываясь на информации уровней L4 - L7, и если пакет состоит из нескольких фрагментов, то у устройства могут возникнуть трудности с применением своих политик к таким пакетам.


Предотвращение IP-фрагментации. Что такое TCP MSS и как оно работает

Максимальный Размер TCP Сегмента (MSS) определяет максимальное количество данных, которые хост желает принимать в единственной TCP/IP датаграмме. Эта TCP/IP датаграмма может быть фрагментирована в уровне IP. Значение MSS посылают как опциию TCP заголовка только в сегменте TCP SYN. Каждая сторона на TCP соединении сообщает свое значение MSS другой стороне. Хост отправитель обязан ограничивать размер данных в единственном TCP сегменте в значение, меньшем или равном MSS, о котором сообщает хост получатель.

Первоначально, значение MSS означало, сколько памяти нужно выделить (больше или равной 65496 КБ) на станции получателя, чтобы в состоянии хранить TCP данные, содержавшиеся в пределах единственной IP датаграммы. MSS был максимальным сегментом (кусочком) данных, которые желал принимать TCP получатель. Этот TCP сегмент мог быть огромным, примерно до 64 КБ (максимальный размер IP датаграммы), и его необходимо было фрагментировать на уровне IP, чтобы передать по сети к хосту получателю. Принимающий хост повторно должен был собрать IP датаграмму прежде, чем передать полный TCP сегмент на уровень TCP.

Рассмотрим ниже несколько показательных сценариев, от том как установливаются и используются значения MSS, чтобы ограничить размеры TCP сегмента, и соотвественно, размеры IP датаграммы.

Сценарий 1 иллюстрирует способ, которым реализовывлся MSS ранее. Хост A имеет буфер 16 КБ а Хост B - буфер 8 КБ. Они посылают и получают свои МSS значения и корректируют их чтобы послать данные друг другу. Заметьте, что Хост A и Хост B должны фрагментировать IP датаграммы, которые по размеру больше чем MTU интерфейса, но все еще меньше чем посылаемый MSS, потому что стек TCP может передать 16 КБ или 8 КБ данных в IP стек. В случае Хоста B, пакеты могут быть фрагментированы дважды, один раз, чтобы дойти до Token Ring LAN и еще раз, чтобы добраться до сети Ethernet.


  1. Хост А посылает свое MSS значениеХ в 16К Хосту B
  2. Хост B принимает значение MSS 16K от Хоста A
  3. Хост B устанавливает MSS посылки в значение 16K
  4. Хост B посылает свое значение MSS в 8K хосту A
  5. Хост A принимает значение MSS 8K от Хоста B
  6. Хост A устанавливает MSS посылки в значение 8K
Для того, чтобы уйти от IP-фрагментации, на конечных точках TCP соединения, выбранные значения MSS были изменены на минимальный размер буфера и MTU исходящего интерфейса (-40). Значение MSS на 40 байт меньше чем значение MTU, потому что MSS это только размер TCP данных, который не включает 20-байтовый заголовок IP и 20-байтовый заголовок TCP. MSS основан на значениях размера заголовков по умолчанию; стек отправителя должен вычесть соответствующие значения для IP заголовка и TCP заголовка в зависимости от того, какая используется TCP или IP опция.

Способ которым теперь работает MSS это то, что каждый хост сначала сравнивает свой MTU исходящего интерфейса с его собственным буфером и выберет самое низкое значение в качестве MSS, для посылки. Затем хосты сравнят полученный размер MSS, с их собственным MTU интерфейса и снова выберут меньшее из двух значений.

Сценарий 2 иллюстрирует этот дополнительный шаг, сделанный отправителем, чтобы избежать фрагментации на локальных и удаленных каналах. Посмотрите, как принимается во внимание MTU исходящего интерфейса каждым хостом (прежде, чем хосты пошлют друг другу свои значения MSS), и как это помогает избежать фрагментации.


  1. Хост A сравнивает свой MSS буфер (16 КБ) и свой MTU (1500 - 40 = 1460) и использует наименьшее значение как MSS (1460), чтобы послать его Хосту B.
  2. Хост B получает MSS (1460) который послал хост A, и сравнивает его со значением MTU своего исходящего интерфейса - 40 (4422).
  3. Хост B устанавливает наименьшее значение (1460) как MSS для того, чтобы послать IP датаграммы Хосту A.
  4. Хост B сравнивает свой MSS буфер (8 КБ) и свой MTU (4462-40 = 4422) и использует 4422 как MSS, чтобы послать его Хосту A.
  5. Хост A получает MSS от хоста B (4422), и сравнивает его со значением MTU своего исходящего интерфейса -40 (1460).
  6. Хост А устанавливает наименьшее значение (1460) как MSS для того, чтобы посылать IP датаграммы Хосту B.
1460 это значение, выбранное обоими хостами как МSS посылка друг для друга. Часто посылаемое значение MSS будет тем же самым на каждой стороне TCP соединения.

В Сценарии 2, фрагментация не происходит, потому что хостами были приняты во внимание MTU обоих интерфейсов. Пакеты могут все еще фрагментироваться в сети между Router A и Router B, если они встретят линк с более низким MTU.