2017-03-15 10 views
3

どのようにippごとの接続を制限できますか?私はこのコードを試しましたhow to block unknown clients in indy (Delphi)しかし、私のサーバーが浸水している私は接続できません。 Remyのコードは、CPUが100%を使用してより多くのRAMを使用することを防ぎます。しかし、tcpserver上でまだ洪水からの接続が生きていて、私はサーバーに接続できません。だから私の質問は、どのように私は接続の前にtcpserverを使用して受け入れるには、接続を制限することができますですか?多分フック受け入れ機能と接続を制限しようとする?IPブラックリストTcpServer

+1

おそらく、ファイアウォールなど、ハードウェアレベルで着信接続をブロックするのが最良です。問題が攻撃者によってサーバーに負荷をかけている場合は、書き込むコードの数は問題ではなく、技術的にはまだアプリケーションに移行しています。結局のところ、それはDDoSの仕組みの本質です。 –

+0

はい、私は9999のクライアントを作成して接続し、私のシステムをフリーズする小さなアプリを怒らせました。だから私はファイアウォールを使用せずにipごとの接続を制限する必要があります。 –

+0

私の以前のコメントを拡張するために、この正確な性質のDDoS攻撃を防ぐために明示的に設計されたハードウェアファイアウォールが多数あります。ほとんどの標準的な/安いルータはそれを処理できません。私はDDoS対策を行っていたビジネスクラスのSonicWallルータでDDoSをテストしました。私はインターネットを紛失する前に英国の友人が3秒間しか攻撃をしていないので、二階に行って物理的に再起動しなければなりませんでした。 –

答えて

5

どのようにipごとの接続を制限できますか?

これはまさにthe other codeさんのやっているとおりです。

私のサーバーが浸水していると接続できません。

他のコードの目的は、洪水またはより低いCPU/RAM使用量を妨げない、10の同時接続の最大にクライアントIPアドレスを制限するだけです。サーバーを無効にするか、サーバーのMaxConnectionsプロパティを設定しない限り、不要なクライアントがサーバーに接続するのを防ぐことはできません。それ以外では、サーバーのOnConnectイベントでできるだけ早く不要なクライアントを切断することができます。しかし、もしあなたが浸水しているなら、特にサーバーのContextsリストを連続的にロックしたりロックを解除したりすると、サーバーの内部スレッドをシリアライズすることになります。

フラッド管理は、実際にはサーバーアプリケーション自体ではなく、ファイアウォールやルーター/ロードバランサで処理する必要があります。これがあなたにとって受け入れられない場合は、少なくともWindowsのみで、仮想Accept()メソッドをオーバーライドするカスタムTIdServerIOHandlerStack-derivedコンポーネントを書き込んで、WinSockのWSAAccept()関数を呼び出すことができますそれらは受け入れ待ち行列を離れるので、TIdTCPServerでは表示されません。たとえば、次のように

type 
    TMyServerIOHandler = class(TIdServerIOHandlerStack) 
    public 
    function Accept(ASocket: TIdSocketHandle; AListenerThread: TIdThread; AYarn: TIdYarn): TIdIOHandler; override; 
    end; 

function MyConditionFunc(lpCallerId, lpCallerData: LPWSABUF; lpSQOS, lpGQOS: LPQOS; lpCalleeId, lpCalleeData: LPWSABUF; g: PGROUP dwCallbackData: DWORD_PTR): Integer; stdcall; 
begin 
    if (the address stored in lpCallerId is blocked) then 
    Result := CF_REJECT 
    else 
    Result := CF_ACCEPT; 
end; 

type 
    TIdSocketHandleAccess = class(TIdSocketHandle) 
    end; 

function TMyServerIOHandler.Accept(ASocket: TIdSocketHandle; AListenerThread: TIdThread; AYarn: TIdYarn): TIdIOHandler; 
var 
    LIOHandler: TIdIOHandlerSocket; 
    LBinding: TIdSocketHandle; 
    LAcceptedSocket: TIdStackSocketHandle; 
begin 
    Result := nil; 
    LIOHandler := TIdIOHandlerStack.Create(nil); 
    try 
    LIOHandler.Open; 
    while not AListenerThread.Stopped do 
    begin 
     if ASocket.Select(250) then 
     begin 
     LBinding := LIOHandler.Binding; 
     LBinding.Reset; 
     LAcceptedSocket := WSAAccept(ASocket.Handle, nil, nil, @MyConditionFunc, 0); 
     if LAcceptedSocket <> Id_INVALID_SOCKET then 
     begin 
      TIdSocketHandleAccess(LBinding).SetHandle(LAcceptedSocket); 
      LBinding.UpdateBindingLocal; 
      LBinding.UpdateBindingPeer; 
      LIOHandler.AfterAccept; 
      Result := LIOHandler; 
      LIOHandler := nil; 
      Break; 
     end; 
     end; 
    end; 
    finally 
    FreeAndNil(LIOHandler); 
    end; 
end; 

その後、サーバーを起動する前に、TIdTCPServer.IOHandlerプロパティにTMyServerIOHandlerのインスタンスを割り当てることができます。

+0

[dcc32エラー] Unit1.pas(372):E2003宣言されていない識別子: 'IOHandlerSocketClass' –

+0

は現在[dcc32エラー] Unit1.pas(1682):E2010互換性のないタイプ: 'TIdServerIOHandler'および 'class 「TMyIdServerIOHandler」のIdTCPServer1.IOHandler:= TMyIdServerIOHandlerを割り当てようとすると、 –

+0

@DouglasRuiz 'TIdTCPServer.IOHandler'プロパティはオブジェクトへのポインタであり、クラス型ではありません。 'IdTCPServer1.IOHandler:= TMyIdServerIOHandler.Create(IdTCPServer1);' –

関連する問題