как заблокировать неизвестных клиентов в indy (Delphi) - PullRequest
0 голосов
/ 06 августа 2010

У меня есть публичный сервер (настроен на инди 10).Некоторые неизвестные клиенты отправляют тысячи сообщений без содержимого, что приводит к изменению использования процессора сервером до 50%.У меня нет брандмауэра на моем сервере, поэтому я попытался заблокировать неизвестных клиентов с помощью следующих кодов:

Это функция, которая работает с таймером:

var
  i, j: integer;
begin
  IX2 := IX2 + 1;
  SetLength(ClientIPs, IX2);
  ClientIPs[IX2 - 1] := StrIP;
  j := 0;
  for i := low(ClientIPs) to high(ClientIPs) do
  begin
    Application.ProcessMessages;
    if ClientIPs[i] = StrIP then
      j := j + 1;
  end;
  if j > 10 then
  begin
    Result := false;
    exit;
  end;
  Result := true;

И это мой код таймера:

  //Reset filtering measures
  IX2 := 0;
  SetLength(ClientIPs, 0);

Так что я использую его в событии OnExecute:

  LogIP := AContext.Connection.Socket.Binding.PeerIP;

  if IPFilter(LogIP) <> true then
  begin
    AContext.Connection.disconnect;
    exit;
  end;

  //Get Data *********
  Data := AContext.Connection.IOHandler.ReadLn();

наконец, если клиент отправит много сообщений за короткое время, он будет отключен.но есть проблема .на самом деле, после отключения клиента событие Onexecute все еще работает, и я не могу остановить операцию. Полностью. В любом случае мне нужно полностью заблокировать некоторые IP-адреса.

Спасибо

Ответы [ 2 ]

5 голосов
/ 08 августа 2010

Событие OnConnect было бы лучшим местом для отключения занесенных в черный список IP-адресов.Единственная причина для проверки в событии OnExecute заключается в том, что IP-адрес не занесен в черный список до тех пор, пока OnConnect уже не был запущен.

Что касается того, почему OnExecute продолжает работать после отключения - единственный способ, который может произойти, этоесли ваш обработчик OnExecute имеет блок try..except, который перехватывает и игнорирует внутренние уведомления Indy.Любая обработка исключений, которую вы делаете, должна повторно вызывать исключения, производные от EIdException, чтобы сервер мог их обрабатывать.

4 голосов
/ 11 августа 2010

Продолжение моего предыдущего комментария:

function TForm1.IPFilter(const StrIP: string): Boolean;
var 
  i, j: integer; 
  list: TList;
begin 
  j := 0; 
  list := IdTCPServer1.Contexts.LockList;
  try
    for i := 0 to list.Count-1 do 
    begin 
      if TIdContext(list[i]).Binding.PeerIP = StrIP then
        Inc(j); 
    end; 
    Result := j <= 10; 
  finally
    IdTCPServer1.Contexts.UnlockList;
  end;
end;

procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
  // the simpliest way to force a disconnect and stop
  // the calling thread is to raise an exception...
  if not IPFilter(AContext.Binding.PeerIP) then
    Abort();

  // alternatively, if you call Disconnect(), make sure
  // the IOHandler's InputBuffer is empty, or else
  // AContext.Connection.Connected() will continue
  // returning True!...
  {if not IPFilter(AContext.Binding.PeerIP) then
  begin
    AContext.Connection.Disconnect;
    AContext.Connection.IOHandler.InputBuffer.Clear;
    Exit;
  end;}

  //Get Data ********* 
  Data := AContext.Connection.IOHandler.ReadLn(); 
end;
...