Литмир - Электронная Библиотека

Для меток времени, передаваемых от отправителя к получателю и обратно, существует одноименный параметр. Если во время настройки соединения этот параметр решено было использовать, он добавляется в каждый пакет. Он позволяет получить данные о круговой задержке, которые, в свою очередь, используются для определения потери пакетов. Также он используется в качестве логического расширения 32-битного порядкового номера. При быстром соединении порядковые номера могут проходить полный круг очень быстро, и в результате новые и старые данные будет невозможно отличить. Детектирование повторного использования порядковых номеров (PAWSProtection Against Wrapped Sequence numbers) удаляет сегменты со старыми метками времени, позволяя избежать этой проблемы. Наконец, с помощью выборочного подтверждения (SACK, Selective ACKnowledgement) получатель может сообщать отправителю диапазоны порядковых номеров доставленных пакетов. Этот параметр является дополнением к Номеру подтверждения и используется в случаях, когда после потери пакета данные все равно были доставлены (возможно, в виде копии). Новые данные не отражены в поле заголовка Номер подтверждения, так как оно содержит только следующий по порядку ожидаемый байт. Если использовать выборочное подтверждение, отправитель всегда будет знать, какие данные есть у получателя, и сможет выполнять повторную передачу только тогда, когда это действительно нужно. Выборочное подтверждение описано в RFC 2108 и RFC 2883. В последнее время эта схема используется все чаще. О ее применении при контроле перегрузки мы поговорим в разделе 6.5.10.

6.5.5. Установка TCP-соединения

В протоколе TCP соединения устанавливаются с помощью «тройного рукопожатия». Чтобы установить соединение, одна сторона (например, сервер) пассивно ожидает входящего соединения, выполняя базовые операции LISTEN и ACCEPT, либо указывая конкретный источник, либо не указывая его.

Другая сторона (например, клиент) выполняет операцию CONNECT, указывая IP-адрес и порт, с которым она хочет установить соединение, максимальный размер TCP-сегмента и, по желанию, некоторые данные пользователя (например, пароль). Примитив CONNECT посылает TCP-сегмент с установленным битом SYN и сброшенным битом ACK и ждет ответа.

Когда этот сегмент прибывает в пункт назначения, TCP-подсистема проверяет, выполнил ли какой-нибудь процесс операцию LISTEN, указав в качестве параметра тот же порт, который содержится в поле Порт получателя. Если такого процесса нет, она отвечает отправкой сегмента с установленным битом RST для отказа от соединения.

Компьютерные сети. 5-е издание - _351.jpg

Рис. 6.32. Установка TCP-соединения в нормальном случае (а); одновременная установка соединения обеими сторонами (б)

Если какой-либо процесс прослушивает указанный порт, то входящий TCP-сегмент передается этому процессу. Последний может принять соединение или отказаться от него. Если процесс принимает соединение, он отсылает в ответ подтверждение. Последовательность TCP-сегментов, посылаемых в нормальном случае, показана на рис. 6.32, а. Обратите внимание на то, что сегмент с установленным битом SYN занимает 1 байт пространства порядковых номеров, что позволяет избежать неоднозначности в их подтверждениях.

Если два хоста одновременно попытаются установить соединение друг с другом, то последовательность происходящих при этом событий будет соответствовать рис. 6.32, б. В результате будет установлено только одно соединение, а не два, так как пара конечных точек однозначно определяет соединение. То есть если оба соединения пытаются идентифицировать себя с помощью пары (x, y), делается всего одна табличная запись для (x, y).

Если вы помните, начальное значение порядкового номера, выбранное каждым отдельным хостом, должно медленно меняться, а не равняться константе (например, нулю). Как мы уже говорили в разделе 6.2.2, это правило обеспечивает защиту от задержавшихся копий пакетов. Изначально эта схема была реализована с помощью таймера, изменяющего свое состояние каждые 4 мкс.

Однако проблема реализации схемы «тройного рукопожатия» состоит в том, что слушающий процесс должен помнить свой порядковый номер до тех пор, пока он не отправит свой собственный ,5ТА-сегмент. Это значит, что злонамеренный отправитель может блокировать ресурсы хоста, отправляя на него поток ,5ТА-сегментов и не разрывая соединение. Такие атаки называются затоплением SYN-сегментами (SYN flood). В 1990-е годы из-за них многие веб-серверы оказались парализованными.

Один из методов, позволяющих обезопасить себя от таких атак, называется SYN cookies. Вместо того чтобы запоминать порядковый номер, хост генерирует криптографическое значение номера, записывает его в исходящий сегмент и забывает. Если «тройное рукопожатие» завершается, этот порядковый номер (увеличенный на 1) вернется на хост. Хост может повторно сгенерировать правильный порядковый номер, вычислив значение той же криптографической функции, при условии, что известны входные данные (это может быть IP-адрес и порт другого хоста, а также какое-то секретное значение). С помощью этой процедуры хост может проверять правильность подтвержденного порядкового номера без необходимости отдельно запоминать этот номер. Одна из тонкостей этого метода состоит в том, что он не работает с дополнительными полями (параметрами) TCP. Поэтому SYN cookies можно использовать только в случае затопления SYN-сегментами. Но в целом это очень интересный прием. Более подробно см. RFC 4987 и (Lemon, 2002).

6.5.6. Разрыв соединения TCP

Хотя TCP-соединения являются полнодуплексными, чтобы понять, как происходит их разъединение, лучше считать их парами симплексных соединений. Каждое симплексное соединение разрывается независимо от своего напарника. Чтобы разорвать соединение, любая из сторон может послать TCP-сегмент с установленным в единицу битом НА, это означает, что у него больше нет данных для передачи. Когда этот TCP-сегмент получает подтверждение, это направление передачи закрывается. Тем не менее данные могут продолжать передаваться неопределенно долго в противоположном направлении. Соединение разрывается, когда оба направления закрываются. Обычно для разрыва соединения требуются четыре TCP-сегмента: по одному с битом FIA и по одному с битом ACK в каждом направлении. Первый бит ACK и второй бит НА могут также содержаться в одном TCP-сегменте, что уменьшит количество сегментов до трех.

Как при телефонном разговоре, когда оба участника могут одновременно попрощаться и повесить трубки, оба конца TCP-соединения могут послать FIN-сегменты в одно и то же время. Они оба получают обычные подтверждения, и соединение закрывается. По сути, между одновременным и последовательным разъединением нет никакой разницы.

Чтобы избежать проблемы двух армий (см. раздел 6.2.3), используются таймеры. Если ответ на посланный FIN-сегмент не приходит в течение двух максимальных интервалов времени жизни пакета, отправитель FIN-сегмента разрывает соединение. Другая сторона, в конце концов, заметит, что ей никто не отвечает, и также разорвет соединение. Хотя такое решение и не идеально, но, учитывая недостижимость идеала, приходится пользоваться тем, что есть. На практике проблемы возникают довольно редко.

6.5.7. Модель управления TCP-соединением

Этапы, необходимые для установки и разрыва соединения, могут быть представлены в виде конечного автомата, 11 состояний которого перечислены в табл. 6.5. В каждом из этих состояний могут происходить разрешенные и запрещенные события. В ответ на какое-либо разрешенное событие может осуществляться определенное действие. При возникновении запрещенных событий сообщается об ошибке.

Таблица 6.5. Состояния конечного автомата, управляющего TCP-соединением

197
{"b":"639789","o":1}