나는 Nginx에서 실행되는 Drupal을 Limit_conn 및 Limit_req를 사용하여 간단한 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개의 동시 연결로 이 구성을 테스트하면
ab -n 100 -c 5 http://test.dev/
차단이 발생하지 않습니다.
제한을 11개의 nginx로 올리-c 11
자마자 요청을 차단하기 시작합니다. - 전역 연결 제한을 10에서 5로 수정하면 nginx는 6개 이상의 연결을 제한합니다( ). 블록
-c 6
의 지시문이 무시되는 것처럼 보입니다 .location ~ \.php$
- 서버 수준에서 지시문 을 삭제하면 블록
conn_limit
의 지시문이location ~ \.php$
갑자기 작동하기 시작합니다! - 더 혼란스러운 점은 블록
conn_limit
에 지시문 을 추가하면location /
전역 지시문을 올바르게 덮어쓰게 된다는 것입니다!
어쩌면 문제가 try_files
지시문이나 다중 리디렉션에 있는 것일까요? 누군가가 conn_limit
예상한 대로 지시문을 덮어쓰지 않는 이유를 설명할 수 있다면 매우 감사하겠습니다 .
답변1
@AlexeyTen 덕분에 질문에 답할 수 있었으면 좋겠습니다.
중요한 점은 다음 두 가지입니다.
- 지시문은
limit_conn
요청당 한 번만 처리됩니다! limit_conn
이러한 지시어는 현재 수준에 지시어가 없는 경우에만 이전 수준에서 상속됩니다 .
요약: 지시문이 있으면 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
no 에서 지시문 limit_conn
을 발견하여 at 지시문을 location /
처리합니다. 다시 말하지만, 우리는 location ~ \.php$
블록을 무시하고 있습니다.