6.1 Nginx 反向代理概述
Nginx即可以實現正向代理,也可以實現反向代理。我們先來通過一個小案例演示下Nginx正向代理的簡單應用。
先提需求:
(1)服務端的設置:
http {
log_format main 'client send request=>clientIp=$remote_addr serverIp=>$host';
server{
listen 80;
server_name localhost;
access_log logs/access.log main;
location {
root html;
index index.html index.htm;
}
}
}
(2)使用客戶端訪問服務端,打開日志查看結果
(3)代理服務器設置:
server {
listen 82;
resolver 8.8.8.8;
location /{
proxy_pass http://$host$request_uri;
}
}
(4)在客戶端配置代理服務器
(6)設置完成后,再次通過瀏覽器訪問服務端
通過對比,上下兩次的日志記錄,會發現雖然我們是客戶端訪問服務端,但是如何使用了代理,那么服務端能看到的只是代理發送過去的請求,這樣的化,就使用Nginx實現了正向代理的設置。
但是Nginx正向代理,在實際的應用中不是特別多,所以我們簡單了解下,接下來我們繼續學習Nginx的反向代理,這是Nginx比較重要的一個功能。
6.2 Nginx 反向代理的配置語法
Nginx反向代理模塊的指令是由ngx_http_proxy_module
模塊進行解析,該模塊在安裝Nginx的時候已經自己加裝到Nginx中了,接下來我們把反向代理中的常用指令一一介紹下:
proxy_pass
proxy_set_header
proxy_redirect
6.2.1 proxy_pass
該指令用來設置被代理服務器地址,可以是主機名稱、IP地址加端口號形式。
語法 | proxy_pass URL; |
---|---|
默認值 | — |
位置 | location |
URL:為要設置的被代理服務器地址,包含傳輸協議(http
,https://
)、主機名稱或IP地址加端口號、URI等要素。
舉例:
proxy_pass http://www.baidu.com;
location /server{}
proxy_pass http://192.168.5.4;
http://192.168.200.146/server/index.html
proxy_pass http://192.168.5.4/;
http://192.168.5.4/index.html
大家在編寫proxy_pass的時候,后面的值要不要加"/"?
接下來通過例子來說明剛才我們提到的問題:
server {
listen 80;
server_name localhost;
location /{
# proxy_pass http://192.168.5.4:82;
proxy_pass http://192.168.5.4:82/;
}
}
# 當客戶端訪問 http://localhost/index.html,效果是一樣的
server{
listen 80;
server_name localhost;
location /server{
# proxy_pass http://192.168.5.4:82;
proxy_pass http://192.168.5.4:82/;
}
}
# 當客戶端訪問 http://localhost/server/index.html
# 這個時候,第一個proxy_pass就變成了http://localhost/server/index.html
# 第二個proxy_pass就變成了http://localhost/index.html效果就不一樣了。
6.2.2 proxy_set_header
該指令可以更改Nginx服務器接收到的客戶端請求的請求頭信息,然后將新的請求頭發送給代理的服務器
語法 | proxy_set_header field value; |
---|---|
默認值 | proxy_set_header Host $proxy_host; proxy_set_header Connection close; |
位置 | http、server、location |
需要注意的是,如果想要看到結果,必須在被代理的服務器上來獲取添加的頭信息。
被代理服務器: [192.168.5.4:82]
server {
listen 82;
server_name localhost;
default_type text/plain;
return 200 $http_username;
}
代理服務器: [192.168.5.3]
server {
listen 80;
server_name localhost;
location /server {
proxy_pass http://192.168.5.4:82/;
proxy_set_header username TOM;
}
}
訪問測試
6.2.3 proxy_redirect
該指令是用來重置頭信息中的"Location"和"Refresh"的值。
語法 | proxy_redirect redirect replacement; proxy_redirect default; proxy_redirect off; |
---|---|
默認值 | proxy_redirect default; |
位置 | http、server、location |
(1)為什么要用該指令?
服務端[192.168.5.4:8080]
server {
listen 82;
server_name localhost;
if (!-f $request_filename){
return 302 http://192.168.5.4:80;
}
}
代理服務端[192.168.5.3]
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://192.168.5.4:8080/;
proxy_redirect http://192.168.5.4:8080 http://192.168.5.3;
}
}
(2)該指令的幾組選項
proxy_redirect redirect replacement;
redirect:目標,Location的值
replacement:要替換的值
proxy_redirect default;
default;
將location塊的uri變量作為replacement,
將proxy_pass變量作為redirect進行替換
proxy_redirect off;
關閉proxy_redirect的功能
6.3 Nginx 反向代理實戰
服務器1,2,3存在兩種情況
-
第一種情況: 三台服務器的內容不一樣。
-
第二種情況: 三台服務器的內容是一樣。
(1)如果服務器1、服務器2和服務器3的內容不一樣,那我們可以根據用戶請求來分發到不同的服務器。
代理服務器
server {
listen 8082;
server_name localhost;
location /server1 {
proxy_pass http://192.168.5.4:9001/;
}
location /server2 {
proxy_pass http://192.168.5.4:9002/;
}
location /server3 {
proxy_pass http://192.168.5.4:9003/;
}
}
服務端
server1
server {
listen 9001;
server_name localhost;
default_type text/html;
return 200 '<h1>192.168.5.4:9001</h1>'
}
server2
server {
listen 9002;
server_name localhost;
default_type text/html;
return 200 '<h1>192.168.5.4:9002</h1>'
}
server3
server {
listen 9003;
server_name localhost;
default_type text/html;
return 200 '<h1>192.168.5.4:9003</h1>'
}
(2)如果服務器1、服務器2和服務器3的內容是一樣的,該如何處理?
可以采用輔助均衡的方式
6.4 Nginx 的安全控制
關於web服務器的安全是比較大的一個話題,里面所涉及的內容很多,Nginx反向代理是如何來提升web服務器的安全呢?
安全隔離
什么是安全隔離?
通過代理分開了客戶端到應用程序服務器端的連接,實現了安全措施。在反向代理之前設置防火牆,僅留一個入口供代理服務器訪問。
6.5 如何使用SSL對流量進行加密
翻譯成大家能熟悉的說法就是將我們常用的http請求轉變成https請求,那么這兩個之間的區別簡單的來說兩個都是HTTP協議,只不過https是身披SSL外殼的http.
HTTPS是一種通過計算機網絡進行安全通信的傳輸協議。它經由HTTP進行通信,利用SSL/TLS建立全通信,加密數據包,確保數據的安全性。
-
SSL(Secure Sockets Layer)安全套接層
-
TLS(Transport Layer Security)傳輸層安全
上述這兩個是為網絡通信提供安全及數據完整性的一種安全協議,TLS和SSL在傳輸層和應用層對網絡連接進行加密。
http協議是明文傳輸數據,存在安全問題,而https是加密傳輸,相當於http+ssl,並且可以防止流量劫持。
Nginx要想使用SSL,需要滿足一個條件即需要添加一個模塊--with-http_ssl_module
,而該模塊在編譯的過程中又需要OpenSSL的支持,這個我們之前已經准備好了。
6.5.1 nginx添加SSL的支持
完成 --with-http_ssl_module
模塊的增量添加
-
將原有/usr/local/nginx/sbin/nginx進行備份
-
拷貝nginx之前的配置信息
-
在nginx的安裝源碼進行配置指定對應模塊 ./configure --with-http_ssl_module
-
通過make模板進行編譯
-
將objs下面的nginx移動到/usr/local/nginx/sbin下
-
在源碼目錄下執行 make upgrade進行升級,這個可以實現不停機添加新模塊的功能
6.5.2 Nginx的SSL相關指令
因為剛才我們介紹過該模塊的指令都是通過ngx_http_ssl_module模塊來解析的。
1)ssl:該指令用來在指定的服務器開啟HTTPS,可以使用 listen 443 ssl,后面這種方式更通用些。
語法 | ssl on | off; |
---|---|
默認值 | ssl off; |
位置 | http、server |
server{
listen 443 ssl;
}
2)ssl_certificate:為當前這個虛擬主機指定一個帶有PEM格式證書的證書。
語法 | ssl_certificate file; |
---|---|
默認值 | — |
位置 | http、server |
3)ssl_certificate_key:該指令用來指定PEM secret key文件的路徑
語法 | ssl_ceritificate_key file; |
---|---|
默認值 | — |
位置 | http、server |
4)ssl_session_cache:該指令用來配置用於SSL會話的緩存
語法 | ssl_sesion_cache off|none|[builtin[:size]] [shared:name:size] |
---|---|
默認值 | ssl_session_cache none; |
位置 | http、server |
-
off:禁用會話緩存,客戶端不得重復使用會話
-
none:禁止使用會話緩存,客戶端可以重復使用,但是並沒有在緩存中存儲會話參數
-
builtin:內置OpenSSL緩存,僅在一個工作進程中使用。
-
shared:所有工作進程之間共享緩存,緩存的相關信息用name和size來指定
5)ssl_session_timeout:開啟SSL會話功能后,設置客戶端能夠反復使用儲存在緩存中的會話參數時間。
語法 | ssl_session_timeout time; |
---|---|
默認值 | ssl_session_timeout 5m; |
位置 | http、server |
6)ssl_ciphers:指出允許的密碼,密碼指定為OpenSSL支持的格式
語法 | ssl_ciphers ciphers; |
---|---|
默認值 | ssl_ciphers HIGH:!aNULL:!MD5; |
位置 | http、server |
可以使用openssl ciphers
查看openssl支持的格式。
7)ssl_prefer_server_ciphers:該指令指定是否服務器密碼優先客戶端密碼
語法 | ssl_perfer_server_ciphers on|off; |
---|---|
默認值 | ssl_perfer_server_ciphers off; |
位置 | http、server |
6.5.3 生成證書
方式一:使用阿里雲/騰訊雲等第三方服務進行購買。
方式二:使用自定義證書
先要確認當前系統是否有安裝openssl
openssl version
安裝下面的命令進行生成
mkdir /root/cert && cd /root/cert
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
6.5.4 開啟SSL實例
server {
listen 443 ssl;
server_name localhost;
ssl_certificate server.cert;
ssl_certificate_key server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
6.5.5 驗證
因為證書使我們自己生成了,並沒有經過第三方的驗證,所以出現不安全是正常的,但是可以看到證書信息
6.5.6 開啟http自動跳轉https
server {
listen 80;
#填寫綁定證書的域名
server_name localhost;
#把http的域名請求轉成https
return 301 https://$host$request_uri;
}
6.6 反向代理系統調優
反向代理值Buffer和Cache
Buffer翻譯過來是"緩沖",Cache翻譯過來是"緩存"。
總結下:
相同點:
兩種方式都是用來提供IO吞吐效率,都是用來提升Nginx代理的性能。
不同點:
緩沖主要用來解決不同設備之間數據傳遞速度不一致導致的性能低的問題,緩沖中的數據一旦此次操作完成后,就可以刪除。
緩存主要是備份,將被代理服務器的數據緩存一份到代理服務器,這樣的話,客戶端再次獲取相同數據的時候,就只需要從代理服務器上獲取,效率較高,緩存中的數據可以重復使用,只有滿足特定條件才會刪除.
(1)Proxy Buffer相關指令
1)proxy_buffering :該指令用來開啟或者關閉代理服務器的緩沖區;
語法 | proxy_buffering on|off; |
---|---|
默認值 | proxy_buffering on; |
位置 | http、server、location |
2)proxy_buffers:該指令用來指定單個連接從代理服務器讀取響應的緩存區的個數和大小。
語法 | proxy_buffers number size; |
---|---|
默認值 | proxy_buffers 8 4k | 8K;(與系統平台有關) |
位置 | http、server、location |
number:緩沖區的個數
size:每個緩沖區的大小,緩沖區的總大小就是number*size
3)proxy_buffer_size:該指令用來設置從被代理服務器獲取的第一部分響應數據的大小。保持與proxy_buffers中的size一致即可,當然也可以更小。
語法 | proxy_buffer_size size; |
---|---|
默認值 | proxy_buffer_size 4k | 8k;(與系統平台有關) |
位置 | http、server、location |
4)proxy_busy_buffers_size:該指令用來限制同時處於BUSY狀態的緩沖總大小。
語法 | proxy_busy_buffers_size size; |
---|---|
默認值 | proxy_busy_buffers_size 8k|16K; |
位置 | http、server、location |
5)proxy_temp_path:當緩沖區存滿后,仍未被Nginx服務器完全接受,響應數據就會被臨時存放在磁盤文件上,該指令設置文件路徑
語法 | proxy_temp_path path; |
---|---|
默認值 | proxy_temp_path proxy_temp; |
位置 | http、server、location |
注意path最多設置三層。
6)proxy_temp_file_write_size:該指令用來設置磁盤上緩沖文件的大小。
語法 | proxy_temp_file_write_size size; |
---|---|
默認值 | proxy_temp_file_write_size 8K|16K; |
位置 | http、server、location |
通用網站的配置
proxy_buffering on;
proxy_buffer_size 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;