|
Краткое описание Перенаправляемые (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, который
не связан ни с каким интерфейсом |
|