nginx安全:用limit_req_zone/limit_req限制連接速率(流量控制/限流)


一,limit_req的用途:

1,官方文檔地址:

http://nginx.org/en/docs/http/ngx_http_limit_req_module.html

 

2,用途:

限制用戶在給定時間內HTTP請求的數量,

流量限制主要用作安全目的,

可以防止大量請求的攻擊下服務被壓垮,

可以減慢暴力密碼破解的速率

 

3,原理:漏桶算法

在limit_req的限制下,請求被nginx以固定的速率處理,這個符合漏桶算法,

即流出的速率恆定。

 

說明:劉宏締的架構森林是一個專注架構的博客,地址:https://www.cnblogs.com/architectforest

         對應的源碼可以訪問這里獲取: https://github.com/liuhongdi/

說明:作者:劉宏締 郵箱: 371125307@qq.com

 

二,limit_req的配置舉例:

1,常用的兩個指令:

nginx.conf中

limit_req_zone:定義到http區域:

 limit_req_zone $binary_remote_addr zone=perip:20m rate=1r/s;

 

limit_req:定義到server或location區域

limit_req zone=perip;

 

說明:

變量:$binary_remote_addr,這里是客戶端的ip地址,

          在這里是做限制的標識,是基於ip地址來限制

zone=perip:20m:  perip是內存區域的名字,

                         20m: 生成的內存區域的大小

rate=1r/s:       允放相同標識的客戶端的訪問頻次,

在這個例子中:就是同一個ip地址在每秒內只能訪問1次

 

2,例子一:以每秒處理1個請求的速率做限制

limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;
... limit_req zone
=perip;

重啟 nginx后測試:

[liuhongdi@centos8 logs]$ ab -c 10 -n 10 http://www.lhdtest.com/index.html
...
Concurrency Level:      10
Time taken for tests:   0.002 seconds
Complete requests:      10
Failed requests:        9
   (Connect: 0, Receive: 0, Length: 9, Exceptions: 0)
Non-2xx responses:      9
...

只有一個成功,有9個請求失敗

時長是0.002 seconds

 

3,例子2:burst

增加burst,再次測試

limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;
...
limit_req zone=perip burst=2;

說明:burst=2 允許2個突發,

          有大量請求時,超過頻次限制的請求,會允許2個訪問,

          注意:burst指定的請求數量,不會馬上進行處理,

                    而是按照rate指定的值,以固定的速率進行處理。

          以10個並發請求為例:

          rate= 1r/s

          就是先處理1個,剩下的9個中,

           7個請求,直接返回503

           剩下的2個放到突發的隊列中延遲執行,

          仍然按rate= 1r/s進行處理,所以需要約兩秒的等待時間

[liuhongdi@centos8 logs]$ ab -c 10 -n 10 http://www.lhdtest.com/index.html
...
Concurrency Level:      10
Time taken for tests:   2.004 seconds
Complete requests:      10
Failed requests:        7
   (Connect: 0, Receive: 0, Length: 7, Exceptions: 0)
Non-2xx responses:      7
...

有7個請求失敗

注意時間變成了2.004 seconds

 

4,例子三:nodelay

limit_req_zone $binary_remote_addr zone=perip:10m rate=1r/s;
...
limit_req zone=perip burst=2 nodelay;

說明:

nodelay參數:

burst的隊列雖然可以處理用戶的需求,但需要用戶按照處理時間等待,對用戶不夠友好,

nodelay參數允許請求在排隊的時候就立即被處理,

這里有一點要注意:因為nodelay允許立即處理,也就是有並發請求時

事實上已經超過了rate設置的處理速率了,

所以要根據自己機器的實際情況設置這個值

 

理解nodelay:

nodelay只是對放到burst隊列中的請求立即處理,

但處理完成后隊列並不立即清空,

隊列清空的速度仍然按原來的速度每秒一個清空,

所以當再有請求過來時,並不會馬上又有兩個burst請求被處理.

 

再次測試

[liuhongdi@centos8 logs]$ ab -c 10 -n 10 http://www.lhdtest.com/index.html
...
Concurrency Level:      10
Time taken for tests:   0.002 seconds
Complete requests:      10
Failed requests:        7
   (Connect: 0, Receive: 0, Length: 7, Exceptions: 0)
Non-2xx responses:      7
...

有7個請求失敗

注意時間:這次是0.002 seconds

 

三,rate和burst應該設置為多少?

1,網站需要把動態生成的內容(java,php,python等程序生成)和靜態內容分離到不同的虛擬主機

     因為靜態內容不需要大量的計算,

     通常limit_req用於限制動態內容的訪問頻率

     

2,限流的目的不是讓用戶不能訪問,

      而是為了保證用戶能流暢的訪問,

      所以需要根據頁面的實際情況來限制

      如果一個頁面打開時同時發出的請求比較多,

     (靜態文件分離后要檢查ajax請求數,

      可以根據生產環境的日志進行檢查)

     則rate值不能低於並發的請求數.

     如果低於並發的情求數,會導致用戶不能正常訪問頁面

 

3,我們在生產環境中的例子,僅供參考

     limit_req_zone $binary_remote_addr zone=reqperip:20m rate=20r/s;
     limit_req zone=reqperip burst=10 nodelay;

 

四,其他可配置的參數:

1,limit_req_status用來指定請求時報錯產生的狀態碼:

limit_req_status 這個值默認是503,

可以指定為一個自定義的值,

例如:444

說明:444是nginx自定義的一個非標准狀態碼,

       它會立即關閉連接,連響應頭也不給客戶端發

         可以在受到惡意攻擊時使用這個狀態碼

 

2,limit_req_log_level   當報錯時記錄到日志的錯誤級別,

默認值是error

可選值: info | notice | warn | error

不建議改動這個值

 

五,查看nginx的版本:

[root@centos8 conf.d]# /usr/local/soft/nginx-1.18.0/sbin/nginx -v
nginx version: nginx/1.18.0

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM