nginx에서 속도를 제한하지만 특정 IP 주소를 포함 / 제외하는 방법은 무엇입니까?


27

limit_req모든 요청을 내 서버로 평가하는 데 사용할 수 있습니다 .

그러나 특정 IP 주소 (예 : 화이트리스트)에 대한 속도 제한을 제거하고 다른 특정 주소 (예 : 1r / s만큼 낮은 특정 IP)에 대해 다른 속도 제한을 사용하고 싶습니다.

조건부 (예 :)를 사용해 보았지만 if ( $remote_addr = "1.2.3.4" ) {}속도 제한 규칙이 아닌 다시 쓰기 규칙에서만 작동하는 것 같습니다.

답변:


33

"if"지시문을 사용하지 않는 것이 좋습니다. limit_req_zone (및 limit_conn_zone)의 키가 비어 있으면 제한이 적용되지 않습니다. 이것을 스로틀 한계가 적용되지 않는 IP의 화이트리스트를 작성하기 위해 맵 및 지리 모듈과 함께 사용할 수 있습니다.

이 예는 동시 요청과 단일 IP의 요청 비율 모두에 대한 제한을 구성하는 방법을 보여줍니다.

http {
    geo $whitelist {
       default 0;
       # CIDR in the list below are not limited
       1.2.3.0/24 1;
       9.10.11.12/32 1;
       127.0.0.1/32 1;
    }

    map $whitelist $limit {
        0     $binary_remote_addr;
        1     "";
    }

    # The directives below limit concurrent connections from a 
    # non-whitelisted IP address to five

    limit_conn_zone      $limit    zone=connlimit:10m;

    limit_conn           connlimit 5;
    limit_conn_log_level warn;   # logging level when threshold exceeded
    limit_conn_status    503;    # the error code to return

    # The code below limits the number requests from a non-whitelisted IP
    # to one every two seconds with up to 3 requests per IP delayed 
    # until the average time between responses reaches the threshold. 
    # Further requests over and above this limit will result 
    # in an immediate 503 error.

    limit_req_zone       $limit   zone=one:10m  rate=30r/m;

    limit_req            zone=one burst=3;
    limit_req_log_level  warn;
    limit_req_status     503;

영역 지시문은 http 레벨에 배치해야하지만 다른 지시문은 서버 또는 위치 레벨에 더 멀리 배치하여 범위를 제한하거나 한계를 더 조정할 수 있습니다.

추가 정보는 Nginx 문서 ngx_http_limit_req_modulengx_http_limit_conn_module을 참조하십시오.


이 두 모듈의 차이점은 무엇입니까?
mente

1
의견에 따르면, 첫 번째는 동시 연결을 제한하고 두 번째는 연결 속도를 제한합니다
shonky linux user

당신은 두 단계로 매핑 할 왜 당신은, 설명 할 수 geo다음 map이 아니라 단지 사용하기보다, geo설정 $limit직접?
Marcus Downing

2
보인다 geo지정한 그래서 만약 변수에 매핑 할 수 없습니다 $binary_remote_addr이 리터럴 문자열로 변환하는 매핑 값 "$binary_remote_addr"이 아닌 변수의 값.
ColinM

1
문제의 IP가 이미 영역에 있으면 nginx 다시 시작 해야 한다고 덧붙이고 싶습니다 . 재 장전으로는 충분하지 않습니다.
Halfgaar

5

if () 블록에서 "@location"과 같은 명명 된 위치를 안전하게 사용할 수 있습니다.

참조 : http://wiki.nginx.org/IfIsEvil

이와 같은 것이 작동해야합니다.

http {

   limit_req_zone $binary_remote_addr zone=delay:10m rate=1r/m;

   server {
      ...

      error_page 410 = @slowdown;

      if( $remote_addr != "1.2.3.4" ) {
         return 410;
      }

      location @slowdown {
         limit_req zone=delay burst 5;
         ...
      }

      location / {
         ...
      }
   }

nginx를 리버스 프록시로 사용하는 경우 proxy_pass와 같은 "location / {}과 동일한 정보로"location @slowdown {} "을 채우십시오.


410 부분을 이해하지 못합니까? 클라이언트가 실제로 http 410 상태 코드를 보입니까?
svrist

1
와우, 이것은 실제로 작동합니다! 아주 멋진 error_page트릭, +1! @svrist, serverfault.com/a/870170/110020 에서 이와 같은 작동 방식 및 이유에 대한 자세한 설명을 참조하십시오 .
cnst
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.