Получение и сборка исходных текстов

Для использования divert-сокетов в Linux, вам понадобятся две вещи - модифицированные патчем исходные тексты ядра и исходные тексты пакета ipchains версии 1.3.9, также модифицированные соответствующим патчем.

Где взять исходные тексты?

Оба патча можно взять с веб-сайта divert-сокетов http://www.anr.mcnc.org/~divert Для ядра существуют два варианта - патч к неизмененным исходным текстам ядра версии 2.2.12, или готовые модифицированные исходные тексты ядра 2.2.12 (значительно большие по размеру, чем патч). ipchains находится там же, в виде уже модифицированного пакета с исходными текстами.

Сборка

Собрать ipchains достаточно просто - дайте команду
make
в подкаталоге ipchains-1.3.9.

Для включения поддержки divert-сокетов, вам надо пересобрать ядро, предварительно настроив его командой:
make config 
или
make menuconfig 
или 
make xconfig
Не забудьте включить опцию "Поддержку неполных и/или разрабатываемых кодов/драйверов" ("Prompt for development and/or incomplete code/drivers"). Существуют всего три опции, влияющих на работу divert-сокетов, и все они описаны в следующей главе.

Опции, необходимые при сборке ядра

Чтобы использовать divert-сокеты, вам надо включить в ядро поддержку firewall и IP-firewall. На работу divert-сокетов влияют три опции сборки ядра:

IP: divert sockets

Включает поддержку divert-сокетов в ядре.

IP: divert pass-through

Определяет поведение правил DIVERT: по умолчанию правило DIVERT, описанное в firewall, отбрасывает пакеты, при отсутствии программы на порте, определенном этим правилом, то есть действует аналогично правилу DENY.

При включении данной опции, эти пакеты будут проходить дальше через firewall. Опцию можно использовать, если вам нужно статическое правило в firewall, но вы не хотите, чтобы с портом divert-сокетов постоянно работала ваша программа.

IP: always defragment

Определяет, выполнять ли дефрагментирование при передаче данных в сокет. По умолчанию код divert-сокет получает отдельные фрагменты пакетов, имеющих больший, чем MTU, размер и посылает их в таком же виде программе. Задача дефрагментации в этом случае лежит на приложении, использующем divert-сокеты. Более того, приложение не может послать фрагмент пакета, больший, чем MTU - он сразу будет отброшен (это ограничение ядра, а не divert-сокетов - ядра Linux версии до 2.2.x НЕ фрагментируют пакеты с установленной опцией IP_HDRINCL). Обычно в таком поведении нет ничего страшного - в основном, вы просто пересылаете те же фрагменты пакетов, которые получили, и все прекрасно работает - в этом случае, размер фрагментов не будет больше MTU.

Если вы включите опцию always defragment, то все дефрагментирование будет производиться в ядре. Это сильно уменьшает производительность механизма перехвата - каждый большой пакет, который вы хотите перехватить, должен быть сначала собран из фрагментов, и только после этого будет передан вашей программе. Затем, когда вы захотите послать его дальше, он будет снова разбит на части (если в ядре включить эту опцию, то оно будет фрагментировать пакеты, имеющие флаг IP_HDRINCL)

В ядрах Linux версии 2.0.36 подобный выбор не предоставлялся из-за неправильной структуры кода firewall - он обрабатывал только первый фрагмент пакета, а с остальными фрагментами поступал так же, как и с первым, не обрабатывая их. В результате этого, если первый фрагмент был отброшен firewall, то и все остальные отбрасывались дефрагментатором. Поэтому для нормальной работы с divert-сокетами в этой версии ядра вы ДОЛЖНЫ были использовать опцию always defragment для того, чтобы получать весь пакет, а не только его первый фрагмент.

В версии 2.2.12 структура кода firewall была исправлена, и вы можете сами решать, будет ли ядро заниматься (де)фрагментацией, или вы будете делать этой в своей программе.

ВНИМАНИЕ: в версии 1.0.4 divert-сокетов функция дефрагментирования не реализована. Работа над этим продолжается.