一、簡介
對于網(wǎng)站來說,尤其是流量較大出名的網(wǎng)站,經(jīng)常遇到攻擊,如DDoS攻擊等,雖然有些第三方,如Cloudflare可以擋,但對于動(dòng)態(tài)網(wǎng)站php來說,只能擋一部分。這時(shí)候需要對于單個(gè)IP惡意攻擊做出限流。Nginx的兩個(gè)模塊可以限流。
nginx兩個(gè)限流模塊:
連接頻率限制,
ngx_http_limit_conn_module:官方文檔:https://nginx.org/en/docs/http/ngx_http_limit_conn_module.html
請求頻率限制,ngx_http_limit_req_module:官方文檔:
https://nginx.org/en/docs/http/ngx_http_limit_req_module.html
二、兩者模塊區(qū)別
首先理解請求和連接,HTTP請求建立在一次TCP連接基礎(chǔ)上, 一次TCP連接至少產(chǎn)生一次HTTP請求(1次或多次)
網(wǎng)上理論很多,根據(jù)名字可知:
- connection是連接,即常說的tcp連接,通過三次握手而建立的一個(gè)完整狀態(tài)機(jī)。建立一個(gè)連接,必須要三次握手。
- request是指請求,即http請求,tcp連接是有狀態(tài)的,而構(gòu)建在tcp之上的http卻是無狀態(tài)的協(xié)議。
當(dāng)然還是看不懂的話,通俗點(diǎn)講(相對于時(shí)間比較):
- limit_req_zone,在 有限的時(shí)間 內(nèi)限制,單個(gè)IP每秒或者每分鐘只能發(fā)出多少請求。多的一概不理會(huì)。
- limit_conn_zone, 不限時(shí)間 ,只允許單個(gè)IP這么多個(gè)連接,或者稱為并發(fā)。如:設(shè)置10個(gè)連接,第11個(gè)連接時(shí),必須等前面有一個(gè)已經(jīng)完成或者釋放后,這個(gè)連接才能允許。
比如秒殺,搶購,連接頻率限制和請求頻率限制應(yīng)該配合使用 , 使用連接頻率限制同一IP同時(shí)只能有3個(gè)連接, 再使用請求頻率限制對于同一ip的請求,限制平均速率為5個(gè)請求/秒 , 這樣比單獨(dú)只使用一種限制要好很多。
比如只使用請求頻率限制 , 可以精確地限制同一ip1秒只能發(fā)起5次的http請求 , 假如同一ip1秒內(nèi)發(fā)起了100000次請求 , 雖然限制了只有5次成功響應(yīng) , 但是其他的99995次的請求TCP握手建立http連接是不是會(huì)消耗服務(wù)器資源? 所以還需要配合使用。
三、配置
1、limit_req_zone,示例:
http{
limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
#定義一個(gè)名為allips的limit_req_zone用來存儲(chǔ)session,大小是10M內(nèi)存,
#以$binary_remote_addr 為key,限制平均每秒的請求為20個(gè),
#1M能存儲(chǔ)16000個(gè)狀態(tài),rete的值必須為整數(shù),
#如果限制兩秒鐘一個(gè)請求,可以設(shè)置成30r/m
server{
location / {
#限制每ip每秒不超過20個(gè)請求,漏桶數(shù)burst為5
#brust的意思就是,如果第1秒、2,3,4秒請求為19個(gè),
#第5秒的請求為25個(gè)是被允許的。
#但是如果你第1秒就25個(gè)請求,第2秒超過20的請求返回503錯(cuò)誤。
#nodelay,如果不設(shè)置該選項(xiàng),嚴(yán)格使用平均速率限制請求數(shù),
#第1秒25個(gè)請求時(shí),5個(gè)請求放到第2秒執(zhí)行,
#設(shè)置nodelay,25個(gè)請求將在第1秒執(zhí)行。
limit_req zone=allips burst=5 nodelay;
}
}
}
2、limit_conn_zone,示例:
http {
limit_conn_zone $binary_remote_addr zone=addr:10m;
#定義一個(gè)名為addr的limit_req_zone用來存儲(chǔ)session,大小是10M內(nèi)存,
#以$binary_remote_addr 為key
#nginx 1.18以后用limit_conn_zone替換了limit_conn,
#且只能放在http{}代碼段.
server {
location / {
limit_conn addr 10; #連接數(shù)限制,并發(fā)數(shù)
#設(shè)置給定鍵值的共享內(nèi)存區(qū)域和允許的最大連接數(shù)。超出此限制時(shí),服務(wù)器將返回503(服務(wù)臨時(shí)不可用)錯(cuò)誤.
#如果區(qū)域存儲(chǔ)空間不足,服務(wù)器將返回503(服務(wù)臨時(shí)不可用)錯(cuò)誤
}
}
}
3、搭配一起使用
http {
...
...
limit_req_zone $binary_remote_addr zone=req_zone:1m rate=20r/s;
#限制連接請求設(shè)置,訪問內(nèi)存10M,所有訪問ip 限制每秒10個(gè)請求
limit_conn_zone $binary_remote_addr zone=addr:10m;
#限制連接IP設(shè)置
...
...
server {
listen 80;
server_name ywbj.cc;
location / {
...
limit_req zone=req_zone burst=5 nodelay;
limit_conn addr 5;
...
}
}
}
四、壓力測試工具
1、ab命令
ab是Apache自帶的壓力測試工具。一般不用額外安裝,ab非常實(shí)用,它不僅可以對apache服務(wù)器進(jìn)行網(wǎng)站訪問壓力測試,也可以對或其它類型的服務(wù)器進(jìn)行壓力測試。比如nginx、Tomcat、IIS等。
測試命令
ab -c 10 -n 100 https://ywbj.cc/
#-c10表示并發(fā)用戶數(shù)為10
#-n100表示請求總數(shù)為100
2、wrk命令
需自己安裝,地址:https://github.com/wg/wrk
安裝
git clone git@github.com:wg/wrk.git
#或者自己下載解壓
cd wrk
#進(jìn)入目錄
make
#make編譯后在目錄可使用wrk命令,先安裝make,unzip這些工具。
測試命令:
wrk -t12 -c100 -d30s https://ywbj.cc
#12線程,100連接,30s時(shí)間
還有其他壓測工具,自行研究