私は、limit_conn と limit_req を使用して、Nginx 上で実行されている Drupal を単純な DDoS から保護しようとしています。しかし、limit_conn
ディレクティブの継承に関して説明できない奇妙な動作が発生しました。
nginx (1.8.0) の設定を最低限にまで減らしたところ、問題が明らかになりました。
limit_conn_zone $binary_remote_addr zone=perip:10m;
server {
server_name test.dev;
root /var/nginx/drupal; ## <-- Your only path reference.
#Allow not more than 10 simultaneous connections from one address.
limit_conn perip 10;
location / {
#limit_conn perip 1;
# This is cool because no php is touched for static content
try_files $uri @rewrite;
}
location @rewrite {
# Clean URLs are handled in drupal_environment_initialize().
rewrite ^ /index.php;
}
location ~ \.php$ {
#Allow not more than 1 simultaneous *connection_to_PHP* from one address.
limit_conn perip 1;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi.conf;
fastcgi_intercept_errors on;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
}
ご覧のとおり、すべてのリクエストの同時接続数を 10 に制限し、PHP バックエンドの同時接続数を 4 に制限したいと考えています。(この例では、4 つの接続を 1 に変更して、トリガーしやすくしました)
Nginxのドキュメントhttp://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_conn次のように述べています。
limit_conn
これらのディレクティブは、現在のレベルにディレクティブがない場合にのみ、前のレベルから継承されます。
limit_conn
しかし、私のテストでは奇妙なことが起こり、nginx がブロック内のディレクティブを無視しているようですlocation ~ \.php$
。
- この設定を 5 つの同時接続でテストすると、ブロックは発生しません。 制限を 11 に
ab -n 100 -c 5 http://test.dev/
上げるとすぐに、nginx はリクエストをブロックし始めます。-c 11
- グローバル接続制限を 10 から 5 に変更すると、nginx は 6 を超える接続を制限します ( ) -ブロック
-c 6
内のディレクティブは無視されるようです 。location ~ \.php$
- サーバー レベルでディレクティブを削除すると
conn_limit
、ブロック内のディレクティブがlocation ~ \.php$
突然機能し始めます。 - さらに混乱を招くのは、
conn_limit
ディレクティブをブロックに追加するとlocation /
、グローバル ディレクティブが正しく上書きされることです。
おそらく、問題はディレクティブまたは複数のリダイレクトにありますか?ディレクティブが期待どおりに上書きされないtry_files
理由を誰かが説明してくれると非常にありがたいです。conn_limit
答え1
@AlexeyTen のおかげで、質問に答えられると思います。
重要なのは次の2点です。
- ディレクティブは
limit_conn
リクエストごとに 1 回だけ処理されます。 limit_conn
これらのディレクティブは、現在のレベルにディレクティブがない場合にのみ、前のレベルから継承されます。
TL;DR: ディレクティブがある場合limit_conn
、nginx は実行チェーン内の子ブロックを調べ、ない場合はlimit_conn
親ブロックが処理されます。その後、他のすべてのlimit_conn
ディレクティブは無視されます。
私の例を使って説明してみます:
私が投稿した例では、「http://test.dev/" リクエストが到着すると、最初は nginx はレベルlimit_conn
で処理せずserver
、一致する場所を調べるのを待ちますlocation /
。ただし、このレベルにはディレクティブがないlimit_conn
ため、nginx はserver
レベルのディレクティブを処理します。その後は、limit_conn
すでに処理されているため、すべてのディレクティブは無視されます。これが私のテスト 1 ~ 3 を説明しています。
テスト 4 では、nginx はlimit_conn
location でディレクティブを見つけてlocation /
処理しますが、ここでも location location @rewrite
nolimit_conn
は見つからないため、 at のディレクティブlocation /
が処理されます。ここでも、ブロックは無視されますlocation ~ \.php$
。