UNIX: разработка сетевых приложений - Уильям Стивенс
Шрифт:
Интервал:
Закладка:
Тем самым дейтаграммы IP отсылаются с узла freebsd на узел macosx, обратно на узел freebsd4, и наконец, на macosx, где запущен наш сервер. Две промежуточные системы freebsd4 и macosx должны переправлять дейтаграммы и принимать дейтаграммы с маршрутизацией от отправителя, чтобы этот пример работал.
Когда соединение устанавливается, на стороне сервера выдается следующий результат:
macosx % tcpserv01
received IP options, len = 16
received LSRR, 172.24.37.94 172.24.37.78 172.24.37.94
Первый выведенный IP-адрес — это первый узел обратного маршрута (freebsd4, как показано на рис. 27.2), а следующие два адреса идут в том порядке, который используется сервером для отправки дейтаграмм назад клиенту. Если мы понаблюдаем за процессом взаимодействия клиента и сервера с помощью программы tcpdump, мы увидим, как используется параметр маршрутизации для каждой дейтаграммы в обоих направлениях.
ПРИМЕЧАНИЕК сожалению, действие параметра сокета IP_OPTIONS никогда не было документировано, поэтому вы можете увидеть различные вариации поведения в системах, не происходящих от исходного кода Беркли. Например, в системе Solaris 2.5 первый адрес, возвращаемый функцией getsockopt (см. рис. 27.2) — это не первый адрес в обращенном маршруте, а адрес собеседника. Тем не менее обратный маршрут, используемый TCP, будет корректен. Кроме того, в Solaris 2.5 всем параметрам маршрутизации предшествует четыре параметра NOP, что ограничивает параметр маршрутизации восемью IP-адресами, а не девятью, которые реально могли бы поместиться.
Уничтожение полученного маршрута от отправителя
К сожалению, использование параметра маршрутизации образует брешь в системе обеспечения безопасности программ, выполняющих аутентификацию по IP-адресам (сейчас такая проверка считается недостаточной). Если хакер отправляет пакеты, используя один из доверенных адресов в качестве адреса отправителя, но указывая в качестве одного из промежуточных адресов маршрута от отправителя свой собственный адрес, возвращаемые по обратному маршруту пакеты будут попадать к хакеру, а «отправитель», чьим адресом хакер прикрывался, никогда не узнает об этом. Начиная с выпуска Net/1 (1989), серверы rlogind и rshd использовали код, аналогичный следующему:
u_char buf[44];
char lbuf[BUFSIZ];
int optsize;
optsize = sizeof(buf);
if (getsockopt(0, IPPROTO_IP, IP_OPTIONS,
buf, &optsize) == 0 && optsize != 0) {
/* форматируем параметры как шестнадцатеричные числа для записи в lbuf[] */
syslog(LOG_NOTICE,
"Connection received using IP options (ignored):%s", lbuf);
setsockopt(0, ipproto, IP_OPTIONS, NULL, 0);
}
Если устанавливается соединение с какими-либо параметрами IP (значение переменной optsize, возвращенное функцией getsockopt, не равно нулю), то с помощью функции syslog делается запись соответствующего сообщения и вызывается функция setsockopt для очистки всех параметров. Таким образом предотвращается отправка последующих сегментов TCP для данного соединения по обращенному маршруту от отправителя. Сейчас уже известно, что этой технологии недостаточно, так к моменту установления соединения трехэтапное рукопожатие TCP будет уже завершено и второй сегмент (сегмент SYN-ACK на рис. 2.5) будет уже отправлен по обращенному маршруту от отправителя к клиенту. Даже если этот сегмент не успеет дойти до клиента, то во всяком случае он дойдет до некоторого промежуточного узла, входящего в маршрут от отправителя, где, возможно, затаился хакер. Так как предполагаемый хакер видел порядковые номера TCP в обоих направлениях, даже если никаких других пакетов по маршруту от отправителя послано не будет, он по-прежнему сможет отправлять серверу сообщения с правильным порядковым номером.
Единственным решением этой возможной проблемы является запрет на прием любых соединений TCP, приходящих по обращенному маршруту от отправителя, когда вы используете IP-адрес от отправителя для какой-либо формы подтверждения (как, например, в случае с rlogin или rshd). Вместо вызова функции setsockopt во фрагменте кода, приведенном ранее, закройте только что принятое соединение и завершите только что порожденный процесс сервера. Второй сегмент трехэтапного рукопожатия отправится, но соединение не останется открытым и не будет использоваться далее.
27.4. Заголовки расширения IPv6
Мы не показываем никаких параметров в заголовке IPv6 на рис. А.2 (который всегда имеет длину 40 байт), но следом за этим заголовком могут идти заголовки расширения[7] (extension headers).
1. Параметры для транзитных узлов (hop-by-hop options) должны следовать непосредственно за 40-байтовым заголовком IPv6. В настоящее время не определены какие-либо параметры для транзитных узлов, которые могли бы использоваться в приложениях.
2. Параметры получателя (destination options). В настоящее время не определены какие-либо параметры получателя, которые могли бы использоваться в приложениях.
3. Заголовок маршрутизации. Этот параметр маршрутизации от отправителя аналогичен по своей сути тем, которые мы рассматривали в случае IPv4 в разделе 27.3.
4. Заголовок фрагментации. Этот заголовок автоматически генерируется узлом при фрагментации дейтаграммы IPv6, а затем обрабатывается получателем при сборке дейтаграммы из фрагментов.
5. Заголовок аутентификации (АН — authentication header). Использование этого заголовка документировано в RFC 2402 [65].
6. Заголовок шифрования (ESH — encapsulating security payload header). Использование этого заголовка документировано в RFC 2406 [66].
Мы уже говорили о том, что заголовок фрагментации целиком обрабатывается ядром, как и заголовки АН и ESP, обработка которых управляется согласно базе данных соглашений о безопасности (о сокетах управления ключами читайте в главе 9). Остаются еще три параметра, которые мы обсудим в следующем разделе. Интерфейс этих параметров определен в RFC 3542 [114].
27.5. Параметры транзитных узлов и параметры получателя IPv6
Параметры для транзитных узлов и параметры получателя IPv6 имеют одинаковый формат, показанный на рис. 27.3. Восьмиразрядное поле следующий заголовок (next header) идентифицирует следующий заголовок, который следует за данным заголовком. Восьмиразрядное поле длина заголовка расширения (header extension length) содержит длину заголовка расширения в условных единицах (1 у.e. = 8 байт), но не учитывает первые 8 байт заголовка. Например, если заголовок занимает всего 8 байт, то значение поля длины будет равно нулю. Если заголовок занимает 16 байт, то соответственно значение этого поля будет равно 1, и т.д. Оба заголовка заполняются таким образом, чтобы длина каждого была кратна 8 байтам. Это достигается либо с помощью параметра pad1, либо с помощью параметра padN, которые мы вскоре рассмотрим.
Рис. 27.3. Формат параметра для транзитных узлов и параметра получателя
Заголовок параметра транзитных узлов и заголовок параметра получателя могут содержать произвольное количество отдельных параметров, как показано на рис. 27.4.
Рис. 27.4. Формат отдельных параметров, входящих в заголовок параметра транзитных узлов и заголовок параметра получателя
Этот формат иногда называется TLV, так как для каждого отдельного параметра указывается его тип, длина и значение (type, length, value). Восьмиразрядное поле типа (type) указывает тип параметра. В дополнение к этому два старших разряда указывают, что именно узел IPv6 будет делать с этим параметром в том случае, если он не сможет в нем разобраться:
■ 00 — пропустить параметр и продолжить обработку заголовка.
■ 01 — игнорировать пакет.
■ 10 — игнорировать пакет и отослать отправителю сообщение об ошибке ICMP типа 2 (см. табл. А.6), независимо от того, является ли адрес получателя пакета групповым адресом.
■ 11 — игнорировать пакет и отослать отправителю сообщение об ошибке ICMP типа 2 (см. табл. А.6) но только в том случае, если адрес получателя пакета не является адресом многоадресной передачи.
Следующий разряд указывает, могут ли меняться данные, входящие в этот параметр, в процессе передачи пакета.
■ 0 — данные параметра не могут быть изменены.
■ 1 — данные параметра могут быть изменены.
Оставшиеся пять младших разрядов задают сам параметр. Заметьте, что код параметра определяется всеми восемью битами, младших пяти битов для этого недостаточно. Однако значения параметров выбираются таким образом, чтобы обеспечивать уникальность младших пяти битов как можно дольше.