Nginx反向代理模式下出現頁面載入不全,或直接出現502 bad gateway的情況。
出現502 bad gateway的情況很多,大多是一些nginx相關timeout的設定問題。下文討論一種比較少見但又不得不注意的情況。
出現環境
nginx工作在反向代理模式下,監聽非80端口(這點很重要,監聽非80端口往往意味著用戶準備配置多個虛擬主機,但不限於此情境),以ip形式訪問(應該在網域訪問的情況下也存在,這點沒去驗證)。
具體問題
訪問包含多個元素的頁面(指不僅僅是靜態html頁面,客戶端往往會向伺服器請求多個元素,如圖片,css格式等等),客戶端訪問到的頁面不完整,缺乏圖片樣式等元素,回傳502 bad gateway錯誤。
問題分析
一開始接觸這個問題是,以為是host字段值非法,被後端伺服器給屏蔽了,當初這樣認為的理由如下:
1. 假設nginx監聽的位址是1.1.1.1:2001,代理程式的位址是2.2.2.2,代理伺服器配置在upstream裡,如下:
listen 1.1.1.1:2001;
upstream backend1 {
server 2.2.2.2;
}
proxy_set_header Host $host;
proxy_pass http://backend1;
2. 在上述設定下,透過wireshark抓包,客戶端存取nginx代理,也就是1.1.1.1:2001時,請求的host為,Host:1.1.1.1,如果沒設定proxy_set_header,請 nginx存取後端server的host為,Host:backend1
(Nginx官方文件提到:Allows redefining or appending fields to the request header passed to the proxied server. The value can contain text, variables, and their combinations. The value can contain text, variables, and their combinations. if and only if there are no proxy_set_header directives defined on the current level. By default, only two fields are redefined:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
如果設定了proxy_set_header Host $host,這時nginx存取後端server的host為1.1.1.1。不論哪種情況,如果後端server出於安全考慮對請求包host字段做了限制(只有為2.2.2.2,即server本身的位址才合理),那麼所有host字段不正確的訪問都會被deny或重定向或其他處理掉,不會正常訪問,所以遇到這個問題時,開始以為是後端的server作了限制。
3. 後來思考,如果後端server真對存取包的host欄位作了限制,應該不會有頁面載入不全的情況,畢竟很少有server對某部分元素做限製而某部分不做。透過進一步抓包分析,client在第一次造訪包含多個元素的頁面後,server會將這個頁面中包含的其他元素位址告訴client,以便client繼續要求取得來取得一個資訊完整的網頁,而server告訴client的其他元素的位址的ip:port恰恰與nginx與server通訊的host欄位相同(可以理解,nginx做反向代理),如果host中沒設定端口,預設是80(這就是為什麼nginx監聽80端口往往沒有問題),client會依據這個回傳的位址來取得頁面元素。
4. 所以在上面的情況,如果設定了proxy_set_header Host $host,client訪問頁面其他元素的位址將是http://1.1.1.1/…,可以看到,還是透過nginx代理,但問題來了:nginx監聽的是1.1.1.1:2001,而新來的存取是1.1.1.1:80(http埠預設80,https預設443),所以無法透過nginx來代理請求。
解決方式
解決方法也很簡單,就是proxy_set_header Host $host:$server_port,這樣會將nginx監聽的連接埠加上去。
後記
雖然這次證明並非是因server對Host字段限製而影響的訪問,但個人認為host字段的限制問題是值得注意的,nginx官方也推薦對於非法host的訪問是直接deny的。
').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i ').text(i)); }; $numbering.fadeIn(1700); }); });以上就介紹了nginx頁面載入不全或提示502bad gateway,nginx反向代理埠號遺失,包括了bad gateway方面的內容,希望對PHP教學有興趣的朋友有所幫助。