如何在 indy (Delphi) 中阻止未知客户端

发布于 2024-09-13 11:21:15 字数 1016 浏览 9 评论 0原文

我有一个公共服务器(配置有 indy 10)。一些未知的客户端正在发送数千条无内容消息,它将服务器的 CPU 使用率更改为 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。

谢谢

I have a public server(configured with indy 10) . some unknown clients are sending thousands of no content messages that it change the server's cpu usage to 50% . i have no firewall on my server , so i tried to block the unknown clients with this codes :

This is a function that works with a 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;

And it's my Timer code :

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

So i use it in OnExecute event :

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

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

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

finally , if a client sends many message in a short time , it will be disconnect . but there is a problem . in fact , after client disconnection , the Onexecute event is still working and i can not stop the operation Fully .anyway i need to block some IPs completely .

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

红墙和绿瓦 2024-09-20 11:21:16

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

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

The OnConnect event would be a better place to disconnect blacklisted IPs. The only reason to do the check in the OnExecute event is if the IP is not being blacklisted until after OnConnect has already been fired.

As for why OnExecute keeps running after you disconnect - the only way that can happen is if your OnExecute handler has a try..except block that is catching and discarding Indy's internal notifications. Any exception handling you do needs to re-raise EIdException-derived exceptions so the server can process them.

翻身的咸鱼 2024-09-20 11:21:16

我之前的评论的后续:

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;

Followup to my earlier comment:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文