特定のIPアドレスを含める/除外するnginxでレート制限する方法は?


27

limit_reqサーバーへのすべてのリクエストをレート制限するために使用できます。

ただし、特定のIPアドレス(つまり、ホワイトリスト)のレート制限を削除し、特定の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_moduleおよびngx_http_limit_conn_moduleを参照してください


これら2つのモジュールの違いは何ですか?
メンテ

1
コメントの通り、第一制限同時接続は、第二は、接続の速度制限
shonky Linuxユーザ

あなたは二段階でマッピングを行うなぜあなたはして、説明することができますgeoが続くmapというだけの使用よりも、geo設定する$limit直接?
マーカスダウニング

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 / {
         ...
      }
   }

「location @slowdown {}」に、「location / {}」と同じ情報を入力します。たとえば、nginxをリバースプロキシとして使用している場合は、proxy_passを入力します。


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.