RFC: 793
Оригинал: Transmission Control Protocol
Предыдущие версии: RFC 761
Категория: Стандарт Интернета
Дата публикации:
Автор:
Перевод: Николай Малых

Полуоткрытые соединения и другие аномалии

Организованное соединение называют полуоткрытым (half-open), если одна из сторон TCP закрыла или прервала соединение от себя, а другая сторона не знает об этом или обе стороны находятся в рассинхронизированном состоянии в результате краха с потерей памяти. Такие соединения будут автоматически сбрасываться при попытке передачи данных в любом направлении. Однако, полуоткрытые соединения являются не совсем обычными и процедура восстановления для них будет отличаться.

Если на сайте A соединение больше не существует, тогда попытка пользователя с сайта B передать какие-либо данные через это соединение будет приводить к тому, что TCP B получит управляющее сообщение reset. Такое сообщение говорит TCP B о некорректности соединения и необходимости его разрыва.

Предположим, что пользователи A и B обменивались данными в момент краха TCP с потерей памяти на хосте A. В зависимости от операционной системы хоста A запускается тот или иной механизм повторной загрузки TCP. После восстановления TCP хост A будет пытаться организовать соединение заново или восстановить его. В результате хост может попытаться снова вызвать функцию OPEN для восстановления соединения или попытается вызвать SEND, надеясь, что соединение существует. Во втором случае будет получено сообщение об ошибке connection not open от локального (A) TCP. При попытке организации нового соединения TCP A будет передавать сегмент, содержащий SYN (этот сценарий показан на рисунке 10). После краха TCP A пользователь пытается заново организовать соединение, а TCP B предполагает, что соединение существует по прежнему.

    TCP A                                           TCP B

1.  (CRASH)                               (send 300,receive 100)

2.  CLOSED                                           ESTABLISHED

3.  SYN-SENT --> <SEQ=400><CTL=SYN>              --> (??)

4.  (!!)     <-- <SEQ=300><ACK=100><CTL=ACK>     <-- ESTABLISHED

5.  SYN-SENT --> <SEQ=100><CTL=RST>              --> (Abort!!)

6.  SYN-SENT                                         CLOSED

7.  SYN-SENT --> <SEQ=400><CTL=SYN>              -->

Рисунок 10. Обнаружение полуоткрытого соединения

При получении SYN (строка 3) TCP B, будучи в синхронизированном состоянии, видит входящий сегмент за пределами окна и отвечает подтверждением с порядковым номером следующего сегмента, который ожидается (ACK 100). TCP A видит, что этот сегмент (подтверждение) не подтверждает ничего из переданного им и, будучи в рассинхронизированном состоянии, передает RST, поскольку обнаружено полуоткрытое соединение. TCP B прерывает соединение (строка 5). TCP A будет продолжать попытки организовать соединение, используя стандартную трехэтапную процедуру согласования (см. рисунок 7).

Интересный случай наблюдается при крахе TCP A, когда TCP B пытается передать данные, предполагая наличие синхронизированного соединения (см. рисунок 11). В этом случае данные, приходящие TCP A от TCP B (строка 2), не могут быть восприняты по причине отсутствия соединения, поэтому TCP A будет слать RST. Сообщение RST воспринимается TCP B, после чего соединение будет разорвано.

    TCP A                                              TCP B

1.  (CRASH)                                   (send 300,receive 100)

2.  (??)    <-- <SEQ=300><ACK=100><DATA=10><CTL=ACK> <-- ESTABLISHED

3.          --> <SEQ=100><CTL=RST>                   --> (ABORT!!)

Рисунок 11. Активная сторона пытается использовать полуоткрытое соединение

На рисунке 12 показаны TCP A и TCP B в пассивном состоянии, ожидающие SYN. Старый дубликат, принимаемый TCP B (строка 2), заставляет B начать действия. Возвращается сегмент SYN-ACK (строка 3), который заставляет TCP A генерировать RST (ACK в строке 3 не может быть принят). TCP B принимает сигнал сброса и возвращается в свое пассивное состояние LISTEN.

    TCP A                                         TCP B

1.  LISTEN                                        LISTEN

2.       ... <SEQ=Z><CTL=SYN>                -->  SYN-RECEIVED

3.  (??) <-- <SEQ=X><ACK=Z+1><CTL=SYN,ACK>   <--  SYN-RECEIVED

4.       --> <SEQ=Z+1><CTL=RST>              -->  (return to LISTEN!)

5.  LISTEN                                        LISTEN

Рисунок 12. Старый дубликат SYN инициирует Reset при двух пассивных сокетах

Возможно множество других ситуаций, каждая из которых разрешается при соблюдении рассмотренных ниже правил генерации и обработки RST.

2007 - 2017 © Русские переводы RFC, IETF, ISOC.