Redmine是一套架構在Ruby on Rails的專案平台,開發團隊最近在公司架了個Windows版,用它追蹤及管理Bug,取代先前使用的BugTracker.NET。
不知從何時起,我手邊兩台機器連上Redmine回應奇慢,明明是在Intranet 100M LAN,開啟網頁時畫面都會頓一下,等上幾秒鐘才會顯示。最令人氣結的是,只有我的兩台機器有此症狀,其他人用起來速度飛快,完全感受不到任何延遲,只有我活似從火星衛星連線,讓人氣到想"冰斗"。
用瀏覽器側錄網路傳輸看到一個現象: 從我機器發出的所有Request會先被卡住4秒,之後才像閘門被打開,幾個Request結果一起被傳回來。
同樣的現象在IE跟Chrome都存在,但只發生在這台Redmine(httq://redmine_host:3000/*),改連同一主機IIS的80 Port不會有問題,在其他台IIS開個HTTP Port 3000 Web Site,連起來也沒有任何延遲。
最後,我整理出一個極精簡的問題重現法: 在LINQPad4執行一小段程式,用WebClient從Remine主機取回一個匿名存取圖檔,實測要耗時9秒鐘。
從沒遇過這種玄疑狀況,毫無頭緒,甚至懷疑該不會機器中木馬被攔截特定傳輸被才會如此,一想到不禁冒了冷汗。(資安偏執狂很會疑神疑鬼呀~)
最後,決定動用對付網路茶包的小型核武 – Microsoft Network Monitor。
錄下LINQPad測試過程的來往封包,很快發現一些怪異記錄,除了LINQPad的傳輸,另外冒出一段Redmine主機與主機間的System層次網路活動:
檢視System的網路活動,研判是連續六次NetBIOS查詢:
對照WebClient的相關封包,可以看出有趣關聯:
- 3.7750秒時,WebClient發出GET /images/loading.gif Request
- 從3.7885起,分別在3.7885, 5.2875, 6.7872, 8.2887, 9.7877, 11.2875六個時點,Redmine主機陸續丟過來六次NetBIOS查詢(推測是要查詢我的機器名稱),但我的主機未給回應。
- 為了降低被攻擊風險,我習慣關閉對外的NetBIOS相關Port,這是主機沒回應NetBIOS查詢的原因。
- 在六次NetBIOS查詢失敗後,在12.7959秒Redmine主機終於送回loading.gif圖檔內容,足足慢了九秒。
由此推測,Redmine主機似乎會反查機器名稱,但因為我關閉NetBIOS Port導致查詢失敗,歷經六次嘗試後才放棄,甘心傳回結果,這可以解釋每次連線時會先停頓幾秒(試著反查機器名稱),之後才多個Request一起傳回的現象。而關閉NetBIOS Port是我這種資安偏執狂才會做的機車之舉,無怪乎同一個網站大家用得好好的,唯獨我一直卡到陰。
為了驗證假設,試著在Redmine主機的system32/drivers/etc/hosts加入我的機器IP與名稱,果不其然,卡住狀況瞬間消失。掌握住問題大方向,沒多就爬文找到根本原因,原來我們的Redmine採用Webrick做為網站伺服器,而Webrick有一個廣為人知的問題 -- 預設會反查Client機器名稱,有時導致回應緩慢,但config.rb中有個DoNotReverseLookup選項可以關閉設定。找到C:\Ruby\v193\lib\ruby\1.9.1\webrick\config.rb後,將其中的 :DoNotReverseLookup => nil 改為 :DoNotReverseLookup => true,另一台未設hosts記錄的機器也立刻不再卡卡,茶包正式消滅,Microsoft Network Monitor萬歲!