Если сегмент SYN, полученный от клиента, не содержит никаких параметров IP, переменная len
по завершении функции getsockopt
будет иметь нулевое значение (эта переменная относится к типу «значение-результат»). Как уже упоминалось, нам не нужно предпринимать какие-либо шаги для того, чтобы на стороне сервера использовался обращенный маршрут от отправителя: это делается автоматически без нашего участия [128, с. 931]. Вызывая функцию getsockopt
, мы просто получаем копию обращенного маршрута от отправителя. Если мы не хотим, чтобы TCP использовал этот маршрут, то после завершения функции accept следует вызвать функцию setsockopt
и задать нулевую длину (последний аргумент), тем самым удалив все используемые в текущий момент параметры IP. Но маршрут от отправителя тем не менее уже был использован в процессе трехэтапного рукопожатия при пересылке второго сегмента. Если мы уберем параметры маршрутизации, IP составит и будет использовать для пересылки последующих пакетов какой-либо другой маршрут.
Теперь мы покажем пример клиент-серверного взаимодействия при заданном маршруте от отправителя. Мы запускаем наш клиент на узле freebsd
следующим образом:
freebsd4 % tcpcli01 -g macosx freebsd4 macosx
Тем самым дейтаграммы 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);
}