博客 / 詳情

返回

Nginx如何反向代理、延時響應、SLL

昨日之深淵,今日之淺談。路雖遠,行則將至。事雖難,做則可成。

在前端生態中,代理服務扮演着重要的角色。代理服務是指一種中間層服務,用於在前端應用程序和後端服務器之間進行請求轉發和數據交互。它可以提供以下功能和優勢:

  1. 跨域請求:代理服務可以解決瀏覽器的同源策略限制,使前端應用可以從不同的域名或端口請求數據。通過代理服務,前端應用可以將請求發送到同一域名下的代理服務器,並由代理服務器轉發到目標服務器,從而避免跨域限制。
  2. 安全性和隱私保護:代理服務可以在前端和後端之間充當安全屏障,隱藏後端服務器的真實地址和細節。通過代理服務,可以實現安全的數據傳輸、身份驗證和訪問控制,保護後端服務器的安全性,並提供額外的隱私保護。
  3. 緩存和性能優化:代理服務可以緩存靜態資源或響應結果,以減輕後端服務器的負載,並提高前端應用的性能。通過在代理層緩存數據,可以減少對後端的請求次數,加快響應速度,並減少對網絡帶寬的佔用。
  4. 請求轉發和路由:代理服務可以根據特定的規則和條件將請求轉發到不同的後端服務器,實現請求的負載均衡、路由和分發。這使得前端應用可以靈活地根據需求將請求發送到不同的服務實例或後端集羣。
  5. 日誌記錄和監控:代理服務可以記錄請求和響應的日誌,並提供監控和分析功能。通過代理服務,可以收集關於請求流量、性能指標和錯誤日誌的信息,幫助進行故障排查、性能優化和系統監控。

總而言之,代理服務在前端生態中扮演着關鍵的角色,提供了跨域請求、安全性、性能優化、請求轉發和監控等功能。它在構建現代前端應用中發揮着重要作用,幫助開發人員解決跨域問題、提高性能並提供更好的用户體驗。

安裝nginx

這裏我們以 nginx/1.12.2 為例。需要獲取源碼:

$ cd /opt/
$ wget http://nginx.org/download/nginx-1.12.2.tar.gz
$ tar -zxvf nginx-1.12.2.tar.gz

編譯安裝

$ cd /opt/nginx-1.12.2/
$ sudo make -j2
$ sudo make install

make install 後,會覆蓋之前安裝的 NginxMac 通常會安裝在 /usr/local/ 目錄下。

Nginx配置反向代理

Nginx 中配置反向代理非常簡單。下面是一個基本的反向代理配置示例:

編輯 Nginx 配置文件:

$ sudo vim /usr/local/nginx/conf/nginx.conf 

添加如下配置項:

server {
  listen 80;
  server_name example.com;

  location / {
    proxy_pass http://backend_server;
  }
}

啓動 Nginx

$ sudo /usr/local/nginx/sbin/nginx

如果已經啓動了,執行下面命令重新加載配置文件:

$ sudo /usr/local/nginx/sbin/nginx -s reload

如果想要停止服務,執行下面命令:

$ sudo /usr/local/nginx/sbin/nginx -s stop

在上述示例中,我們創建了一個服務器塊(server block),監聽 example.com 的端口 80。在 location / 塊中,我們使用了 proxy_pass 指令將請求代理到名為 backend_server 的後端服務器。

確保將 example.com 替換為您的域名或服務器 IP,將 backend_server 替換為實際的後端服務器地址。

Nginx配置延遲響應

echo-nginx-module 是一個用於 NGINX 的第三方模塊,它允許在 NGINX 中進行自定義響應的生成和處理。該模塊提供了一些指令和變量,可以用來構建自定義的響應內容。可以使用它來實現延時響應:

獲取 echo-nginx-module 源代碼,我們下載最新穩定版(截止到2018-12-23),並解壓,不用安裝

$ cd /opt
$ wget https://github.com/openresty/echo-nginx-module/archive/v0.61.tar.gz
$ tar zxvf v0.61.tar.gz

編譯 Nginx 並添加 echo-nginx-module

$ cd /opt/nginx-1.12.2/
$ ./configure --prefix=/usr/local/nginx --add-module=/opt/echo-nginx-module-0.61

請將 /opt/echo-nginx-module-0.61 替換為您實際存放 echo-nginx-module 源代碼的路徑。

運行上面的 ./configure 後進行編譯安裝:

$ sudo make install

make install 後,會覆蓋之前安裝的Nginx

配置延時響應

/usr/local/nginx/conf/nginx.confserver 代碼塊里加入如下代碼:

location /hello_echo { 
    # 延時 5 秒
    set $delay 5;
    echo_sleep $delay;
    default_type 'text/plain'; 
    echo "Delayed response after 5 seconds";
}

重新加載配置文件:

$ sudo /usr/local/nginx/sbin/nginx -s reload

image.png

Nginx配置SSL

with-http_ssl_moduleNGINX 的一個編譯選項,用於在構建 NGINX 時添加支持 SSL/TLS 的功能模塊。

SSL(Secure Sockets Layer)和其繼任者 TLS(Transport Layer Security)是用於加密網絡通信的協議。它們允許在客户端和服務器之間建立安全的加密連接,以保護數據的機密性和完整性。

通過配置 NGINX 編譯時加入 with-http_ssl_module,你可以啓用 NGINXSSL/TLS 功能。這樣,NGINX 將能夠處理加密連接、支持 HTTPS 協議以及提供 SSL/TLS 相關的配置指令。

要使用 with-http_ssl_module,你需要按照以下步驟編譯 NGINX

1、配置 with-http_ssl_module 模塊
Nginx 配置 SSL 需要配置 http_ssl_module 模塊

$ cd /opt/nginx-1.12.2/
$ ./configure --prefix=/usr/local/nginx --with-http_ssl_module
$ sudo make install

2、生成私鑰和自簽名證書
創建任意名文件夾,假設為~/ssl, 在其中新建文件 sslConfigureFile.conf

[ req ]
 
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only
 
[ subject ]
 
countryName                 = Country Name (2 letter code)
countryName_default         = CN
 
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = JiangSu
 
localityName                = Locality Name (eg, city)
localityName_default        = Nanjing
 
organizationName            = Organization Name (eg, company)
organizationName_default    = Example, LLC
 
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_default          = Example Company
 
emailAddress                = Email Address
emailAddress_default        = test@example.com
 
[ x509_ext ]
 
subjectKeyIdentifier   = hash
authorityKeyIdentifier = keyid,issuer
 
basicConstraints       = CA:FALSE
keyUsage               = digitalSignature, keyEncipherment
subjectAltName         = @alternate_names
nsComment              = "OpenSSL Generated Certificate"
 
[ req_ext ]
 
subjectKeyIdentifier = hash
 
basicConstraints     = CA:FALSE
keyUsage             = digitalSignature, keyEncipherment
subjectAltName       = @alternate_names
nsComment            = "OpenSSL Generated Certificate"
 
[ alternate_names ]
 
DNS.1       = local.cmsk1979.com # 此處需要改為本地域名, 如有需要可配合/etc/hosts修改

執行命令生成證書文件:

openssl req -config sslConfigureFile.conf -new -sha256 -newkey rsa:2048 -nodes -keyout ssl.key -x509 -days 365 -out ssl.crt

注:sslConfigureFile.conf文件路徑一定要準確

按提示執行完該命令後,將生成以下文件

~/ssl/ssl.key
~/ssl/ssl.crt

3、信任證書
雙擊生成的證書進入“鑰匙串訪問”,找到對應的證書

image.png

雙擊,選擇始終信任,瀏覽器訪問就不會提示“不安全訪問”

image.png

4、將私鑰和證書文件複製到適當的位置

將生成的私鑰文件 ssl.key 和證書文件 ssl.crt 複製到 Nginx 配置文件所在的目錄(/usr/local/ssl)。

5、配置 Nginx 使用自簽名證書
打開 Nginx 的配置文件(通常是 /usr/local/nginx/conf/nginx.conf)。

在適當的 server 塊中,添加以下 SSL/TLS 配置:

server {
  listen 443 ssl;
  server_name local.cmsk1979.com;

  ssl_certificate /usr/local/ssl/ssl.crt;
  ssl_certificate_key /usr/local/ssl/ssl.key;

  ssl_session_cache    shared:SSL:1m;
  ssl_session_timeout  5m;
    
  ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers  HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers  on;

  # 其他 Nginx 配置...
  location /hello {
    default_type 'text/plain';
    return 200 'hello!';
  }
}

6、配置hosts

127.0.0.1    www.local.cmsk1979.com
127.0.0.1    local.cmsk1979.com

7、重新加載配置文件:

sudo /usr/local/nginx/sbin/nginx -s reload

注意:訪問時不能開啓VPN代理,不然可能出現訪問失敗
image.png

訪問結果:

image.png

加上延時響應

http_ssl_module 模塊和 echo-nginx-module 編譯到 Nginx 中:

$ cd /opt/nginx-1.12.2/
$ ./configure --prefix=/usr/local/nginx --with-http_ssl_module --add-module=/opt/echo-nginx-module-0.61
$ sudo make install

在適當的 server 塊中,添加 SSL/TLS 和延時響應的配置:

server {
  listen 443 ssl;
  server_name local.cmsk1979.com;

  ssl_certificate /usr/local/ssl/ssl.crt;
  ssl_certificate_key /usr/local/ssl/ssl.key;

  ssl_session_cache    shared:SSL:1m;
  ssl_session_timeout  5m;
    
  ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers  HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers  on;

  # 其他 Nginx 配置...
  location /hello {
    set $delay 5;
    echo_sleep $delay;
    default_type 'text/plain';
    echo "Delayed response after 5 seconds";
  }
}

image.png

加上反向代理

以反向代理獲取 https://mstatic.cassmall.com/assets/sensors/sensorsdata1.19.4.min.js 為例,在適當的 server 塊中,添加 SSL/TLS 和延時響應、反向代理的配置:

server {
  listen 443 ssl;
  server_name local.cmsk1979.com;

  ssl_certificate /usr/local/ssl/ssl.crt;
  ssl_certificate_key /usr/local/ssl/ssl.key;

  ssl_session_cache    shared:SSL:1m;
  ssl_session_timeout  5m;
    
  ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers  HIGH:!aNULL:!MD5;
  ssl_prefer_server_ciphers  on;

  # 其他 Nginx 配置...
  location /assets/sensors {
    set $delay 5;
    echo_sleep $delay;
    # 傳遞客户端請求的頭信息給目標服務器
    proxy_pass https://mstatic.cassmall.com;
  }
}

可以看到代理訪問是成功的,但是延時響應的配置沒有生效

image.png

這是因為 echo_sleepecho-nginx-module 提供的內容處理程序,而 proxy_passngx_http_proxy_module 提供的內容處理程序,如果在單個位置中使用這兩個不同的內容處理程序,它們將發生衝突(因為 Nginx 只允許單個處理程序),並且只有一個會生效(哪個會生效是不確定的)。

GitHub 有一個 issue:https://github.com/openresty/echo-nginx-module/issues/5

如果我們對調一些配置的順序:

location /assets/sensors {
    # 傳遞客户端請求的頭信息給目標服務器
    proxy_pass https://mstatic.cassmall.com;
    set $delay 5;
    echo_sleep $delay;
  }

可以看到延時響應生效,而反向代理配置沒有生效

image.png

下面給出了一個解決辦法,你可以使用 echo_location 來向由 proxy_pass 配置的位置發送子請求,像這樣:

# 定義一個命名位置
location /proxy/ {
    rewrite ^/proxy/(.*)$ /$1 break;
    proxy_pass https://mstatic.cassmall.com;
}

location /assets/sensors {
    set $delay 5;
    echo_sleep $delay;
    # 使用echo_location發送子請求到/proxy位置
    echo_location /proxy/$uri;
}

返回的腳本內容呈現亂碼

image.png

修改配置:

# 定義一個命名位置
location /proxy/ {
    rewrite ^/proxy/(.*)$ /$1 break;
    proxy_pass https://mstatic.cassmall.com;
    proxy_set_header Accept-Encoding "";
    proxy_set_header Accept-Language $http_accept_language;
    proxy_set_header Content-Type "text/javascript; charset=utf-8";
}

location /assets/sensors {
    set $delay 5;
    echo_sleep $delay;
    # 使用echo_location發送子請求到/proxy位置
    echo_location /proxy/$uri;
}

image.png

參考文章:
Nginx安裝echo模塊
echo_sleep with proxy_pass - no result if echo sleep before; no delay if echo_sleep after proxy_pass

user avatar thepoy 頭像 tudou_5e2d76940fbaa 頭像
2 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.