ネットワークプログラミングにPHPを使用する場合、 socket_accept()はクライアント接続を受け入れるコア関数です。 DOS(サービスの拒否)攻撃に直面して、攻撃者は通常、多数の悪意のある接続要求を使用し、サーバーリソースを使い果たし、サーバーが正常に正当なユーザー要求に応答できなくなります。この記事では、socket_accept()によって受け入れられた接続の最大数を制限することにより、サーバーが悪意を持ってドラッグされるのを効果的に防止する方法について説明します。
DOS攻撃では、攻撃者がサーバーのサーバーの同時接続を埋める多数の同時接続を作成し、サーバーが新しい通常の要求を処理できなくなります。接続の最大数を制限し、サーバーがリソース許可範囲内で特定の数のクライアント接続のみを処理することを保証することで、この攻撃の影響を効果的に減らすことができます。
変数を使用して、現在確立されている接続の数をカウントします。
新しい接続を受信すると、現在の接続数が制限を超えるかどうかが判断されます。
制限を超えたときに接続を拒否し(新しい接続を閉じます)、 Socket_accept()は処理するために呼び出されなくなります。
接続が閉じたら、時間内に接続カウントを減らします。
次のコードは、最大接続が100であると仮定して、PHPのsocket_accept()に基づいて最大接続制限を実装する方法を示しています。
<?php
set_time_limit(0);
error_reporting(E_ALL);
$address = '0.0.0.0';
$port = 12345;
$maxConnections = 100;
$currentConnections = 0;
// 作成する TCP Socket
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($sock, $address, $port) or die('バインディングは失敗しました');
socket_listen($sock);
echo "サーバーの起動,モニター {$address}:{$port}\n";
$clients = [];
while (true) {
// 接続の最大数を超えるかどうかを判断します
if ($currentConnections < $maxConnections) {
// 非ブロッキングモードは新しい接続を受け入れます
socket_set_nonblock($sock);
$client = @socket_accept($sock);
if ($client !== false) {
// 新しい接続が成功しました,1つをカウントします
$currentConnections++;
$clients[] = $client;
// クライアントのセットアップsocketブロックしていません
socket_set_nonblock($client);
echo "新しいクライアント接続,現在の接続番号: $currentConnections\n";
}
} else {
// 接続の最大数を超えました,新しい接続を拒否します(オプションの待機時間)
usleep(100000); // 100ms
}
// 接続されたクライアントからのデータを処理するためのポーリング
foreach ($clients as $key => $clientSocket) {
$data = @socket_read($clientSocket, 2048, PHP_NORMAL_READ);
if ($data === false) {
// 切断,クライアントを削除します
socket_close($clientSocket);
unset($clients[$key]);
$currentConnections--;
echo "クライアントが切断されました,現在の接続番号: $currentConnections\n";
continue;
} elseif ($data !== '') {
$data = trim($data);
if ($data === 'quit') {
// クライアントは積極的に切断されます
socket_close($clientSocket);
unset($clients[$key]);
$currentConnections--;
echo "クライアントは積極的に切断されます,現在の接続番号: $currentConnections\n";
continue;
}
// クライアントが送信したデータを処理します
$response = "受信したサーバー: {$data}\n";
socket_write($clientSocket, $response, strlen($response));
}
}
usleep(50000); // 減らすCPU占有
}
?>
$ currentConnectionsを使用して、現在のアクティブ接続数を記録します。
接続の最大数を超えない場合にのみ、新しい接続を受信するためにsocket_accept()を呼び出します。
新しい接続が作成されたら、クライアントソケットを$クライアント配列に保存し、非ブロッキングモードに設定します。
$クライアントを投票することにより、クライアントデータを読み取り、応答後にリスニングを続けます。
クライアントがQUITコマンドを切断または送信した場合、ソケットを閉じて接続カウントを減らします。
USLEEP()を使用して、CPUの過剰占有を減らします。
タイムアウトの設定:クライアント接続のアイドル時間を検出すると、タイムアウトは自動的に切断されます。
単一のIP接続の数を制限する:単一のIPが多数の接続を製造するのを防ぎます。
ファイアウォールの使用:サーバーレベルでの例外接続を制限します。
負荷分散を使用します:分散要求圧力。
監視ログ:時間内に異常なトラフィックを発見します。
PHPソケットサーバーの接続数の最大数を制限することにより、ある程度のDOS攻撃に効果的に抵抗し、サーバーリソースの悪意のある枯渇を避けることができます。他のセキュリティ対策と組み合わせて、サーバーをより強固な保護を提供し、サービスの安定した操作を確保することができます。