如何設置能限制某個IP某一時間段的訪問次數是一個讓人頭疼的問題,特別面對惡意的ddos攻擊的時候。其中CC攻擊(Challenge Collapsar)是DDOS(分布式拒絕服務)的一種,也是一種常見的網站攻擊方法,攻擊者通過代理服務器或者肉雞向向受害主機不停地發大量數據包,造成對方服務器資源耗盡,一直到宕機崩潰。
cc攻擊一般就是使用有限的ip數對服務器頻繁發送數據來達到攻擊的目的,nginx可以通過HttpLimitReqModul和HttpLimitZoneModule配置來限制ip在同一時間段的訪問次數來防cc攻擊。
HttpLimitReqModul用來限制連單位時間內連接數的模塊,使用limit_req_zone和limit_req指令配合使用來達到限制。一旦並發連接超過指定數量,就會返回503錯誤。
HttpLimitConnModul用來限制單個ip的並發連接數,使用limit_zone和limit_conn指令
HttpLimitReqModul實例
限制某一時間段內同一ip連接數
http{
…
#定義一個名為allips的limit_req_zone用來存儲session,大小是10M內存,
#以$binary_remote_addr 為key,限制平均每秒的請求為20個,
#1M能存儲16000個狀態,rete的值必須為整數,如果限制兩秒鐘一個請求,可以設置成30r/m
limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
…
server{
…
location {
…
#限制每ip每秒不超過20個請求,漏桶數burst為5
#brust的意思就是,如果第1秒、2,3,4秒請求為19個,第5秒的請求為25個是被允許的。
#但是如果你第1秒就25個請求後面的5個請求就會被限制,返回503錯誤。
#nodelay,如果不設置該選項,嚴格使用平均速率限制請求數,
#也就是說如果你設置rate=120r/m,相當於每秒只允許處理2個請求
limit_req zone=allips burst=5 nodelay;
…
}
…
}
…
}
HttpLimitZoneModule實例,
限制並發連接數
limit_zone只能定義在http作用域,limit_conn可以定義在http server location作用域
http{
…
#定義一個名為one的limit_zone,大小10M內存來存儲session,以$binary_remote_addr 為key
limit_zone one $binary_remote_addr 10m;
…
server{
…
location {
…
limit_conn one 20; #連接數限制
limit_rate 500k; #帶寬限制,對單個連接限數,如果一個ip兩個連接,就是500x2k
…
}
…
}
…
}
nginx白名單設置
以上配置會對所有的ip都進行限制,有些時候我們不希望對搜索引擎的蜘蛛或者自己測試ip進行限制,
對於特定的白名單ip我們可以借助geo指令實現。
1.
http{
geo $limited{
default 1;
64.233.160.0/19 0;
65.52.0.0/14 0;
66.102.0.0/20 0;
66.249.64.0/19 0;
72.14.192.0/18 0;
74.125.0.0/16 0;
209.85.128.0/17 0;
216.239.32.0/19 0;
#M$
64.4.0.0/18 0;
157.60.0.0/16 0;
157.54.0.0/15 0;
157.56.0.0/14 0;
207.46.0.0/16 0;
207.68.192.0/20 0;
207.68.128.0/18 0;
#yahoo
8.12.144.0/24 0;
66.196.64.0/18 0;
66.228.160.0/19 0;
67.195.0.0/16 0;
74.6.0.0/16 0;
68.142.192.0/18 0;
72.30.0.0/16 0;
209.191.64.0/18 0;
#My IPs
127.0.0.1/32 0;
123.456.0.0/28 0; #example for your server CIDR
}
geo指令定義了一個白名單$limited變量,默認值為1,如果客戶端ip在上面的范圍內,$limited的值為0
2.使用map指令映射搜索引擎客戶端的ip為空串,如果不是搜索引擎就顯示本身真是的ip,這樣就不能存到limit_req_zone內存session中
map $limited $limit {
1 $binary_remote_addr;
0 “”;
}
3.設置limit_req_zone和limit_req
limit_req_zone $limit zone=foo:1m rate=10r/m;
limit_req zone=foo burst=5;