Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > AntiFlood как реализовать?


Автор: azesmcar 13.4.2009, 14:22
Добрый день,

Есть серверная система. Есть class ServerSocket и class SocketUser. Нужно реализовать антифлуд на сокетах. Т.е. если пользователь начал флудить - отключить его, при рецидиве - заблокировать АЙПИ к примеру.
Вот только не приходит на ум как это реализовать. 
Код

void ServerSocket::OnUserAction(SocketUser* user)
{
   //тут надо проверить не флудит ли пользователь прежде чем вызввать обработчика
   actionHandlers->ExecuteCorrespondingHandler( SocketUser->Message()->Type );
}


только беда в том что нужно иметь данные о прежних сообщениях пользователя. A где их хранить? В классе SocketUser?
Код

void ServerSocket::OnUserAction(SocketUser* user)
{
   if ( user->AreYouFlooding() )
      user->GoToHell();

   actionHandlers->ExecuteCorrespondingHandler( SocketUser->Message()->Type );
}

Нелогично как-то получается спрашивать у пользователя а не флудит ли он?
Хранить для этого отдельный контейнер? (ну или адаптер на контейнер)
Код

void ServerSocket::OnUserAction(SocketUser* user)
{
   floodChecker_->AddUserMessage( user );
   if ( floodChecker_->IsFlooding( user ) )
      user->GoToHell();

   actionHandlers->ExecuteCorrespondingHandler( SocketUser->Message()->Type );
}

Тоже не очень, так как придется каждый раз снова искать его в контейнерe, притом что пользователь передан событию как параметр и если запихнуть эти данные в него - получится оптимальнее (но некрасиво) smile 

Вот вобщем-то и вопрос.

Спасибо заранее

Автор: andrew_121 13.4.2009, 15:24
Цитата(azesmcar @  13.4.2009,  14:22 Найти цитируемый пост)
Нелогично как-то получается спрашивать у пользователя а не флудит ли он?

Да. А он взял и правду сказал. И правда не логично smile 

И еще. Многова не понятно. Знаки препинания расставьте. smile 

Автор: azesmcar 13.4.2009, 15:38
Цитата

Да. А он взял и правду сказал. И правда не логично smile 


Суть не в том что пользователь может сказать правду или не правду. Суть в том что с точки зрения логики распределения обязанностей классов - роль проверки "флуда пользователя" не подходит классу самого пользователя.

Автор: Lazin 13.4.2009, 18:49
мне кажется это нужно делать не на уровне SocketUser а намного выше, я не знаю что это за приложение, но если это что-то вроде мессенджера, то у тебя все-равно будет какой-либо компонент, который будет хранить историю сообщений, какую-либо информацию о пользователе и тд, вот где-то там это и нужно реализовывать

Автор: azesmcar 13.4.2009, 19:02
Lazin

Точно! Это не совсем мессенджер, но один из сервисов приложения - обмен текстовыми сообщениями. Я хочу построить антифлуд на уровне базового сервиса..т.е. чтобы он работал для каждого сервиса. Хоть какая-то базовая защита от дос атаки.

Компоненты высокого уровня есть, и в принципе они могут это проверить но только из базы данных.
Поиск по базе - операция медленная, делать это для каждого сообщения не хотелось бы делать..да и в map придется делать поиск по пользователю, правда там он будет намного быстрее.
Наверное так и сделаю, так как пока другого выхода не вижу. Т.е. выходит этот вариант?

Код

void ServerSocket::OnUserAction(SocketUser* user)
{
   floodChecker_->AddUserMessage( user );
   if ( floodChecker_->IsFlooding( user ) )
      user->GoToHell();
   actionHandlers->ExecuteCorrespondingHandler( SocketUser->Message()->Type );
}


Автор: Lazin 13.4.2009, 20:57
Цитата(azesmcar @  13.4.2009,  19:02 Найти цитируемый пост)
защита от дос атаки

ну, защита от перегрузки и защита от флуда это разные вещи, флуд это из той-же категории что и спам - анализ поведения пользователя, а защита на уровне соединения может выглядеть так: у продюсера есть очередь с сообщениями, мы добавляем туда сообщения методом push, а другой поток, достает оттуда сообщения и отправляет их (он может реализовывать алгоритм Нагеля или нет, не суть выжно...), если во время вызова push размер очереди превышает некоторый порог, метод push блокируется, и не возвращает управление, пока другой поток не выберет все сообщения и не отправит их потребителю. В этом случае скорость, с которой данные могут быть отправлены, будет зависеть от того, с какой скоростью они могут быть обработаны. smile 

Автор: azesmcar 13.4.2009, 21:04
Lazin

Ну флуд это одна из разновидностей ДОС атаки. 
Цитата

    * Флуд (англ. flood) — атака, связанная с большим количеством обычно бессмысленных или сформированных в неправильном формате запросов к компьютерной системе или сетевому оборудованию, имеющая своей целью или приведшая к отказу в работе системы из-за исчерпания ресурсов системы — процессора, памяти либо каналов связи.


А вот насчет очереди мысль интересная...можно реализовать. Только вот контейнер queue в стандарт не вошел. Надо будет написать адаптер видимо (не люблю не стандартных решений) smile
В принципе если в очереди пользователя больше чем N-ое число необработанных сообщений разница во времени между которыми не более секунды - это флуд. Адаптер очереди может имплементировать патерн State и перевести в состояние Blocked - как только flood detected.
Думаю сойдет, спасибо.

Автор: zim22 13.4.2009, 21:32
Цитата(azesmcar @  13.4.2009,  21:04 Найти цитируемый пост)
Только вот контейнер queue в стандарт не вошел

вы уверены что не вошёл?
23.2.3.1. Class template queue

Автор: Lazin 13.4.2009, 21:52
тут нужна несколько другая очередь

Добавлено через 3 минуты и 25 секунд
concurrent_queue из intel threading building blocks, или просто порт завершения

Автор: azesmcar 13.4.2009, 21:56
zim22

Интересный вопрос..я был уверен что - не вошел

Эффективное использование STL
user posted image

а вот стандарт...
user posted image

 smile

Добавлено через 1 минуту и 24 секунды
Цитата

тут нужна несколько другая очередь


Завтра во время реализации разберусь..главное идея smile

Автор: Любитель 13.4.2009, 23:11
azesmcar, в твоей цитате речь о другом. Что есть стандартные контейнеры, но они строго говоря не являются STL-совместимыми (всякие begin, end и прочее) по тем или иным причинам.

Автор: azesmcar 14.4.2009, 00:34
Любитель

Фразу "контейнер queue не относится к STL (стандартной библиотеке C++)" понимать как "не является STL совместимым?"
Я почему-то понимаю ее как - не вошла в стандарт. Но в стандарте ясно сказано
Цитата

The C++ Standard library provides 32 C++ headers, as shown in table 11. 

И среди них stack, queue, bitset ...

Так как то что
Цитата

provides standard C++ library

Цитата

не относится к STL

?

Добавлено через 2 минуты и 13 секунд
Модераторам: Нельзя ли вынести тему связанную сo стандартностью queue вынести в отдельную?

Спасибо smile 

Автор: Любитель 14.4.2009, 00:59
STL - это часть стандартной библиотеки. Хотя в любом случае фраза из книги звучит немного кривовато smile std::queue - самый что ни на есть стандартный контейнер (ну или, как принято говорить, контейнерный адаптер).

Автор: azesmcar 14.4.2009, 08:27
Любитель
Видимо перевод неудачный. Если глубоко вникнуть - понять можно, но я ее давно читал..как понял так и запечатлелась smile
Ладно спасибо, посмотрю оригинал Мейерса по этому вопросу.

Автор: zim22 14.4.2009, 08:58
Цитата(azesmcar @  14.4.2009,  08:27 Найти цитируемый пост)
Видимо перевод неудачный

русские переводы книг - это зло.
вот пример из книги, которую я сейчас читаю:
Код

for (Node *p = node->next; p; / * удаление */) { ... }

в оригинале это было так:
Код

for (Node *p = node->next; p; / * empty */) { ... }

Автор: azesmcar 14.4.2009, 09:02
zim22
smile сейчас уже в основном на английском читаю..то раньше было, просто неправильно запомнилось.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)