DIVERT


Краткое описание
Перенаправляемые (divert) сокеты подобны на необработанные IP-пакеты, за исключением того, что они могут быть перенавравлены на определенный порт divert посредством системного вызова bind. При этом IP-адрес игнорируется, значение имеет только номер порта. divert-сокет, привязанный к divert-порту, будет получать все пакеты, направленные к этому порту, посредством некоторого (неопределенного здесь) механизма системного ядра. Пакеты могут быть также записаны в divert-порт, в этом случае они проходят повторно обработку IP-пакетов системным ядром.

divert-сокеты обычно используются в сочетании с фильтрацией пакетов и программной ipfw.

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

Чтение пакетов
Пакеты перенаправляются (заворачиваются) либо по мере их "входа", либо по мере "выхода". Входящие пакеты заворачиваются после их получения IP-интерфейсом, а "исходящие" пакеты - перед следующим отскоком. divert-пакеты могут обязательно читаться read(2), recv(2) или recfrom(2). B посдеднем случае возвращаемый адрес будет иметь установки порта, которые установит перенаправитель пакетов (обычно это номер правила ipfw) и IP-адрес устанавливается равным адресу интерфейса, которым этот пакет был принят (если пакет был входящим) или INADDR_ANY, если пакет был исходящим. В случае входящиего пакета имя интерфейса будет помещено также в 8 байт сдедующих за адресом (принимая его установки).

Запись пакетов
Запись divert-сокетов подобна записи подобна написи исходных (необработанных) IP-пакетов. пакет впускается "как есть" сквозь обычную обработку пакетов системным ядром, производится минимальная проверка ошибок. Пакеты записываются либо как входящие, либо как исходящие: если write(2) или send(2) используются для доставки пакетов, или IP-адрес назначения INADDR_ANY, если используется sendto(2). Затем пакет обращается как если бы он был исходящим, т.е. направленный не на локальный адрес. В противном случае пакет принимается как входящий и выполняется полная маршрутизация пакета. В последнем случае IP-адрес определяется определенный IP-адрес должен соответствовать адресу некоторого локального интерфейса или имя имя интерфейса должно быть найдено после IP-адреса. Если имя интерфейса найдено, то этот интерфейс будет использован и значение IP-адреса будет проигнорировано (иначе, чем в случае INADDR_ANY). Это производится для обозначения интерфейса, на который "прибыл" пакет.

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

Детали
Чтобы можно использовать divert необходимо откомпилировать ядро с опцией IPDIVERT. Если пакет перенаправлен, однако с портом не связано никакого приложения, либо системное ядро откомпилировано без опции IPDIVERT, то пакет отбрасывается. Перенаправляемые фрагменты входящих пакетов перед доставкой полностью пересобираются. Перенаправление любого одного фрагмента приводит к перенаправлению всего пакета. Если различные фрагменты перенаправляются в разные порты, то какой порт будет выбран в конечном итоге - непрадсказуемо. Пакеты отправляются и принимаются неизменными за исключением того, что у пакетов, прочитанных как "исходящие", неправильна контрольная сумма заголовков IP, и у них корректируется контрольная сумма (у IP-заголовков). Входящие пакеты с неправильными контрольными суммами отбрасываются. В противном случае все поля заголовков остаются неизменными (в соответствии с сетевыми правилами).

Привязка к номеру порта, меньшему, чем 1024, требует доступ с правами суперпользователя, как создающий сокет типа SOCK_RAW.

Ошибки
Запись в перенаправляющий сокет может наряду с обычными ошибками, возможными при записи RAW-пакетов, возвращать такие ошибки:

[EINVAL]
У пакета неправильный заголовок, или же IP-опции в пакете и установки сокета были несовместимыми

EADDRNOTAVAIL
Адрес назначения содержит IP-адрес, не эквивалентный INADDR_ANY, который не связан ни с каким интерфейсом

Обновлено: 12.03.2015