Почему реализация Linux IPSec не поддерживает фрагментацию перед шифрованием?

Я пытаюсь решить проблему, из-за которой пакеты ESP фрагментируются, поскольку после добавления заголовка ESP превышен размер MTU. Решение (которое делают все) состоит в том, чтобы выполнить фрагментацию перед шифрованием ESP.

Мой вопрос: если это так полезно, почему реализация Linux IPSec изначально не поддерживает это. Я понимаю, что будут определенные ограничения, при которых селекторы трафика L4 не будут работать. Но не все этим пользуются.

Кроме того, если вы можете поделиться какими-либо указателями относительно того, как лучше всего добавить эту поддержку, это действительно поможет.

Спасибо.


person Nikhil Utane    schedule 05.02.2015    source источник
comment
Это может быть очень полезным вопросом и ответом, но кажется, что он лучше подходит для serverfault или network-eng.   -  person Brett Hale    schedule 17.01.2016


Ответы (1)


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

Вот соответствующая выдержка из нашего внутреннего документа, подготовленного Шрирамом Дхарвадкаром, который также выполнял реализацию. Некоторые ссылки относятся к нашим внутренним именам приложений, но не думаю, что у вас должны возникнуть проблемы с пониманием.

Окончательное решение

Очереди NetFilter — это библиотека пользовательского пространства, предоставляющая API-интерфейсы для обработки пакетов, поставленных в очередь фильтром пакетов ядра. Приложение, желающее использовать эту функцию, должно динамически ссылаться на netfilter_queue и nfnetlink и включать необходимые заголовки из sysroot-target/usr/include/libnetfilter_queue/ и sysroot-target/usr. /include/libnfnetlink/. Требуется добавить Iptables с NFQUEUE в качестве цели. NFQUEUE — это цель iptables и ip6tables, которая делегирует решение о пакетах программному обеспечению пользовательского пространства. Например, следующее правило будет запрашивать решение для прослушивающей программы пользовательского пространства для всех пакетов, стоящих в очереди.

iptables -A INPUT -j NFQUEUE --queue-num 0

В пространстве пользователя программное обеспечение должно использовать API libnetfilter_queue для подключения к очереди 0 (по умолчанию) и получения сообщений от ядра. Затем он должен вынести вердикт пакету.
Когда пакет достигает цели NFQUEUE, он ставится в очередь в очередь, соответствующую номеру, заданному параметром --queue-num. Очередь пакетов реализована в виде связанного списка, элементом которого является пакет и метаданные (skb ядра Linux):

  • Это очередь фиксированной длины, реализованная в виде связанного списка пакетов.
  • Хранение пакетов, которые индексируются целым числом
  • Пакет выпускается, когда пользовательское пространство выносит вердикт соответствующему целому индексу.
  • Когда очередь заполнена, ни один пакет не может быть помещен в нее.
  • Пользовательское пространство может читать несколько пакетов и ждать вынесения вердикта. Если очередь не заполнена, это не влияет на это поведение.
  • Пакеты могут быть вынесены без порядка. Пользовательское пространство может читать пакеты 1,2,3,4 и выносить вердикт 4,2,3,1 в указанном порядке.
  • Слишком медленный вердикт приведет к полной очереди. Затем ядро ​​​​отбрасывает входящие пакеты вместо того, чтобы ставить их в очередь.
  • Между ядром и пользовательским пространством используется протокол nfnetlink. Это протокол на основе сообщений, который не использует общую память. Когда пакет поставлен в очередь, ядро ​​отправляет в сокет сообщение в формате nfnetlink, содержащее данные пакета и соответствующую информацию. Пользовательское пространство читает это сообщение и выносит вердикт

Логика префрагментации реализована в AvPreFragApp (новое приложение), а также в Security Broker (существующее приложение-контроллер).
В Security Broker, как только будет установлен туннель. Следующие два правила добавляются в таблицу RAW.

Для предварительной фрагментации TCP:

/usr/sbin/iptables -t raw -I ВЫВОД 1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1360

Приведенное выше правило согласовывает правильный размер MSS во время трехстороннего рукопожатия. Можно с уверенностью предположить, что 1360+TCPH+IPH+ESP+IPH ‹= 1500, так что после шифрования не произойдет фрагментации.

Для предварительной фрагментации UDP:

/usr/sbin/iptables -t raw -I OUTPUT 2 -s ‹tia> -p udp -m mark ! --mark 0xbeef0000/0xffff0000 -j NFQUEUE

Вышеупомянутое правило ставит в очередь все пакеты udp с src ip как TIA (туннельный адрес) и пометкой не равной 0xbeef0000 в очередь netfilter для обработки приложением. 0xbeef0000 будет помечен AvPreFragApp на всех udp-пакетах, стоящих в очереди. Это сделано для того, чтобы избежать повторной постановки пакетов в очередь.

Приложение AvPreFrag

Приложение AvPreFragApp использует очереди сетевого фильтра для обработки пакетов, поставленных в очередь целью NFQUEUE. Как упоминалось выше, правило iptables ставит в очередь пакеты udp, имеющие TIA, поскольку src ip добавляется в брокере безопасности. Это правило добавляется при установлении туннеля и обновляется при возврате туннеля с помощью нового TIA. Таким образом, все пакеты с TIA в качестве исходного IP-адреса ставятся в очередь для обработки AvPreFragApp.

  • AvPreFragApp вызывает набор API из libnetfilter_queue для настройки очереди и копирования пакета из ядра в приложение.
  • При создании очереди передать адрес функции обратного вызова, которая вызывается после того, как пакет поставлен в очередь для обработки
  • Необходимо установить режим NFQNL_COPY_PACKET, он копирует весь пакет из ядра в приложение.
  • Дескриптор файла можно получить с помощью обработчика очереди netfilter. С помощью буфера пакетов функции recv можно получить
  • При обработке пакета AvPreFragApp проверяет размер пакета. Если размер пакета ‹= 1376. Выдается вердикт ACCEPT. Также, если установлен бит DF, выдается вердикт ACCEPT.
  • Если размер пакета > 1376 и бит DF не установлен, выдается вердикт DROP. Это означает, что исходный пакет отброшен. Но до этого пакет копировался бы в буфер приложения. Теперь AvPreFragApp выполняет фрагментацию в приложении. Все эти фрагменты записываются в необработанный сокет с меткой 0xbeef0000. sendmsg используется для записи пакетов в необработанный сокет
  • Эти предварительно фрагментированные пакеты шифруются и инкапсулируются ESP в ядре.

Примечание. TIA: внутренний адрес туннеля, логический интерфейс IPSec.

person Nikhil Utane    schedule 11.01.2016