1. 程式人生 > >Nginx虛擬主機配置、Nginx的Rwrite配置

Nginx虛擬主機配置、Nginx的Rwrite配置

防火 permanent 開頭 刪除 日誌 inux 就是 控制 add

Nginx虛擬主機配置
一臺機器上跑多個站點,即多個域名
Nginx默認虛擬主機
不管什麽域名解析到該服務器,都會訪問到默認虛擬主機
nginx.conf中第一個server { }
或 listen       80 default_server;
泛解析 *.aming.com  
Nginx虛擬主機配置規範
主配置文件include虛擬主機配置文件
在conf目錄下創建vhost目錄,在vhosts目錄下面定義虛擬主機配置
Nginx基於端口的虛擬主機
listen端口不同,server_name可以相同

Nginx的Rwrite配置

功能:域名跳轉(重定向)、URL重寫(偽靜態)、動靜分離(跳轉域名,並接入CDN實現加速)
依賴PCRE庫
模塊:ngx_http_rewrite_module

Rwrite相關指令
if (條件) { command }
coding.net/u/aminglinux/p/nginx/git/blob/master/rewrite/if.md

if指令

格式:if (條件判斷) { 具體的rewrite規則 }
條件舉例

條件判斷語句由Nginx內置變量、邏輯判斷符號和目標字符串三部分組成。
其中,內置變量是Nginx固定的非自定義的變量,如,$request_method, $request_uri等。
邏輯判斷符號,有=, !=, ~, ~, !~, !~
!表示相反的意思,~為匹配符號,它右側為正則表達式,區分大小寫,而~*為不區分大小寫匹配。
目標字符串可以是正則表達式,通常不用加引號,但表達式中有特殊符號時,比如空格、花括號、分號等,需要用單引號引起來。

示例1
if ($request_method = POST) //當請求的方法為POST時,直接返回405狀態碼
{
return 405; //在該示例中並未用到rewrite規則,if中支持用return指令。
}

示例2
if ($http_user_agent ~ MSIE) //user_agent帶有MSIE字符的請求,直接返回403狀態碼
{
return 403;
}

如果想同時限制多個user_agent,還可以寫成這樣

if ($http_user_agent ~ "MSIE|firefox|spider")
{
return 403;
}

示例3
if(!-f $request_filename) //當請求的文件不存在,將會執行下面的rewrite規則

{
rewrite 語句;
}

示例4
if($request_uri ~* ‘gid=\d{9,12}/‘) //\d表示數字,{9,12}表示數字出現的次數是9到12次,如gid=123456789/就是符合條件的。
{
rewrite 語句;
}

break和last

coding.net/u/aminglinux/p/nginx/git/blob/master/rewrite/break.md

rewrite中的break和last
兩個指令用法相同,但含義不同,需要放到rewrite規則的末尾,用來控制重寫後的鏈接是否繼續被nginx配置執行(主要是rewrite、return指令)。

示例1(連續兩條rewrite規則):
server{
listen 80;
server_name test.com;
root /tmp/123.com;

rewrite /1.html /2.html ;
rewrite /2.html /3.html ;

}
當我們請求1.html時,最終訪問到的是3.html,兩條rewrite規則先後執行。

break和last在location {}外部

格式:rewrite xxxxx break;

示例2(增加break):
server{
listen 80;
server_name test.com;
root /tmp/123.com;

rewrite /1.html /2.html break;
rewrite /2.html /3.html;

}
當我們請求1.html時,最終訪問到的是2.html
說明break在此示例中,作用是不再執行break以下的rewrite規則。

但,當配置文件中有location時,它還會去執行location{}段的配置(請求要匹配該location)。

示例3(break後面還有location段):
server{
listen 80;
server_name test.com;
root /tmp/123.com;

rewrite /1.html /2.html break;
rewrite /2.html /3.html;
location /2.html {
    return 403;
}

}
當請求1.html時,最終會返回403狀態碼,說明它去匹配了break後面的location{}配置。

以上2個示例中,可以把break替換為last,它們兩者起到的效果一模一樣。

當break和last在location{}裏面
示例4(什麽都不加):
server{
listen 80;
server_name test.com;
root /tmp/123.com;

location / {
    rewrite /1.html /2.html;
    rewrite /2.html /3.html;
}
location /2.html
{
    rewrite /2.html /a.html;
}
location /3.html
{
    rewrite /3.html /b.html;
}

}
當請求/1.html,最終將會訪問/b.html,連續執行location /下的兩次rewrite,跳轉到了/3.html,然後又匹配location /3.html

示例5(增加break):
server{
listen 80;
server_name test.com;
root /tmp/123.com;

location / {
    rewrite /1.html /2.html break;
    rewrite /2.html /3.html;
}
location /2.html
{
    rewrite /2.html /a.html;
}
location /3.html
{
    rewrite /3.html /b.html;
}

}
當請求/1.html,最終會訪問/2.html
在location{}內部,遇到break,本location{}內以及後面的所有location{}內的所有指令都不再執行。

示例6(增加last):
server{
listen 80;
server_name test.com;
root /tmp/123.com;

location / {
    rewrite /1.html /2.html last;
    rewrite /2.html /3.html;
}
location /2.html
{
    rewrite /2.html /a.html;
}
location /3.html
{
    rewrite /3.html /b.html;
}

}
當請求/1.html,最終會訪問/a.html
在location{}內部,遇到last,本location{}內後續指令不再執行,而重寫後的url再次從頭開始,從頭到尾匹配一遍規則。

結論
當rewrite規則在location{}外,break和last作用一樣,遇到break或last後,其後續的rewrite/return語句不再執行。但後續有location{}的話,還會近一步執行location{}裏面的語句,當然前提是請求必須要匹配該location。
當rewrite規則在location{}裏,遇到break後,本location{}與其他location{}的所有rewrite/return規則都不再執行。
當rewrite規則在location{}裏,遇到last後,本location{}裏後續rewrite/return規則不執行,但重寫後的url再次從頭開始執行所有規則,哪個匹配執行哪個。

return 後面跟狀態碼、URL、text(支持變量)

coding.net/u/aminglinux/p/nginx/git/blob/master/rewrite/return.md

nginx的return指令
該指令一般用於對請求的客戶端直接返回響應狀態碼。在該作用域內return後面的所有nginx配置都是無效的。
可以使用在server、location以及if配置中。

除了支持跟狀態碼,還可以跟字符串或者url鏈接。

直接返回狀態碼

示例1:
server{
listen 80;
server_name www.aming.com;
return 403;
rewrite /(.*) /abc/$1; //該行配置不會被執行。
}

示例2:
server {
.....

if ($request_uri ~ ".htpasswd|.bak")
{
return 404;
rewrite /(.*) /aaa.txt; //該行配置不會被執行。
}
//如果下面還有其他配置,會被執行。
.....
}

返回字符串
示例3:
server{
listen 80;
server_name www.aming.com;
return 200 "hello";
}
說明:如果要想返回字符串,必須要加上狀態碼,否則會報錯。
還可以支持json數據

示例4:
location ^~ /aming {
default_type application/json ;
return 200 ‘{"name":"aming","id":"100"}‘;
}

也支持寫一個變量

示例5:
location /test {
return 200 "$host $request_uri";
}

返回url
示例6:
server{
listen 80;
server_name www.aming.com;
return http://www.aminglinux.com/123.html;
rewrite /(.*) /abc/$1; //該行配置不會被執行。
}
註意:return後面的url必須是以http://或者https://開頭的。

生成場景實戰
背景:網站被黑了,凡是在百度點擊到本網站的請求,全部都跳轉到了一個×××。
臨時解決通過nginx解決:
if ($http_referer ~ ‘baidu.com‘)
{
return 200 "<html><script>window.location.href=‘//$host$request_uri‘;</script></html>";
}

如果寫成:
return http://$host$request_uri; 在瀏覽器中會提示“重定向的次數過多”。

rewrite規則

coding.net/u/aminglinux/p/nginx/git/blob/master/rewrite/rewrite_ruler.md

格式:rewrite regex replacement [flag]

  • rewrite配置可以在server、location以及if配置段內生效

  • regex是用於匹配URI的正則表達式,其不會匹配到$host(域名)

  • replacement是目標跳轉的URI,可以以http://或者https://開頭,也可以省略掉$host,直接寫$request_uri部分(即請求的鏈接)

  • flag,用來設置rewrite對URI的處理行為,其中有break、last、rediect、permanent,其中break和last在前面已經介紹過,
    rediect和permanent的區別在於,前者為臨時重定向(302),而後者是永久重定向(301),對於用戶通過瀏覽器訪問,這兩者的效果是一致的。
    但是,對於搜索引擎蜘蛛爬蟲來說就有區別了,使用301更有利於SEO。所以,建議replacemnet是以http://或者https://開頭的flag使用permanent。

示例1
location / {
rewrite /(.) http://www.aming.com/$1 permanent;
}
說明:.
為正則表達式,用()括起來,在後面的URI中可以調用它,第一次出現的()用$1調用,第二次出現的()用$2調用,以此類推。

示例2
location / {
rewrite /.* http://www.aming.com$request_uri permanent;
}
說明:在replacement中,支持變量,這裏的$request_uri就是客戶端請求的鏈接

示例3
server{
listen 80;
server_name www.123.com;
root /tmp/123.com;
index index.html;
rewrite /(.*) /abc/$1 redirect;
}
說明:本例中的rewrite規則有問題,會造連續循環,最終會失敗,解決該問題有兩個方案。
關於循環次數,經測試發現,curl 會循環50次,chrome會循環80次,IE會循環120次,firefox會循環20次。

示例4
server{
listen 80;
server_name www.123.com;
root /tmp/123.com;
index index.html;
rewrite /(.*) /abc/$1 break;
}
說明:在rewrite中使用break,會避免循環。

示例5

server{
listen 80;
server_name www.123.com;
root /tmp/123.com;
index index.html;
if ($request_uri !~ ‘^/abc/‘)
{
rewrite /(.*) /abc/$1 redirect;
}
}
說明:加一個條件限制,也可以避免產生循環

rewrite_log定義rewrite日誌 rewrite_log on; 寫到error_log notice級別

Rwrite相關全局變量

coding.net/u/aminglinux/p/nginx/git/blob/master/rewrite/variable.md

nginx 常用全局變量

變量                                                              說明
$args                                            請求中的參數,如www.123.com/1.php?a=1&b=2的$args就是a=1&b=2
$content_length                          HTTP請求信息裏的”Content-Length”
$conten_type                                HTTP請求信息裏的”Content-Type”
$document_root                         nginx虛擬主機配置文件中的root參數對應的值
$document_uri                             當前請求中不包含指令的URI,如www.123.com/1.php?a=1&b=2的$document_uri就是1.php,不包含後面的參數
$host                                            主機頭,也就是域名
$http_user_agent                        客戶端的詳細信息,也就是瀏覽器的標識,用curl -A可以指定
$http_cookie                                客戶端的cookie信息
$limit_rate                                  如果nginx服務器使用limit_rate配置了顯示網絡速率,則會顯示,如果沒有設置, 則顯示0
$remote_addr                              客戶端的公網ip
$remote_port                               客戶端的port
$remote_user                              如果nginx有配置認證,該變量代表客戶端認證的用戶名
$request_body_file                       做反向代理時發給後端服務器的本地資源的名稱
$request_method                        請求資源的方式,GET/PUT/DELETE等
$request_filename                       當前請求的資源文件的路徑名稱,相當於是$document_root/$document_uri的組合
$request_uri                                請求的鏈接,包括$document_uri和$args
$scheme                                  請求的協議,如ftp,http,https
$server_protocol                        客戶端請求資源使用的協議的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0等
$server_addr                            服務器IP地址
$server_name                         服務器的主機名
$server_port                            服務器的端口號
$uri    和$document_uri          相同
$http_referer                          客戶端請求時的referer,通俗講就是該請求是通過哪個鏈接跳過來的,用curl -e可以指定

Rwrite實戰

coding.net/u/aminglinux/p/nginx/git/blob/master/rewrite/example.md

域名跳轉(域名重定向)
示例1(不帶條件的):
server{
listen 80;
server_name www.aminglinux.com;
rewrite /(.*) http://www.aming.com/$1 permanent;
.......

}

示例2(帶條件的):
server{
listen 80;
server_name www.aminglinux.com aminglinux.com;
if ($host != ‘www.aminglinux.com‘)
{
rewrite /(.*) http://www.aminglinux.com/$1 permanent;
}
.......

}
示例3(http跳轉到https):
server{
listen 80;
server_name www.aminglinux.com;
rewrite /(.*) https://www.aminglinux.com/$1 permanent;
.......

}
示例4(域名訪問二級目錄)
server{
listen 80;
server_name bbs.aminglinux.com;
rewrite /(.*) http://www.aminglinux.com/bbs/$1 last;
.......

}
示例5(靜態請求分離)
server{
listen 80;
server_name www.aminglinux.com;
location ~ ^.+.(jpg|jpeg|gif|css|png|js)$
{
rewrite /(.
) http://img.aminglinux.com/$1 permanent;
}

.......

}
或者:
server{
listen 80;
server_name www.aminglinux.com;
if ( $uri ~ ‘jpg|jpeg|gif|css|png|js$‘)
{
rewrite /(.
) http://img.aminglinux.com/$1 permanent;
}

.......

}

防盜鏈

示例6
server{
listen 80;
server_name www.aminglinux.com;
location ~ ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$
{
valid_referers none blocked server_names
.aminglinux.com aminglinux.com .aming.com aming.com;
if ($invalid_referer)
{
rewrite /(.
) http://img.aminglinux.com/images/forbidden.png;
}
}

.......

}
說明:這裏是通配,跟正則裏面的不是一個意思,none指的是referer不存在的情況(curl -e 測試),
blocked指的是referer頭部的值被防火墻或者代理服務器刪除或者偽裝的情況,
該情況下,referer頭部的值不以http://或者https://開頭(curl -e 後面跟的referer不以http://或者https://開頭)。
valid_referers none 就是refer為空
blocked: 若是加上這個,表示可以使用http訪問,若不加這個blocked,則用http訪問,就會返回403
後面是白名單域名可以訪問
if 如果不在以上的白名單裏的域名,就返回403

或者:
location ~ ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$
{
valid_referers none blocked server_names
.aminglinux.com *.aming.com aminglinux.com aming.com;
if ($invalid_referer)
{
return 403;
}
}

偽靜態
示例7(discuz偽靜態):
第一個()表示的就是$1,第二個就是$2
location / {
rewrite ^([^.])/topic-(.+).html$ $1/portal.php?mod=topic&topic=$2 last;
rewrite ^([^.]
)/forum-(\w+)-([0-9]+).html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last;
rewrite ^([^.])/thread-([0-9]+)-([0-9]+)-([0-9]+).html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last;
rewrite ^([^.]
)/group-([0-9]+)-([0-9]+).html$ $1/forum.php?mod=group&fid=$2&page=$3 last;
rewrite ^([^.])/space-(username|uid)-(.+).html$ $1/home.php?mod=space&$2=$3 last;
rewrite ^([^.]
)/(fid|tid)-([0-9]+).html$ $1/index.php?action=$2&value=$3 last;
}

rewrite多個條件的並且
示例8:
location /{
set $rule 0;
if ($document_uri !~ ‘^/abc‘)
{
set $rule "${rule}1";
}
if ($http_user_agent ~ ‘ie6|firefox‘)
{
set $rule "${rule}2";
}
if ($rule = "012")
{
rewrite /(.
) /abc/$1 redirect;
}
}

Nginx虛擬主機配置、Nginx的Rwrite配置