nginx

Nginxのレート制限でブルートフォース攻撃を防ぐ — limit_req設定ガイド

この記事の対象者
  • Webサーバーへの攻撃を防ぎたい方
  • ログイン画面へのブルートフォース攻撃が心配な方
  • Nginxのレート制限を設定したことがない方

レート制限とは

レート制限は、一定時間内のリクエスト数を制限する仕組みです。これにより以下の攻撃を防ぎます。

攻撃 内容 レート制限の効果
ブルートフォース パスワードの総当たり攻撃 試行回数を大幅に制限
DDoS 大量リクエストでサーバーを過負荷にする 1IPあたりのリクエストを制限
スクレイピング サイト内容の自動大量取得 取得速度を制限

Nginxのレート制限の仕組み

Nginxのレート制限は2段階で設定します。

1. ゾーンを定義 httpブロックで共有メモリゾーンを作成
2. ゾーンを適用 locationブロックでゾーンを指定
制限が有効 超過リクエストは429エラーを返す

基本的な設定方法

Step 1 ゾーンを定義する

http ブロック内(nginx.conf)でゾーンを定義します。

nginx.conf(httpブロック内)
# 一般ページ: 1秒あたり10リクエストまで
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;

# ログインページ: 1秒あたり3リクエストまで(厳しく制限)
limit_req_zone $binary_remote_addr zone=login:10m rate=3r/s;

# 同時接続数の制限
limit_conn_zone $binary_remote_addr zone=addr:10m;
パラメータ 意味
$binary_remote_addr クライアントのIPアドレスをキーにする
zone=general:10m 「general」という名前で10MBの共有メモリを確保
rate=10r/s 1秒あたり10リクエストまで許可

Step 2 ゾーンを適用する

サイト設定ファイル
server {
    # サイト全体に一般的なレート制限を適用
    limit_req zone=general burst=20 nodelay;
    limit_conn addr 20;

    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}

ログインページを保護する

ログインページにはより厳しいレート制限をかけます。

サイト設定ファイル
location /admin/ {
    # ログイン用の厳しいレート制限(1秒あたり3リクエスト)
    limit_req zone=login burst=5 nodelay;
    proxy_pass http://127.0.0.1:8080;
}

なぜログインページに厳しい制限が必要?

ブルートフォース攻撃では1秒間に数十〜数百のログイン試行が行われます。rate=3r/s に制限すれば、攻撃者は1秒に3回しか試行できず、パスワード突破に必要な時間が大幅に増加します。

burstオプションを理解する

burst は一時的なリクエスト集中を許容するバッファです。

設定 動作
burst=5 レート超過時に最大5リクエストをキューに入れて順番に処理
burst=5 nodelay キューに入れず即座に処理。ただし超過分は429エラー
burstなし レート超過は即座に429エラー

一般ページには burst=20 nodelay(ページ読み込み時のCSS/JS同時リクエストに対応)、ログインページには burst=5 nodelay(厳しく制限)を推奨します。

動作確認

設定後、Nginxの構文チェックとリロードを行います。

ターミナル
sudo nginx -t && sudo nginx -s reload

レート制限が効いているか確認するには、短時間に大量のリクエストを送ります。

ターミナル
# 10回連続でリクエストを送信
for i in $(seq 1 10); do
    curl -so /dev/null -w "%{http_code} " https://example.com/admin/
done

レート制限を超えると 429 Too Many Requests が返されます。

302 302 302 429 429 429 429 429 429 429

まとめ

  • レート制限: ブルートフォース・DDoS攻撃を防ぐ基本的な対策
  • 2段階設定: limit_req_zone でゾーン定義 → limit_req で適用
  • 推奨値: 一般ページ 10r/s、ログインページ 3r/s
  • burst: 一時的な集中に対応するバッファ。nodelay で即座に処理