суббота, 30 июня 2012 г.

Уязвимости серверов к медленному чтению

По мотивам старой статьи на habrahabr.

Когда я писал echo_server, этой статьи на Хабре еще не было. Но я думал о том, что клиент (remote peer) может «нарочно медленно» принимать данные. Именно поэтому я использую класс ma::cyclic_buffer, совмещающий в себе и буфер приема, и буфер отправки. Благодаря такому совмещению, мне, кажется, удалось более гибко распределить ресурсы сервера:
  • с одной стороны, я выставляю ограничение памяти (размер буфера) на всю сессию,
  • с другой – это ограничение динамически распределяется на буфер отправки и буфер приема одновременно, т.е. выделенное пространство используется максимально эффективно.
Кроме того, я реализовал таймаут. И не просто таймаут на отправку (хотя хватило бы и его), но совмещенный таймаут (+ сэкономил один таймер) «активности remote peer»:
в течение указанного для таймаута значения удаленный конец должен завершить хотя бы одну активную операцию ввода/вывода, если только таковая есть (еcли кому-то интересны подробности, спрашивайте в комментариях).
Конечно, это не полноценная защита. Но, IMHO, и сервер (middleware, application layer) надо проектировать так, чтобы минимизировать возможность проведения успешных атак (в т.ч. DOS) – в идеале вообще исключить их.

FAQ

Соберу-ка здесь некоторые полезные материалы по теме сокетов.

Начну с правильного завершения/закрытия TCP-сессии (сокета) с точки зрения Winsock (в Linux, полагаю, можно делать аналогично, т.е. данный подход одинаково хорошо сработает и в Windows и в Linux). Немногие статьи освещают эту тему. Почему-то закрытие TCP-сессии (равно как и останов сервера) часто обделяют должным вниманием.
Кому есть что добавить - милости прошу в комментарии.

Updated 2013/12/04:
RTFM: Йон Снейдер: "Эффективное программирование TCP/IP". Очень правильная книга, вправляющая мозги по поводу многих мифов вокруг TCP. Часто встречаю в сети (форумы, списки рассылок) вопросы, решаемые прямой отсылкой к соответствующей главе данной книги.