【問題解決】 網關代理Nginx 301暴露自身端口號

一般項目上常用Nginx做負載均衡和靜態資源服務器,本案例中項目上使用Nginx作爲靜態資源服務器出現了很奇怪的現象,我們一起來看看。

“詭異”的現象

部署架構如下圖,Nginx作爲靜態資源服務器監聽8080端口,客戶瀏覽器通過API網關的443端口(就是https)獲取Nginx靜態資源。

現象是用戶瀏覽器訪問API網關的https地址後,API網關將請求SSL解密再請求Nginx 50001端口的/hd-portal路徑,但返回給客戶端的卻是 https://a.com:50001/hd-portal/ !!! 這還是個重定向響應,響應頭裏包含 Location: https://a.com:50001/hd-portal/,由於API網關並沒有開放這個端口號,所以請求到這裏就無法繼續下去了。

問題分析

筆者是同事拉進線上會議看的這個問題,大家已經琢磨好一會了,我讓同事復現了下現象,也試着調了幾個nginx.conf的參數沒有奏效,趕上快中午了,就讓同事用tcpdump抓下Nginx服務器網絡包,我開始Wireshark分析。(常規定位Nginx的問題有兩個辦法:看access.log判斷問題 和 tcpdump抓包分析確定問題。看access.log沒看出那個50001是誰返回的)

這裏就很明確是Nginx返回的301永久重定向,Nginx使用自己端口號暴露出來做的重定向。到此問題已清晰,只要不讓Nginx把端口號暴露出來就可以了。

問題原因

這得先從Nginx的處理流程說起。

案例中,我們請求的是 https://API網關/hd-portal ,Nginx收到請求發現 /hd-portal 是一個目錄,就會設置響應頭Location 和空的響應體,試圖讓瀏覽器以目錄方式訪問資源。而瀏覽器收到響應後,解析響應頭髮現 Location 響應頭確定要重定向,就開始跳轉 https://API網關/hd-portal/

以上是正確合理的情況,不合理的點在於:Nginx爲啥把自己端口號暴露出來了?

經過查詢了Nginx官方文檔,發現了三個有聯繫的配置項,分別貼圖出來:

這三個配置分別是 absolute_redirect / server_name_in_redirect / port_in_redirect,以下簡要說明下三者作用:

  • absolute_redirect:啓用時表示絕對路徑重定向,默認on啓用
  • server_name_in_redirect: 啓用時表示使用Nginx的server_name配置替換重定向路徑,默認off禁用
  • port_in_redirect:啓動時表示重定向時替換重定向的端口號,默認on啓用
  • 這三個配置關係中,如果absolute_redirect配置off,則後兩個配置失效。

解決方案

至此,可以有兩種解決方案,根據實際情況任選其一即可:

  • absolute_redirect配置 off(禁用絕對路徑跳轉,相當於自動識別目錄)
  • port_in_redirect配置 off(禁止替換重定向端口號)

這兩個方案的配置位置可以是http / server / localtion塊,作用範圍也是根據配置位置決定的。

至於本案例中,由於多個項目使用同一個server,就在location塊中添加了 port_in_redirect: off; 解決了問題。

總結

本文試圖從問題現象到分析與解決方案的提出讓讀者能對Nginx的301重定向做到心中有數,相信讀者看完本文再出現類似的問題解決起來肯定更輕鬆愉快!

我是Hellxz,如果本文對您有所幫助,請點個贊再走唄!~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章