Nginx limit_conn 繼承

Nginx limit_conn 繼承

我正在嘗試使用 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當且僅噹噹前層級上沒有指令時,這些指令才會從上一層繼承。

但在我的測驗中發生了一些奇怪的事情,看起來 nginx 忽略了區塊limit_conn內的指令location ~ \.php$

  1. 當我用 5 個同時連接測試此配置時ab -n 100 -c 5 http://test.dev/,沒有發生阻塞。一旦我將
    限制提高到 11,-c 11nginx 就會開始阻止請求。
  2. 如果我將全域連線限制從 10 修改為 5,nginx 會限制超過 6 個連線 ( -c 6) - 看起來 location ~ \.php$block 中的指令被忽略。
  3. 如果我conn_limit在伺服器層級刪除該指令,則區塊中的指令location ~ \.php$會突然開始工作!
  4. 更令人困惑的是:如果我添加conn_limitlocation /阻止的指令,它會正確覆蓋全域指令!

也許問題出在try_files指令或多個重定向?如果有人能解釋為什麼該conn_limit指令沒有像預期的那樣被覆蓋,我將非常感激。

答案1

感謝@AlexeyTen,我希望能夠回答這個問題。

重要的是兩點:

  • limit_conn每個請求僅處理該指令一次!
  • limit_conn當且僅噹噹前層級上沒有指令時,這些指令才會從上一層繼承。

TL;DR:如果有limit_conn指令,nginx 會查看執行鏈中的子區塊,如果沒有limit_conn,則處理父區塊。之後所有其他limit_conn指令都將被忽略。

我嘗試用​​我的例子來解釋它:

在我發布的示例中,當“http://test.dev/「 請求到達,一開始,nginx 不是limit_connserverlevel 處理,而是等待查找匹配的 location location /。但是在這一 level 沒有limit_conn指令,所以 nginx 處理該serverlevel 的指令。之後,所有limit_conn指令都被忽略,因為它這解釋了我的測試1-3。

在測試 4 中,nginxlimit_conn在 location 中找到指令location /並處理它,但同樣,在 location 上location @rewrite沒有找到指令,因此處理了limit_conn指令 at 。location /再次,我們忽略了該location ~ \.php$區塊。

相關內容