繁体   English   中英

如何阻止Indy中的未知客户端(Delphi)

[英]how to block unknown clients in indy (Delphi)

我有一个公共服务器(配置了indy 10)。 一些未知的客户端正在发送数千条无内容的消息,这些消息将服务器的CPU使用率更改为50%。 我的服务器上没有防火墙,因此我尝试使用以下代码阻止未知客户端:

这是与Timer一起使用的功能:

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。

谢谢

OnConnect事件将是断开列入黑名单的IP的更好位置。 在OnExecute事件中进行检查的唯一原因是,直到触发OnConnect之后才将IP列入黑名单。

至于为什么OnExecute在断开连接后仍保持运行-唯一可能发生的方法是,如果OnExecute处理程序具有try..except块来捕获和丢弃Indy的内部通知。 您所做的任何异常处理都需要重新引发EIdException派生的异常,以便服务器可以处理它们。

我先前评论的后续行动:

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;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM