LINUX.ORG.RU

Завершение соединения при помощи FIN+ACK вместо FIN

 ,


0

3
1 23:08:29.110089 IP cli.43512 > srv.22: Flags [S], seq 818015366, win 29200, options [mss 1460,sackOK,TS val 28178215 ecr 0,nop,wscale 7], length 0
2 23:08:29.294750 IP srv.22 > cli.43512: Flags [S.], seq 3935023731, ack 818015367, win 16384, options [mss 1460,nop,nop,sackOK,nop,wscale 3,nop,nop,TS val 1301048581 ecr 28178215], length 0
3 23:08:29.294810 IP cli.43512 > srv.22: Flags [.], ack 1, win 229, options [nop,nop,TS val 28178400 ecr 1301048581], length 0
4 23:08:29.499011 IP srv.22 > cli.43512: Flags [P.], seq 1:22, ack 1, win 2172, options [nop,nop,TS val 1301048582 ecr 28178400], length 21
5 23:08:29.499059 IP cli.43512 > srv.22: Flags [.], ack 22, win 229, options [nop,nop,TS val 28178604 ecr 1301048582], length 0
6 23:08:35.134925 IP cli.43512 > srv.22: Flags [F.], seq 1, ack 22, win 229, options [nop,nop,TS val 28184240 ecr 1301048582], length 0
7 23:08:35.319602 IP srv.22 > cli.43512: Flags [.], ack 2, win 2172, options [nop,nop,TS val 1301048593 ecr 28184240], length 0
8 23:08:35.319796 IP srv.22 > cli.43512: Flags [F.], seq 22, ack 2, win 2172, options [nop,nop,TS val 1301048593 ecr 28184240], length 0
9 23:08:35.319843 IP cli.43512 > srv.22: Flags [.], ack 23, win 229, options [nop,nop,TS val 28184425 ecr 1301048593], length 0

На приведенном дампе видно как клиент подключается к SSH-серверу (1-3), который отправляет клиенту свой баннер (4) после чего клиент подтверждает прием (5).

Через шесть секунд клиент производит активное закрытие (6), выставляя в сегменте FIN зачем-то еще флаг ACK, таким образом подтверждая уже подтвержденные данные.

Вопрос: зачем это делается?

Почти во всей литературе, в которой разбирается TCP, можно наблюдать такую схему: https://upload.wikimedia.org/wikipedia/commons/5/55/TCP_CLOSE.svg

В RFC 793 в разделе 3.5 (Closing a Connection) говорится:

Case 1: Local user initiates the close

In this case, a FIN segment can be constructed and placed on the outgoing segment queue.

cli: Linux 3.18.7
srv: OpenBSD 5.4

★★★★★

Насколько я понимаю в каждом tcp-пакете высылается информация подтверждающая сколько байт получен (так называемый ack). Это касается и пакета, содержащего fin.

На диаграмме при этом написано просто fin, а не fin+ack, просто потому что на диаграмме пишут лишь основную роль пакета, а не все детали передаваемых данных.

То есть FIN - это всегда FIN+ACK.

GPFault ()
Ответ на: комментарий от GPFault

Насколько я понимаю в каждом tcp-пакете высылается информация подтверждающая сколько байт получен (так называемый ack). Это касается и пакета, содержащего fin.

То есть FIN - это всегда FIN+ACK.

Можно цитату из RFC?

Пока что нашел в RFC 793 следующее:

3.7. Data Communication

Note that once in the ESTABLISHED state all segments must carry current acknowledgment information.

Только вот это никак не относится к 8 строке дампа, в которой сервер, уже будучи не в состоянии ESTABLISHED, в FIN сегменте выставляет флаг ACK и заполняет acknowledgment number, тем самым подтверждая уже подтвержденное (см. 7 строку).

edigaryev ★★★★★ ()
Ответ на: комментарий от edigaryev

Можно цитату из RFC?

«Once a connection is established this is always sent.»

frob ★★★★★ ()
Ответ на: комментарий от frob

Acknowledgment Number: 32 bits

If the ACK control bit is set this field contains the value of the next sequence number the sender of the segment is expecting to receive. Once a connection is established this is always sent.

Про необходимость установки самого флага ACK здесь ничего не говорится.

this is always sent

И вообще, разве можно каким-то образом отправить TCP сегмент без номера подтверждения? Это же не какая-то там опция. Возможно имелось ввиду «this is always set»?

edigaryev ★★★★★ ()
Ответ на: комментарий от edigaryev

Только вот это никак не относится к 8 строке дампа, в которой сервер, уже будучи не в состоянии ESTABLISHED, в FIN сегменте выставляет флаг ACK и заполняет acknowledgment number, тем самым подтверждая уже подтвержденное (см. 7 строку).

Насколько я понимаю TCP может отправлять один acknowledgment number сколь угодно много раз и это делается, для того чтоб если прошлый ip-пакет потерялся, получатель смог прочитать acknowledgment number из последующих пакетов.

И отправка FIN тут по сути ничего не меняет - его ACK может быть существенным подтверждением для принимающей стороны, есл предыдущий пакет потерялся. Более того, с точки зрения TCP после того как одна сторона отправила FIN - вторая сторона вполне может продолжать отправлять данные, а первая будет их подтверждать ACK-ами.

GPFault ()
Ответ на: комментарий от edigaryev

Про необходимость установки самого флага ACK здесь ничего не говорится.

«Control bits: <skip>
ACK: Acknowledgement field significant».

Посмотри на «Figure 13». Сравни со своим выхлопом. Выдыхай.

frob ★★★★★ ()
Ответ на: комментарий от frob

Про необходимость установки самого флага ACK здесь ничего не говорится.

«Control bits: <skip>
ACK: Acknowledgement field significant».

И что из этого, по твоему, следует?

Посмотри на «Figure 13». Сравни со своим выхлопом. Выдыхай.

Видел. Хочешь сказать, что эта иллюстрация, на которую даже никто не сослался из текста RFC — единственное что удерживает имплементацию TCP от отправки сегмента FIN без флага ACK?

edigaryev ★★★★★ ()
Ответ на: комментарий от edigaryev

Тебе нечем заняться?

Если в ACK не мусор, то надо выставить флаг.
В каждом пакете в установленном соединении должен быть ACK, а следовательно и ACK flag.

frob ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.