简体   繁体   中英

how to block unknown clients in indy (Delphi)

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

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.

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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