Больше сокетов TCP и POSIX: слушайте () и принимайте () семантику - PullRequest
3 голосов
/ 11 апреля 2009

Ситуация: сервер вызывает listen () (но не accept ()!). Клиент отправляет SYN на сервер. Сервер получает SYN, а затем отправляет SYN / ACK обратно клиенту. Однако клиент теперь зависает / умирает, поэтому он никогда не отправляет ACK обратно на сервер. Соединение находится в состоянии SYN_SENT.

Теперь другой клиент отправляет SYN, возвращает SYN / ACK с сервера и отправляет обратно ACK. Это соединение находится в состоянии УСТАНОВЛЕНО.

Теперь сервер наконец-то вызывает accept (). Что просходит? Блокирует ли accept () первое ошибочное соединение до истечения некоторого времени ожидания? Проверяет ли он очередь на наличие УСТАНОВЛЕННЫХ соединений и возвращает их сначала?

Ответы [ 3 ]

5 голосов
/ 11 апреля 2009

Хорошо, то, что вы описываете здесь, является типичной синодальной атакой (http://en.wikipedia.org/wiki/SYN_flood) при выполнении более одного раза.

При поиске, например: http://lkml.indiana.edu/hypermail/linux/kernel/0307.0/1258.html есть две отдельные очереди, одна очередь синхронизации и одна установленная очередь. Очевидно, что первое соединение останется в очереди syn (так как оно находится в состоянии SYN_RCVD), второе соединение будет в установленной очереди, откуда accept () получит его. Netstat должен по-прежнему показывать первый в состоянии SYN_RCVD.

Примечание : см. Также мой комментарий, это клиент, который будет в состоянии SYN_SENT, сервер (который мы обсуждаем) будет в состоянии SYN_RCVD.

2 голосов
/ 12 апреля 2009

Следует отметить, что в некоторых реализациях наполовину открытое соединение (соединение в состоянии SYN_RCVD) может даже не записываться на сервере. Реализации могут использовать файлы cookie SYN , в которых они кодируют всю информацию, необходимую для завершения установления соединения, в порядковый номер пакета SYN + ACK. Когда пакет ACK возвращается с увеличенным порядковым номером, они могут уменьшить его и получить информацию обратно. Это может помочь защитить от наводнений SYN, не выделяя никаких ресурсов на сервере для этих полуоткрытых соединений; таким образом, независимо от того, сколько дополнительных SYN-пакетов отправляет клиент, серверу не хватит ресурсов.

Обратите внимание, что SCTP реализует четырехстороннее рукопожатие с использованием файлов cookie, встроенных в протокол, для защиты от потоков SYN, позволяя хранить больше информации в файле cookie и, таким образом, не ограничивая протокол поддерживаемые функции, потому что размер файла cookie слишком мал (в TCP вы получаете только 32 бита порядкового номера для хранения всей информации).

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

0 голосов
/ 11 апреля 2009

Вы должны помнить, что listen(), accept() и др. не под инструментами отладки протокола капота. На справочной странице accept: «принять - принять соединение через сокет». О неполных соединениях не сообщается, и не должно быть. Приложению не нужно беспокоиться о настройке и отключении сокетов, повторных передачах, повторной сборке фрагментов или ...

Если вы пишете сетевое приложение, охватить то, о чем вы должны беспокоиться - это более чем достаточно. Если у вас есть работающее приложение, но вы пытаетесь выяснить проблемы, используйте хороший инструмент для отладки сети, инструменты для проверки состояния вашей ОС и т. Д. НЕ пытайтесь вставить это в свои приложения.

Если вы пытаетесь написать инструмент отладки, то вы не сможете выполнить то, что хотите, используя вызовы TCP / IP уровня приложения. Вам нужно будет выпасть хотя бы на один уровень.

...