UNIX: разработка сетевых приложений
Шрифт:
Если трехэтапное рукопожатие завершается нормально (то есть без потерянных сегментов и повторных передач), запись остается в очереди не полностью установленных соединений на время одного периода обращения (round-trip time, RTT), какое бы значение ни имел этот параметр для конкретного соединения между клиентом и сервером. В разделе 14.4 [112] показано, что для одного веб-сервера средний период RTT оказался равен 187 мс. (Чтобы редкие большие числа не искажали картину, здесь использована медиана, а не обычное среднее арифметическое по всем клиентам.)
Традиционно в примерах кода всегда используется значение
В
Возникает вопрос: какое значение аргумента
Мы приводим простое решение этой проблемы, изменив нашу функцию-обертку для функции
Листинг 4.1. Функция-обертка для функции listen, позволяющая переменной окружения переопределить аргумент backlog
1
Все исходные коды программ, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com.
Традиционно в руководствах и книгах утверждалось, что помещение фиксированного числа соединений в очередь позволяет обрабатывать случай загруженного серверного процесса между последовательными вызовами функции
Если очереди заполнены, когда приходит клиентский сегмент SYN, то TCP игнорирует приходящий сегмент SYN [128, с. 930–931] и не посылает RST. Это происходит потому, что состояние считается временным, и TCP клиента должен еще раз передать свой сегмент SYN, для которого в ближайшее время, вероятно, найдется место в очереди. Если бы TCP сервера послал RST, функция
Некоторые реализации отправляют сегмент RST в описанной выше ситуации, что некорректно по изложенным выше причинам. Если вы не пишете клиент специально для работы с подобным сервером, лучше всего игнорировать такую возможность. Ее учет при кодировании клиента снизит его устойчивость и увеличит нагрузку на сеть, если окажется, что порт действительно не прослушивается сервером.
Данные, которые приходят после завершения трехэтапного рукопожатия, но до того, как сервер вызывает функцию
В табл. 4.6 показано действительное число установленных в очередь соединений для различных значений аргумента
Таблица 4.6. Действительное количество соединений в очереди для различных значений аргумента backlog
backlog | MacOS 10.2.6 AIX 5.1 | Linux 2.4.7 | HP-UX 11.11 | FreeBSD 4.8 FreeBSD 5.1 | Solaris 2.9 |
---|---|---|---|---|---|
0 | 1 | 3 | 1 | 1 | 1 |
1 | 2 | 4 | 1 | 2 | 2 |
2 | 4 | 5 | 3 | 3 | 4 |
3 | 5 | 6 | 4 | 4 | 5 |
4 | 7 | 7 | 6 | 5 | 6 |
5 | 8 | 8 | 7 | 6 | 8 |
6 | 10 | 9 | 9 | 7 | 10 |
7 | И | 10 | 10 | 8 | 11 |
8 | 13 | 11 | 12 | 9 | 13 |
9 | 14 | 12 | 13 | 10 | 14 |
10 | 16 | 13 | 15 | 11 | 16 |
11 | 17 | 14 | 16 | 12 | 17 |
12 | 19 | 15 | 18 | 13 | 19 |
13 | 20 | 16 | 19 | 14 | 20 |
14 | 22 | 17 | 21 | 15 | 22 |
Системы AIX, BSD/ОХ
Программа для измерения этих значений представлена в решении упражнения 15.4.
Как мы отмечали, традиционно аргумент backlog задавал максимальное значение для суммы обеих очередей. В 1996 году была предпринята новая атака через Интернет, названная SYN flooding (лавинная адресация сегмента SYN). Написанная хакером программа отправляет жертве сегменты SYN с высокой частотой, заполняя очередь не полностью установленных соединений для одного или нескольких портов TCP. (Хакером мы называем атакующего, как сказано в предисловии к [20].) Кроме того, IP-адрес отправителя каждого сегмента SYN задается случайным числом — формируются вымышленные IP-адреса (IP spoofing), что ведет к получению доступа обманным путем. Таким образом, сегмент сервера SYN/ACK уходит в никуда. Это не позволяет серверу узнать реальный IP-адрес хакера. Очередь не полностью установленных соединений заполняется ложными сегментами SYN, в результате чего для подлинных сегментов SYN в ней не хватает места — происходит отказ в обслуживании (denial of service) нормальных клиентов. Существует два типичных способа противостояния этим атакам [8]. Но самое интересное в этом примечании — это еще одно обращение к вопросу о том, что на самом деле означает аргумент backlog функции listen. Он должен задавать максимальное число установленных соединений для данного сокета, которые ядро помещает в очередь. Ограничение количества установленных соединений имеет целью приостановить получение ядром новых запросов на соединение для данного сокета, когда их не принимает приложение (по любой причине). Если система реализует именно такую интерпретацию, как, например, BSD/OS 3.0, то приложению не нужно задавать большие значения аргумента backlog только потому, что сервер обрабатывает множество клиентских запросов (например, занятый веб-сервер), или для защиты от «наводнения» SYN (лавинной адресации сегмента SYN). Ядро обрабатывает множество не полностью установленных соединений вне зависимости от того, являются ли они законными или приходят от хакера. Но даже в такой интерпретации мы видим (см. табл. 4.6), что значения 5 тут явно недостаточно.
4.6. Функция accept
Функция