最近一直在幫一個購買了張戈博客付費服務的朋友作網站防禦,爲了簡單抵擋一下競爭對手的DDoS攻擊,他給網站開啓了Incapsula的免費CDN服務。php
開啓CDN以後,我以前給他寫的Shell防禦腳本也就宣告無效了,由於不論是正常訪問仍是攻擊訪問,腳本拿到的IP都是CDN節點的,而我不可能把CDN的節點IP也給禁用了,那就都不能訪問了。html
爲了解決這個窘迫,我想到了之前看過的Nginx訪問限制。經過查資料,讓我拜讀了一枚大神的神做,感受收穫頗豐!因而轉過來整理一下,分享給更多須要的人!node
Nginx 有2個模塊用於控制訪問「數量」和「速度」,簡單的說,控制你最多同時有 多少個訪問,而且控制你每秒鐘最多訪問多少次, 你的同時併發訪問不能太多,也不能太快,否則就「殺無赦」。nginx
HttpLimitZoneModule 限制同時併發訪問的數量git
HttpLimitReqModule 限制訪問數據,每秒內最多幾個請求github
什麼叫普通配置?shell
普通配置就是針對【用戶瀏覽器】→【網站服務器】這種常規模式的nginx配置。那麼,若是我要對單IP作訪問限制,絕大多數教程都是這樣寫的:瀏覽器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
## 用戶的 IP 地址 $binary_remote_addr 做爲 Key,每一個 IP 地址最多有 50 個併發鏈接
## 你想開 幾千個鏈接 刷死我? 超過 50 個鏈接,直接返回 503 錯誤給你,根本不處理你的請求了
limit_conn_zone $binary_remote_addrzone=TotalConnLimitZone:10m;
limit_conn TotalConnLimitZone50;
limit_conn_log_level notice;
## 用戶的 IP 地址 $binary_remote_addr 做爲 Key,每一個 IP 地址每秒處理 10 個請求
## 你想用程序每秒幾百次的刷我,沒戲,再快了就不處理了,直接返回 503 錯誤給你
limit_req_zone $binary_remote_addrzone=ConnLimitZone:10mrate=10r/s;
limit_req_log_level notice;
## 具體服務器配置
server{
listen80;
location~\.php${
## 最多 5 個排隊, 因爲每秒處理 10 個請求 + 5個排隊,你一秒最多發送 15 個請求過來,再多就直接返回 503 錯誤給你了
limit_req zone=ConnLimitZone burst=5nodelay;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
}
}
|
這樣一個最簡單的服務器安全限制訪問就完成了,這個基本上你 Google 一搜索能搜索到 90% 的網站都是這個例子,並且還強調用「$binary_remote_addr」能夠節省內存之類的云云。安全
目前國內已經爭相出現了百度雲加速、加速樂、360網站衛士以及安全寶等免費CDN。讓咱們這些小網站也能免費享受之前高大上的CDN加速服務。服務器
用戶瀏覽器 → CDN節點 → 網站源服務器
用戶瀏覽器 → CDN節點(CDN入口、CC\DDoS攻擊流量清洗等) → 阿里雲盾 → 源服務器
能夠看到,咱們的網站中間經歷了好幾層的透明加速和安全過濾, 這種狀況下,咱們就不能用上面的「普通配置」。由於普通配置中基於【源IP的限制】的結果就是,咱們把【CDN節點】或者【阿里雲盾】給限制了,由於這裏「源IP」地址再也不是真實用戶的IP,而是中間CDN節點的IP地址。
咱們須要限制的是最前面的真實用戶,而不是中間爲咱們作加速的加速服務器。
其實,當一個 CDN 或者透明代理服務器把用戶的請求轉到後面服務器的時候,這個 CDN 服務器會在 Http 的頭中加入一個記錄
X-Forwarded-For : 用戶IP, 代理服務器IP
若是中間經歷了不止一個代理服務器,這個記錄會是這樣
X-Forwarded-For : 用戶IP, 代理服務器1-IP, 代理服務器2-IP, 代理服務器3-IP, ….
能夠看到通過好多層代理以後, 用戶的真實IP 在第一個位置, 後面會跟一串中間代理服務器的IP地址,從這裏取到用戶真實的IP地址,針對這個 IP 地址作限制就能夠了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
## 這裏取得原始用戶的IP地址
map$http_x_forwarded_for$clientRealIp{
""$remote_addr;
~^(?P<firstAddr>[0-9\.]+),?.*$$firstAddr;
}
## 針對原始用戶 IP 地址作限制
limit_conn_zone $clientRealIpzone=TotalConnLimitZone:20m;
limit_conn TotalConnLimitZone50;
limit_conn_log_level notice;
## 針對原始用戶 IP 地址作限制
limit_req_zone $clientRealIpzone=ConnLimitZone:20mrate=10r/s;
#limit_req zone=ConnLimitZone burst=10 nodelay; #若是開啓此條規則,burst=10的限制將會在nginx全局生效
limit_req_log_level notice;
## 具體Server:以下在監聽php部分新增限制規則便可
server{
listen80;
location~\.php${
## 最多 5 個排隊, 因爲每秒處理 10 個請求 + 5個排隊,你一秒最多發送 15 個請求過來,再多就直接返回 503 錯誤給你了
limit_req zone=ConnLimitZone burst=5nodelay;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
}
}
|
做者原文提到了nginx的一個echo模塊,特地玩了下感受挺有意思的,下面貼一下簡單集成步驟。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
cd/usr/local/src
#下載echo模塊並解壓:
wget https://github.com/openresty/echo-nginx-module/archive/v0.57.tar.gz
tar zxvf v0.57.tar.gz
#下載nginx並解壓
wget http://nginx.org/download/nginx-1.6.0.tar.gz
tar-xzvf nginx-1.6.0.tar.gz
cdnginx-1.6.0/
#查看在用nginx的編譯參數(若是是全新安裝則省略)
/usr/local/nginx/sbin/nginx-V
nginx version:nginx/1.6.0
built by gcc4.4.720120313(Red Hat4.4.7-4)(GCC)#如下這行即爲舊的編譯參數:
configure arguments:--user=www--group=www--prefix=/usr/local/nginx--with-http_gzip_static_module
#在舊的編譯參數基礎上新增【--add-module=/echo模塊的解壓路徑】參數,開始編譯
./configure--prefix=/usr/local/nginx/nginx--add-module=/usr/local/src/echo-nginx-module-0.57
#make編譯
make-j2
#平滑升級nginx (若是是全新安裝請執行:make install)
mv/usr/local/nginx/sbin/nginx/usr/local/nginx/sbin/nginx.old
cp-fobjs/nginx/usr/local/nginx/sbin/
makeupgrade
|
其實就和shell的echo差很少,可否輸出自定義信息。
好比,在nginx裏面配置以下:
1
2
3
|
location/hello{
echo"hello, world!";
}
|
訪問http://yourdomain.com/hello 就會在瀏覽器裏面輸出hello, world! 了(若是域名開了CDN可能會報404)。
又好比,測試本文提到的真實用戶的IP,只要在本文第二步配置基礎上,加上以下規則並reload便可:
1
2
3
4
5
6
7
8
9
10
|
server{
listen80;
server_name yourdomain.com;
## 如下是新增規則:
## 當用戶訪問 /realip 的時候,咱們輸出 $clientRealIp 變量,看看這個變量
## 值是否是真的 用戶源IP 地址
location/realip{
echo$clientRealIp;
}
}
|
生效後,訪問http://yourdomain.com/realip 就能顯示你所用電腦(寬帶)的真實IP了(可在ip138查驗準確性):
Ps:感興趣又喜歡學習的童鞋能夠看下相關wiki文檔:http://wiki.nginx.org/HttpEchoModule
本文介紹到這就差很少結束了,也是在神做的基礎上精簡整理並測試的,若是看完還有些許疑問,請前往查看神做原文,也許仍是大神寫的比較好理解(是不是原創我就不深究了,感受也是轉來轉去,都沒留連接,悲哀的互聯網)!
本文整理自【棒主婦開源】,原文地址:《網站安全配置(Nginx)防止網站被攻擊》。