關於反向代理
Nginx能夠作爲一個反向代理來終結來自客戶端的請求,並且向上遊服務器打開一個新連接。新連接代表客戶端向上遊服務器發送請求。代理到上游服務器的配置中,最重要的是proxy_pass指令。該指令有一個參數,URL請求將會被轉換,帶有URI部分的proxy_pass指令將會使用該URI代替客戶端request_uri部分。
location /uri { proxy_pass http://localhost:8080/newuri; }
實例:
[root@master vhost]# cat proxy.conf server { listen 80; server_name localhost.myserver.com; access_log /usr/local/nginx/logs/proxy_access.log normal; location /test { proxy_pass http://localhost:8080/index; } } [root@master vhost]# cat localhost_myserver_com.conf server { listen 8080; server_name localhost.myserver.com; access_log /usr/local/nginx/logs/localhost_access.log normal; location / { root /usr/local/nginx/html; } }
此時,在localhost_access.log中記錄的請求發生了改變:
[root@master logs]# tail -1 proxy_access.log 192.168.1.38 - - 2019-03-28T04:02:58-04:00 "GET http://localhost.myserver.com/test.html HTTP/1.1"200 249 393 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36""-" 0.001 0.001 [root@master logs]# [root@master logs]# tail -1 localhost_access.log 127.0.0.1 - - 2019-03-28T04:02:58-04:00 "GET http://localhost.myserver.com/index.html HTTP/1.0"200 205 414 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36""-" 0.001 -
這個規則有兩個例外情況:
如果location定義了一個正則表達式,或者在location中有rewrite規則改變了URI時,在proxy_pass指定URI部分是不被允許的。
向上遊服務器傳遞客戶端真實IP
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://192.168.1.202:8080; }
upstream模塊
upstream模塊經常與proxy搭配使用。upstream模塊啓用新的配置區段,定義了一組上游服務器。這些服務器可能被設置了不同的權重(權重越高的服務器將被Nginx分配更多的連接),也可能是不同的類型(TCP或UNIX域),也可能出於對服務器的維護而標記爲down。
使用指定的負載均衡算法:
Nginx默認會採用輪詢算法,如果想切換爲ip_hash或least_conn,只需要在upstream開始位置指定負載均衡算法
upstream nginxservers { least_conn; server 192.168.1.201:8080; server 192.168.1.202:8080; keepalive 32; }
向上遊服務器保持活動連接:
Nginx服務器將會爲每一個worker進程保持同上遊服務器的連接。在Nginx需要同上遊服務器持續保持一定數量的打開連接時,連接緩存非常有用。Nginx將會使用HTTP/1.1協議的持久連接機制維護這些打開的連接。
在下面的例子中,Nginx起初僅需要爲每一個worker進程打開32個TCP連接,然後通過不發送close的Connection頭保持這些連接。
使用proxy_http_version指定使用HTTP/1.1協議同上遊服務器進行通信。
使用proxy_set_header指令清除了Connection頭的內容。
在業務高峯期,Nginx會打開超過32個TCP連接,當高峯期結束,Nginx將關閉最近最少使用的連接,使連接數回落到32。
upstream nginxservers { server 192.168.1.201:8080; server 192.168.1.202:8080; keepalive 32; } server { listen 80; server_name localhost.myserver.com; access_log /usr/local/nginx/logs/proxy_access.log normal; location / { proxy_http_version 1.1; proxy_set_header Connection ""; proxy_pass http://nginxservers; } }
使用Memcached作爲上游服務器:
upstream memcaches { server 192.168.1.201:11211; server 192.168.1.202:11211; } server { location / { set $memcached_key "$uri?$args"; memcached_pass memcaches; error_page 404 = @appserver; } location @appserver { proxy_pass http://127.0.0.1:8080; } }
使用FastCGI作爲上游服務器:
upstream fastcgis { server 192.168.1.201:9000; server 192.168.1.202:9000; } server { location / { fastcgi_pass fastcgis; } }
Nginx通過uwsgi模塊提供基於Python的上游服務器的連接,配置類似於FastCGI模塊,使用uwsgi_pass指令指定上游服務器。
使用錯誤文件處理上游服務器問題
有一些上游服務器無法響應請求的情況,此時,可以讓Nginx從本地返回一個文件。
server { listen 80; server_name localhost.myserver.com; access_log /usr/local/nginx/logs/proxy_access.log normal; location / { proxy_pass http://nginxservers; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/local/nginx/html; } } }
或者在上游服務器無法響應請求時,想將請求轉發至另一組定義好的後備服務器(fallback)。
server { listen 80; server_name localhost.myserver.com; access_log /usr/local/nginx/logs/proxy_access.log normal; location / { proxy_pass http://nginxservers; error_page 500 502 503 504 = @fallback; } location @fallback { proxy_pass http://localhost:8080; } }
使用SSL對流量進行加密:
使用OpenSSL生成SSL證書:
# openssl req -newkey rsa:2048 -nodes -out localhost.myserver.com -keyout localhost.myserver.com.key ---- 命令執行時提示輸入公司名、郵件等信息,直接回車即可; ---- 完成以上命令會得到證書籤名請求(Certificate Signing Requests),保存在“localhost.myserver.com”文件中; ---- 證書籤名由證書頒發機構授予。或者也可以自己簽名,自己的簽名不能用在公網服務器上 # openssl x509 -req -days 365 -in localhost.myserver.com -signkey localhost.myserver.com.key -out localhost.myserver.com.pem Signature ok subject=/C=XX/L=Default City/O=Default Company Ltd Getting Private key
對客戶端和反向代理之間的流量進行加密:
server { listen 443 default ssl; server_name localhost.myserver.com; ssl_prefer_server_ciphers on; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers AESGCM:ALL:!DH:!EXPORT:!RC4:+HIGH:!MEDIUM:!LOW:!aNULL:!eNULL; ssl_session_timeout 5m; ssl_session_cache shared:WEB:10m; ssl_certificate /usr/local/nginx/ssl_key/localhost.myserver.com.pem; ssl_certificate_key /usr/local/nginx/ssl_key/localhost.myserver.com.key; location / { access_log /usr/local/nginx/logs/ssl.log normal; proxy_set_header X-Forwarded-For-Proto $scheme; proxy_pass http://127.0.0.1:8080; } }
首先使用listen指令的ssl參數激活了SSL模塊。
然後指定了希望客戶端使用服務器密碼,以及協議類型和使用的認證方法;
ssl_session_cache指令被設定爲shared,第二部分和第三部分分別是緩存的名稱和大小;
然後指明證書和key的路徑,要保證文件能被Nginx使用的用戶訪問。
最後設置X-Forwarded-For-Proto頭的值爲$scheme,告訴上游服務器原始請求使用的是http還是https。
對反向代理和上游服務器之間的流量進行加密:
server { …… location / { …… proxy_pass https://127.0.0.1:8080; } }
要保證上游服務器也啓用了SSL模塊,這裏的上游服務器使用Nginx提供服務,設置方法同“對客戶端和反向代理之間的流量進行加密”。