nginx可以通過limit_conn_zone 和limit_req_zone兩個組件來對客戶端訪問目錄和文件的訪問頻率和次數進行限制,另外還可以善用進行服務安全加固,兩個模塊都能夠對客戶端訪問進行限制,具體如何使用要結合公司業務環境進行配置。
如能善用此模塊能夠對 cc、ddos等此類的攻擊進行有效的防御。
一:nginx訪問限制模塊簡介
nginx限速配置指令
1.
指令
limit_zone
語法:limit_conn_zone $variable zone=name:size;
默認值:no
使用字段:http
指令描述會話狀態存儲區域。
會話的數目按照指定的變量來決定,它依賴於使用的變量大小和memory_max_size的值。
2.
指令
limit_conn
語法:limit_conn zone_name max_clients_per_ip
默認值:no
使用字段:http, server, location
指令指定一個會話的最大同時連接數,超過這個數字的請求將被返回”Service unavailable” (503)代碼。
如下例:
http { imit_conn_zone $binary_remote_addr zone=one:10m; ............ server { listen 80; server_name www.abc.com; location / { limit_conn one 1; #這將指定一個地址只能同時存在一個連接。“one”與上面的對應,也可以自定義命名 limit_rate 300k; } }
limit_zone: 是針對每個IP定義一個存儲session狀態的容器.這個示例中定義了一個10m的容器,按照32bytes/session, 可以處理320000個session。
limit_conn one 1:限制每個IP只能發起一個並發連接。
limit_rate 300k: 對每個連接限速300k. 注意,這里是對連接限速,而不是對IP限速。如果一個IP允許兩個並發連接,那么這個IP就是限速limit_rate×2。
nginx限制訪問頻率配置指令
3.
指令
limit_req_zone
語法:limit_req_zone $session_variable zone=name:size rate=rate
默認值:none
上下文:http
命令解析:為session會話狀態分配一個大小為size的內存存儲區,限制了每秒(分、小時)只接受rate個IP的頻率。
4.
指令
limit_req
語法:limit_req zone=name burst=burst [nodelay]
默認值:none
使用字段:http、server、location
命令解析:該指令用於指定使用的內存存儲區(zone)名稱,以及最大的突發請求數(burse)。如果請求的速率超過了limit_req_zone指令中設置的速率,這些請求將被延遲處理,在這種情況下,請求獲得服務不可用信息,返回503狀態碼。
如下例:
http { limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; server { location /{ limit_req zone=one burst=10; } }
上面的參數會讓nginx 每個IP一秒鍾只處理一個請求,但是仍然會有很多還在隊列里面等待處理,這樣也會占用很多tcp連接,從上面那條命令的結果中就能看得出來。
如果加上nodelay就會立即丟棄
limit_req zone=one burst=10 nodelay;
5.
指令
limit_conn_log_level
語法: limit_conn_log_level info | notice | warn | error
默認值: error
使用字段: http, server, location
指定當連接數超過設定的最大連接數,服務器限制連接時的日志等級。
二、實際應用
如果作為代理服務器,我們需要限制每個用戶的請求速度和鏈接數量,但是,由於一個頁面有多個子資源,如果毫無選擇的都進行限制,那就會出現很多不必要的麻煩,如:一個頁面有40個子資源,那么如果想讓一個頁面完整的顯示,就需要將請求速度和連接數都調整到40,以此達到不阻塞用戶正常請求,而這個限制,對服務器性能影響很大,幾百用戶就能把一台nginx的處理性能拉下來。
所以我們需要制定哪些請求是需要進行限制的,如html頁面;哪些是不需要限制的,如css、js、圖片等,這樣就需要通過配置對應的location進一步細化。
我們不對css、js、gif、png,jpg等進行連接限制,而對除此之外的鏈接進行限制
http { limit_conn_zone $binary_remote_addr zone=addr:10m; limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s; ... server { ... location ~ .*\.(gif|png|css|js|icon)$ { proxy_set_header Host $http_host; proxy_set_header X-Real_IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ~* .*\.(jpeg|jpg|JPG)$ { proxy_set_header Host $http_host; proxy_set_header X-Real_IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #p_w_picpath_filter resize 480 -; #p_w_picpath_filter_jpeg_quality 50; #p_w_picpath_filter_sharpen 10; #p_w_picpath_filter_buffer 4M; } location / { proxy_set_header Host $http_host; proxy_set_header X-Real_IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #limit limit_conn addr 3; limit_req zone=one burst=5; } }
補充路徑詳解:
格式:location ??? {
}
路徑優先級 (與代碼所在前后順序無關,只與規則有關)
1. = /error.html
2. ^~ /images/
3. ~* \.(gif|jpg|jpeg|png|bmp|swf)$
4. /static/
5. /
解釋:
1.表示完整匹配,用=和完全的路徑匹配,比如 =/error.html 就匹配 error.html =/ 匹配根路徑
2.表示開頭等於,優先級第二,越長就越能匹配,比如^~ /abc/cd ^~/abc 第一個會優先匹配/abc/cd/xxx
3.表示不區分大小的正則,並且正則中含義是.jpg等結尾的,優先級第三,同樣正則越長越高。
4.表示開頭等於/static/的,但是優先級比第二種低,是一種其他配置找不到再找它,越長就越能匹配。
5.因為4說了是越長越能匹配,當能匹配/static/就不會匹配/,而/是所有其他的一個默認匹配。
特別補充比如:location ~* \.(gif|jpg|jpeg|png|bmp|swf)$ { //注意正則與其他符號要空格,其他一些配置也是如是。
參考官方文檔:http://nginx.org/en/docs/http/ngx_http_limit_req_module.html