Я разрабатываю приложение, которое выполняет NAT между виртуальным интерфейсом TAP и физическим интерфейсом, и я не уверен, сколько буфера мне следует выделить для фрагментации IP.
Согласно Википедии, максимальное значение для «Смещения фрагмента» ограничено 8189, но возможно ли, что источник отправляет 2 или более фрагментированных пакета одновременно? Или он будет отправлять их последовательно (т.е. не отправляет еще один фрагментированный пакет, пока не закончит первый)?
Смещение фрагмента
Смещение фрагмента - это 13-битное поле, и если вы интерпретируете эти биты как целое число без знака, максимальное значение будет 8191. Но на самом деле он подсчитывает числа, кратные 8 байтам, поэтому было бы столь же разумно сказать, что значения идут от От 0 до 65528 с шагом 8.
Какое именно максимальное допустимое значение этого поля не имеет особого значения. Что важно, так это максимальное значение суммы полей смещения и длины. Если эта сумма слишком велика, пакет недействителен. Даже если каждое поле в отдельности находится в допустимом диапазоне, их сумма может превышать допустимые значения. Отсутствие подтверждения суммы при получении может привести к нарушениям безопасности.
Пакет, использующий эту конкретную брешь в системе безопасности, получил название «пинг смерти». Это несколько вводит в заблуждение, потому что это не имеет ничего общего с ping в первую очередь и привело к распространенному заблуждению о том, что ping-пакеты опасны.
Все вышесказанное относится к смещению фрагмента, упомянутому в вашем вопросе, но в остальном не имеет отношения к вашему фактическому вопросу.
Поле IP ID
Вы спрашиваете, может ли источник отправлять два фрагментированных пакета одновременно. В соответствии со стандартом, безусловно, приемлемо чередование двух фрагментированных пакетов у отправителя. Однако это редко имеет смысл. Однако не могу делать никаких предположений по этому поводу.
В случае использования NAT, возможно, что два пакета, которые были отправлены с двух разных хостов с разными IP-адресами, в конечном итоге будут иметь идентичный исходный IP-адрес, когда достигнут пункта назначения. И как только поток фрагментов из двух разных источников встречается, они могут перемежаться.
Даже если такой NAT не использовался, все еще возможно, что пакеты будут переупорядочены в сети (например, если они будут маршрутизироваться по разным путям). Таким образом, они могут перемежаться после достижения пункта назначения по ряду причин.
Чтобы получатель мог правильно собрать пакеты, в заголовке есть поле IP-идентификатора (16 бит для IPv4 и 32 бит для IPv6). Для повторной сборки получатель должен учитывать исходный IP-адрес, IP-адрес назначения и IP-идентификатор. В принципе, этого достаточно для повторной сборки полезных данных, которые чередовались при передаче.
К сожалению, в случае с NAT все не так просто. Допускается одновременная отправка пакета двумя разными хостами с разными IP-адресами, каждый из которых имеет одинаковый IP-идентификатор. (Это, очевидно, должно быть разрешено, потому что ни один из них не может знать о пакете, отправленном другим). Однако, если исходный IP-адрес пакетов изменяется с помощью NAT, так что теперь они имеют идентичный исходный IP-адрес, они больше не могут быть различимы.
Исправление этой проблемы в NAT не очень практично. Поэтому нет ничего необычного в том, что NAT просто игнорирует его и надеется на лучшее. Это означает, что существует риск того, что фрагментированные пакеты, отправленные через NAT, будут неправильно собраны и, возможно, утечка данных из одного соединения в другое соединение.
Этот риск значительно меньше для IPv6 из-за большего размера поля IP ID. Он также меньше, потому что с IPv6 вы не используете NAT (если вам не нравится отлаживать проблемы, связанные с NAT).