最近一直在作location 配置,遇到優先級別問題(若是配置不當可能存在安全隱患哦),如下是我的學習一點體會。php
1、 location 的匹配符
1.等於匹配符:=
等於匹配符就是等號,特色能夠歸納爲兩點:
精確匹配
不支持正則表達式
2.空匹配符
空匹配符的特色是:
匹配以指定模式開始的 URI
不支持正則表達式
3.正則匹配符:~
正則匹配符是可使用正則表達式的匹配符。不過這裏要強調的是,通常來講~是指:
區分大小寫的正則匹配
而~*表示:
不區分大小寫的正則匹配
可是對於一些對大小寫不敏感的操做系統,這二者沒有區別。另一個就是^~,其表示以指定模式開始的正則匹配。css
4.內部訪問符:@
通常用於錯誤頁面等,這個暫不討論。html
2、匹配符優先級
1.=
2.空匹配符,知足精確匹配時
3.^~
4.~或~*
5.空匹配符,知足以指定模式開始時的匹配時
這樣說比較抽象,咱們來看例子吧。nginx
2.1 等於匹配符與精確匹配時的空匹配符正則表達式
看下面的例子(用到咱們此前一塊兒完成的Hello World模塊):windows
location = /poechant {
hello_world no2;
}後端
若是咱們的請求是http://my.domian/poechant,則咱們發現兩個location都與請求的 URI 匹配,這時根據咱們的優先級順序,第一個是精確匹配時的空匹配符,第二個是等於匹配符,因此第二個的優先級高,也就是應該輸出:安全
hello_world, no2
同時也說明 Nginx 的 locatoin 不是按照配置文件中的書寫順序來匹配的。dom
2.2 精確匹配時的空匹配符與正則匹配的^~學習
下面這個例子中,二者開始都精確匹配了,連這個正則匹配都是精確匹配。
location /poechant {
hello_world no2;
}
匹配哪個?你測試一下,會獲得:
hello_world, no2
與咱們上面說的優先級順序相吻合。
3、實戰經驗總結
1.location 匹配的優先級(來自實踐總結中)
(location =) > (location 完整路徑 >) >(location ^~ 路徑) >(location ~* 正則) >(location 路徑)
只要匹配到,其它的都會忽略,而後返回到改匹配。
用如下例子來測試:
說明:測試的時候,先要將#2所有註釋掉,否則會認爲#2 與#4 徹底同樣。會提示:重複配置,提示以下
瀏覽測試:每次都是訪問:http://localhost:9999/a/1.jpg (在windows 安裝測試,而後端口是9999) 文件a/1.jpg 根本不存在。關鍵是測試看頁面返回狀況。
a.用上面的配置請求後的結果
從測試中能夠看到,優先級最高的是:= 號。 它會最早匹配到。
b.接下來咱們 屏蔽掉 #6 以下:
而後重載配置:D:\nginx-0.8.7> nginx -s reload 並訪問:http://localhost:9999/a/1.jpg ,返回如下結果:
結論:從這個測試發現,沒有「=」狀況下,location 後面直接接完整路徑是優先匹配。 經過測試發現,若是將:location/a/1.jpg 改爲:location /a/1\.jpg
會出現意外狀況,直接出現是:return 402. 從這一點,能夠推測到nginx 匹配優先是:網站路徑,而且不帶正則表達式的優先。
c.同理測試 屏蔽掉 #5 以下:註釋及從新加載同上.
訪問:http://localhost:9999/a/1.jpg 返回以下結果。
結論:經過這個測試能夠得出:location ^~ 優先級 高於 location ~* 優先級 ,其中:^~ 主要後面接路徑。
c.同理測試 屏蔽掉 #4 以下:註釋及從新加載同上.
訪問:http://localhost:9999/a/1.jpg 返回以下結果。
結論:從以上比較獲得,正則優先 未帶任何匹配符的路徑匹配
d.同理測試 屏蔽掉 #3 以下:註釋及從新加載同上. 而且去掉#2 的註釋「#」
訪問:http://localhost:9999/a/1.jpg 返回以下結果。
結論:比較有意思是:/a/ 與 / 應該是 同種類型的匹配表達式, 能夠從中獲得,該匹配順序是,將路徑從右匹配, 能夠推測形如逐個字符,那個先匹配到,就是那個優先。 所以獲得是:/a/ 優先於 / .
以上測試,是我測試結果,優先級別以以上規律。 在實際咱們書寫中,常常會犯錯誤。 還記得前段時間:80後安全團隊曝nginx漏洞 其實,我的認爲不能算是nginx 漏洞,只是,咱們不瞭解nginx 配製規則,而出現一個配置上面致命漏洞而已。 其實,經過上面優先級,咱們在配置時候可能也同樣常常犯一個致命錯誤。
location /upload/ {
alias /home/www/html/upload/;
}
並且,這個upload 目錄,是靜態目錄,咱們想法是下面全部文件是不可以執行的,包括php文件。
若是有用戶訪問:http://www.a.com/upload/1.css , 會直接顯示該css, 可是,若是有用戶訪問:http://www.a.com/upload/1.php 相似文件,正如上面所說,實際匹配到:~* \.php$ 了。 upload 下面是執行了。
從這個裏面,咱們發現一個問題,實際沒有達到咱們要求。 靜態目錄下面的文件同樣執行了。 這下比較麻煩了。 一旦出現個什麼上存漏洞的,別人上存了一個php,咱們還覺得,咱們配置是ok的。 以爲很安全,缺在不知不覺中被別人打開一扇門。
那麼咱們怎麼樣修改呢?
對,就是必須用:"^~" ,這樣是否是就已經安全了呢。 若是你再訪問下:http://www.a.com/upload/1.php 你會發現,這段代碼源碼顯示出來了。 這個其實對於咱們而言也是不想見到了。 一段顯示源碼,在各個搜索引擎,很容易經過全部特殊關鍵字,搜索到改文件的。
那麼咱們該怎麼樣配置安全的上存目錄呢? 對,你想到了:限制容許的特殊文件類型。
location ^~ /upload/ {
if ($request_filename ! ~* \.(jpg|jpeg|gif|png|swf|zip|rar|txt)$) {
return 403;
}
alias /home/www/html/upload/;
}
只要不是知足上面擴展名文件,就自動提示:403 不能訪問,有能夠避免源代碼顯示。
剛纔從匹配結果已經知道了,同級不帶任何匹配符的,是以右爲準匹配。 那麼,若是都用正則表達式,以什麼方式匹配呢?
測試以下:(新建配置文件,server 包含)
location ~* 1\.jpg$ {
return 403;
}
結果以下:
看來是返回的是:402 上面一個呢。 按理論說,1.jpg 配置 比 .jpg 更準確,看來跟上面說的順序不一樣,那它會不會是那個在前以那個匹配呢? 咱們再測試下:
location ~* \.jpg$ {
return 402;
}
返回結果是:
哈哈,剛好相反,看來個人推斷是正確的,若是都是正則,都可以匹配,以配置文件出現順序來,誰在前誰優先。 一口氣說了,不知道朋友你,明白個人思路嗎?這樣的比較會不少不少,你們能夠逐一測試。 熟悉location 配置,對於熟練運用nginx 是一個必備基礎。 由於nginx 太靈活,也太流行了。上面的問題,也許朋友你,會遇到。但願對你有幫助。