一次線上websocket返回400問題排查的實戰(zhàn)記錄
現(xiàn)象
生產(chǎn)環(huán)境websocket無法正常連接,服務端返回400 bad request,開發(fā)及測試環(huán)境均正常。
抓包排查
src:nginx服務器 172.16.177.193
dst:imp應用服務器 172.16.177.218
問題定位
觀察到header中的host值帶有下劃線,在一些中間件(如kafka、hadoop)中,對host中的特殊字符也有限制。由此猜測是header問題。
經(jīng)排查,此header來自nginx的upstream
解決方案1
修改nginx的upstream配置,去除下劃線
解決方案2
既然upstream中用了下劃線,為何普通的http請求正常,而websocket則返回400呢?
再看正常的http請求的抓包
src: nginx服務器 172.31.47.151
dst: imp應用服務器 172.31.47.153
可見,header中的host,被轉(zhuǎn)發(fā)到了目標服務器,而此host并沒有下劃線,正常請求。
所以,如果不修改nginx中的upstream下劃線的配置,其實還可以在server中的websocket 對應的location中,添加參數(shù),以便轉(zhuǎn)發(fā)原始請求的host
proxy_set_header Host $host; proxy_set_header X-real-ip $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
配置后的抓包如下
請求正常
原因探討
帶有下劃線的host,為何會被服務端返回400?從上述排查過程可知,應是tomcat返回的。
這一切要從一個RFC協(xié)議規(guī)范說起
RFC-1034是一個關于DNS及域名基礎的標準。在「3.5 Preferred name syntax」中,有提及主機名的格式規(guī)范:由字母開頭,字母或數(shù)字結(jié)尾,中間包含字母、數(shù)字或橫桿
可見,RFC-1034標準中下劃線并不被允許。
而Tomcat在一次8.x的升級中遵循該標準對host做了此校驗,詳見鏈接
org.apache.coyote.AbstractProcessor#parseHost
org.apache.tomcat.util.http.parser.Host#parse(java.io.Reader)
總結(jié)
在我們?nèi)粘E渲胔ost參數(shù)時,都盡量避免使用下劃線。包括在/etc/hosts下進行的配置,有時在集群環(huán)境中為了方便管理,會配置host,此時也應注意避免使用下劃線。因為中間件可能也遵循了RTC規(guī)范。
延伸閱讀
如果大家閱讀了上述規(guī)范,可能會有疑問:為何網(wǎng)易163可以是數(shù)字開頭?大家可以先去了解下域名的解析過程。
此處科普幾個基本概念。
domain nameis the identifier of a resource in a DNS databaselabelis the part of a domain name in between dotshostnameis a special type of domain name which identifies Internet hosts
域名是在dns庫中的唯一標識,label是域名中以「.」分隔的單元,hostname是對于一個地址的特殊域名映射。
在1989年的RFC-1101中的「3.1 Network name syntax」定義了網(wǎng)絡名詞的DNS編碼規(guī)范。允許數(shù)字開頭,只要不與十進制八位字節(jié)形式的ip地址沖突。
在1997年的RFC-2181中「11 Name syntax」對域名語法作了澄清,下劃線不應被DNS服務所拒絕。
而在近年的一次CA/B論壇里,眾多大廠發(fā)起投票,禁止在域名中使用下劃線,否則SSL證書將不能正常申請使用。
有興趣的朋友可以嘗試搭建一個網(wǎng)站并作域名映射。可以確定的是,做域名映射時,因為是hostname,A和MX記錄是不能帶下劃線的。CNAME記錄由于針對的是域名,是否支持則取決于你的DNS服務商了。
到此這篇關于一次線上websocket返回400問題排查的文章就介紹到這了,更多相關websocket返回400問題內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot啟動feign項目報錯:Service id not legal hostnam的解決
這篇文章主要介紹了springboot啟動feign項目報錯:Service id not legal hostnam的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08Java多線程中線程池常見7個參數(shù)的詳解以及執(zhí)行流程
本文主要介紹了Java多線程中線程池常見7個參數(shù)的詳解以及執(zhí)行流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-07-07Jenkins集成sonarQube實現(xiàn)代碼質(zhì)量檢查過程圖解
這篇文章主要介紹了Jenkins集成sonarQube實現(xiàn)代碼質(zhì)量檢查過程圖解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09Java實戰(zhàn)之基于I/O流設計的圖書管理系統(tǒng)
這篇文章主要介紹了Java實戰(zhàn)之基于I/O流設計的圖書館管理系統(tǒng),文中有非常詳細的代碼示例,對正在學習java的小伙伴們有非常好的幫助,需要的朋友可以參考下2021-04-04