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