URL ごと、IP ごと、haproxy を使用したレート制限

URL ごと、IP ごと、haproxy を使用したレート制限

私たちのサーバーは、常に誰かの攻撃を受けています。DDOS ではありません。1 つの IP が 1 つの URL に 1 秒間に 200 回以上アクセスするだけです。現在、IP テーブルによってユーザーをブロックしています。負荷分散には HAproxy を使用しています。IP とアクセスされる URL に基づいてユーザーを制限する方法はありますか?

NAT されたユーザーが影響を受ける可能性があるため、IP のみに基づいてブロックしたくありません。特定の IP が 5 分間に www.example.com/somepage.php?some=option&other=option2 などの同じ URL に 3000 回以上アクセスした場合に 503 エラー ページを表示したいとします。これは、同じ IP が www.example.com/somepage.php?another=someotheroption などの他の URL にアクセスできることを意味します。

答え1

このソリューションには少なくとも haproxy 1.6 が必要です。

まず、フロントエンドに以下を追加します。

http-request set-header X-DOS-Protect %[src];%[req.fhdr(host)]%[capture.req.uri]

次に、バックエンドに以下を追加します。

stick-table type integer size 1m expire 5m store http_req_rate(5m)
tcp-request inspect-delay 5s
tcp-request content track-sc0 req.fhdr(X-DOS-Protect),crc32(1) if HTTP
http-request tarpit if { sc0_http_req_rate gt 3000 }

X-DOS-Protect ヘッダーを構成する連結文字列にコンバーターを適用する方法が見つからなかったため、フロントエンドで追跡を行う方法を見つけることができませんでした。

ハッシュ関数を適用しているのは、スティック テーブルに巨大な文字列を保存しないようにするためです。巨大な文字列を保存すると、簡単にサービス拒否が発生する可能性があります。このハッシュ関数は衝突の可能性が多すぎるため適していないと思われる場合は、次のように、連結された各コンポーネントに crc32 を適用して、ハッシュ関数を大きくすることもできます (もちろん、データを保存するときにこれを削除し、より大きなスティック テーブル ストレージに切り替えます)。

http-request set-header X-DOS-Protect %[src,crc32(1)];%[req.fhdr(host),crc32(1)]%[capture.req.uri,crc32(1)]

stick-table type string len 30 size 1m expire 5m store http_req_rate(5m)
tcp-request inspect-delay 5s
tcp-request content track-sc0 req.fhdr(X-DOS-Protect) if HTTP
http-request tarpit if { sc0_http_req_rate gt 3000 }

この最後のソリューションでは、スティック テーブルの各エントリに対して、最初のソリューションよりも 7 倍以上のメモリが使用されることに注意してください。 もちろん、衝突のリスクも大幅に小さくなります。

関連情報