Nginx常見場景代理轉發配置
注意:本文出自 “阿飛”的部落格 ,如果要轉載本文章,請與作者聯絡!
在這裡分享的不是nginx的配置檔案說明,而是nginx常用的轉發代理配置(比如線上多域名配置,後端各種轉發代理配置以及較為複雜的代理轉發配置),另外還會對常用的轉發代理引數配置進行說明。
nginx配置檔案說明請參考:
1)http://www.cnblogs.com/hunttown/p/5759959.html
2)http://www.jianshu.com/p/1b44b5142155
一、代理轉發
nginx的代理轉發主要是在server部分進行配置。如果轉向到制定域名或子域名,則需要在godaddy、阿里雲等域名解析中預先配置(子)域名並指定IP。本文中主要描述萬用字元域名的配置,這樣更具有通用性。
server部分配置為:
server {
listen 80;
server_name *.yourdomain.com;
......
如果是https則修改listen部分即可:
listen 443 ssl;
* https配置還需要單獨配置ssl部分的內容,證書不一樣,配置方式也有差異,這裡不做介紹。
一般情況下,我們會有如下常見的幾種需求:
1)指向到公司官網或其他產品網(一級域名)
每個域名單獨配置一個server即可,如HTTPS的配置如下:
server { listen 443 ssl; server_name www.yourdomain.com; #修改為需要的一級域名即可 access_log logs/ssl.access.log; error_log logs/ssl.error.log crit; include ssl_params; location / { index index.html index.htm index.php; index proxy_set_header Host $host; index proxy_set_header X-Real-IP $remote_addr; index proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://server_cluster; #後端伺服器,具體配置upstream部分即可 } }
2)指向到公司內部管理系統等等(二級域名)
同1)部分的配置,只需要修改server_name部分即可:
server_name 二級域名.yourdomain.com; #修改為需要的二級域名即可
3)二級域名下多個服務轉發
比如:
http://dev.yourdomain.com/nexus
http://dev.yourdomain.com/zentao
http://dev.yourdomain.com/adminsys
...
而後端服務可能會部署在不同的server容器中,比如tomcat、php-fpm/fastcgi、第三方服務...
server部分需要先配置第2)點部分內容
a)轉發到後端Tomcat
location /location名稱/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:8080/服務名/;
}
tomcat的轉發是很簡單的了,這裡不需要多說。
b)轉發到php-fpm
將所有php頁面的請求轉給php-fpm處理:
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
fastcgi_params配置:
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
#fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param SERVER_SOFTWARE nginx;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
注意!
配置不具備通用性,需要根據自己伺服器及實際業務需要進行配置和調整。
這裡的配置僅提供參考。
d)轉發到第三方域名(第三方介面服務)
比如做支付時,內部系統需要通過代理轉發到銀聯支付介面:
location /unionpay/ {
proxy_set_header Host gateway.銀聯.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass https://gateway.銀聯.com/;
}
這裡的proxy_set_header Host必須配置。
4)強制http轉https訪問
80埠部分server配置:
server {
listen 80;
server_name api.yourdomain.com;
location / {
rewrite ^/(.*) https://api.yourdomain.com/$1 permanent ;
break;
}
error_page 497 https://$host:$server_port$request_uri;
}
當用戶通過HTTP 80訪問時,nginx將強制轉換為HTTPS 443訪問。
443埠部分server配置:
server {
listen 443 ssl;
server_name api.yourdomain.com;
access_log logs/ssl.api_access.log;
error_log logs/ssl.api_error.log crit;
include ssl_params;
location / {
proxy_pass http://tomcat_servers/$2;
proxy_set_header Host $host:443;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location /v1.0/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://tomcat_servers/v1.0/;
proxy_cookie_path /v1.0/ /;
proxy_redirect off;
}
}
5)字尾名定向
比如,有URL:www.abc.com/register/user.do,需要將URL定向為uuu.abc.com/register/user.do。則可以在WWW.ABC.COM節點中這樣配置:
location / {
rewrite ^(/register)/user(.*)\..*$ https://uuu.abc.com/register/user.do break;
index index.html index.htm;
proxy_set_header Host $host:443;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://localhost:****/;
}
6)在location中通過if-else分支,根據請求引數使用不同的proxy_pass進行轉發。如:
例如url為:http://mail.yourdomain.com/abc/1?n=web01&p=8088,這裡有n和p兩個引數。這裡的目的很簡單,就是想通過n這個引數來轉發到後端不同伺服器的Tomcat中,比如web01轉發到192.168.2.10,web02轉發到192.168.2.11....這種需求,我們不可能為後端每個伺服器配置一個location轉發。
因此,Nginx中可以對location進行if判斷,解決方案如下:
location /test/ {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
if ($arg_n ~* "web01") {
proxy_pass http://192.168.2.10:$arg_p;
break;
}
if ($arg_n ~* "web02") {
proxy_pass http://192.168.2.11:$arg_p;
break;
}
.......
}
其中,$arg_n表示url中的n引數,$arg_p表示url中的p引數。
最後,尤其要注意的是!proxy_pass 後的url不能有與請求的url後的路徑,如proxy_pass http://192.168.2.10:$arg_p;這裡不能配置為:proxy_pass http://192.168.2.10:$arg_p/abc/1...否則要報錯。必須只配置到埠,並且沒有斜槓/結尾。切記切記。
7)Nginx支援websocket的配置
只需要加上紅色字型部分配置即可:
location /drsws/ {
proxy_set_header Host $host;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
........
}
8)支援ttf|woff|woff2字型及圖片檔案防盜鏈的配置
location ~* \.(css|js|jpg|jpeg|png|gif|ico|ttf|woff|woff2|eot|svg)$ {
root /usr/share/nginx/html/phpems;
expires 30d;
valid_referers *.yourdomain.com www.yourdomain.com dev.yourdomain.com *.baidu.com *.google.com;
if ($invalid_referer) {
rewrite ^/ https://www.yourdomain.com;
#return 404;
}
}
二、引數說明
1)proxy_set_header X-real-ip $remote_addr;
在web伺服器端獲得使用者的真實ip。
但是,實際上要獲得使用者的真實ip,不是隻有這一個方法,下面我們繼續看。
2)proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
我們先看看這裡有個X-Forwarded-For變數,這是一個squid開發的,用於識別通過HTTP代理或負載平衡器原始IP一個連線到Web伺服器的客戶機地址的非rfc標準,如果有做X-Forwarded-For設定的話,每次經過proxy轉發都會有記錄,格式就是client1, proxy1, proxy2,以逗號隔開各個地址,由於他是非rfc標準,所以預設是沒有的,需要強制新增,在預設情況下經過proxy轉發的請求,在後端看來遠端地址都是proxy端的ip 。也就是說在預設情況下我們使用request.getAttribute("X-Forwarded-For")獲取不到使用者的ip,如果我們想要通過這個變數獲得使用者的ip,我們需要自己在nginx新增如下配置:
proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;
意思是增加一個$proxy_add_x_forwarded_for到X-Forwarded-For裡去,注意是增加,而不是覆蓋,當然由於預設的X-Forwarded-For值是空的,所以我們總感覺X-Forwarded-For的值就等於$proxy_add_x_forwarded_for的值,實際上當你搭建兩臺nginx在不同的ip上,並且都使用了這段配置,那你會發現在web伺服器端通過request.getAttribute("X-Forwarded-For")獲得的將會是客戶端ip和第一臺nginx的ip。
那麼$proxy_add_x_forwarded_for又是什麼?
$proxy_add_x_forwarded_for變數包含客戶端請求頭中的"X-Forwarded-For",與$remote_addr兩部分,他們之間用逗號分開。
舉個例子,有一個web應用,在它之前通過了兩個nginx轉發,www.linuxidc.com 即使用者訪問該web通過兩臺nginx。
在第一臺nginx中,使用
proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;
現在的$proxy_add_x_forwarded_for變數的"X-Forwarded-For"部分是空的,所以只有$remote_addr,而$remote_addr的值是使用者的ip,於是賦值以後,X-Forwarded-For變數的值就是使用者的真實的ip地址了。
到了第二臺nginx,使用
proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;
現在的$proxy_add_x_forwarded_for變數,X-Forwarded-For部分包含的是使用者的真實ip,$remote_addr部分的值是上一臺nginx的ip地址,於是通過這個賦值以後現在的X-Forwarded-For的值就變成了“使用者的真實ip,第一臺nginx的ip”,這樣就清楚了吧。
最後我們看到還有一個$http_x_forwarded_for變數,這個變數就是X-Forwarded-For,由於之前我們說了,預設的這個X-Forwarded-For是為空的,所以當我們直接使用proxy_set_header X-Forwarded-For$http_x_forwarded_for時會發現,web伺服器端使用request.getAttribute("X-Forwarded-For")獲得的值是null。如果想要通過request.getAttribute("X-Forwarded-For")獲得使用者ip,就必須先使用proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;這樣就可以獲得使用者真實ip。
此部分內容來自:http://blog.csdn.net/bao19901210/article/details/52537279(感謝作者分享)
三、小結
1)通過本文,應該比較清楚的描述了一級、二級域名的配置;
2)通過各種場景,應該描述清楚了location各種情況的轉發配置;
3)引用其他文章,講解了部分引數的含義
4)各種複雜的情況,還需要根據具體的業務及需求進行配置,這裡的例子相對都比較簡單。