在 HaProxy 上收到 BADREQ 400 錯誤?
我在我的 HAProxy 日誌中獲得了大量的 BADREQ 條目(每分鐘 10 多個)。
例子:
10 月 1 日 19:46:00 LB haproxy
$$ 19022 $$: 69.171.251.8:57356 $$ 01/Oct/2018:19:46:00.903 $$站點名稱 站點名稱/ -1/-1/-1/-1/5 400 187 - - PRNN 19/19/0/0/5 0/0 ""
幾乎所有這些似乎都來自 Facebook 的爬蟲。
爬蟲似乎在大多數情況下都可以很好地抓取內容。但是,這些請求中有少數會導致 BADREQ 錯誤。
正如其他地方所建議的,我使用 socat 通過執行以下命令來查看最後一個錯誤:
sudo echo "show errors" | sudo socat unix-connect:/var/run/haproxy.stat stdio
這給了我以下輸出:
invalid request backend mysite (#2), server <NONE> (#-1), event #127 src 69.171.251.1:61042, session #9717, session flags 0x00000080 HTTP msg state 26, msg flags 0x00000000, tx flags 0x00000000 HTTP chunk len 0 bytes, HTTP body len 0 bytes buffer flags 0x00808002, out 0 bytes, total 517 bytes pending 517 bytes, wrapping at 32776, error at position 0: 00000 \x16\x03\x01\x02\x00\x01\x00\x01\xFC\x03\x03 B\x9B\xF8\xAE\xFB=\xD7dN 00021+ \x8D\xAD\xCCP\x99\x9C\xEEow#w\n 00033 \xB5\x99\x16g@\x1F{\x9A5H\x00\x00\xAA\xC00\xC0,\xC0(\xC0$\xC0\x14\xC0 00057+ \n 00058 \x00\xA5\x00\xA3\x00\xA1\x00\x9F\x00k\x00j\x00i\x00h\x009\x008\x007 00080+ \x006\xCC\xA9\xCC\xA8\xCC\x14\xCC\x13\xCC\xAA\xCC\x15\x00\x88\x00\x87 00098+ \x00\x86\x00\x85\xC02\xC0.\xC0*\xC0&\xC0\x0F\xC0\x05\x00\x9D\x00=\x005 00120+ \x00\x84\xC0/\xC0+\xC0'\xC0#\xC0\x13\xC0\t\x00\xA4\x00\xA2\x00\xA0\x00 00141+ \x9E\x00g\x00@\x00?\x00>\x003\x002\x001\x000\x00\x9A\x00\x99\x00\x98 00164+ \x00\x97\x00E\x00D\x00C\x00B\xC01\xC0-\xC0)\xC0%\xC0\x0E\xC0\x04\x00 00187+ \x9C\x00<\x00/\x00\x96\x00A\xC0\x12\xC0\x08\x00\x16\x00\x13\x00\x10 00206+ \x00\r\xC0\r\xC0\x03\x00\n 00214 \x00\xFF\x01\x00\x01)\x00\x00\x00\x14\x00\x12\x00\x00\x0Ffb.mysite.c 00242+ om\x00\x0B\x00\x04\x03\x00\x01\x02\x00\n 00254 \x00\x1C\x00\x1A\x00\x17\x00\x19\x00\x1C\x00\e\x00\x18\x00\x1A\x00\x16 00272+ \x00\x0E\x00\r\x00\x0B\x00\x0C\x00\t\x00\n 00284 \x00\r\x00 \x00\x1E\x06\x01\x06\x02\x06\x03\x05\x01\x05\x02\x05\x03 00302+ \x04\x01\x04\x02\x04\x03\x03\x01\x03\x02\x03\x03\x02\x01\x02\x02\x02 00319+ \x033t\x00\x00\x00\x10\x00\x0B\x00\t\x08http/1.1\x00\x15\x00\xAE\x00 00344+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00361+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00378+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00395+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00412+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00429+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00446+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00463+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00480+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00497+ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 00514+ \x00\x00\x00
老實說,我不知道如何理解上述內容!
更新:我設法使用 tcpdump 在埠 80 上擷取流量。我下載了擷取文件並用 WinShark 打開它。
我發現了一些來自 Facebook IP 31.13.127.5 的請求:
10622 15.837038 31.13.127.5 MYSERVERIP TCP 66 47658 → 80 [ACK] Seq=1 Ack=1 Win=61440 Len=0 TSval=1921577847 TSecr=59275252 10701 15.848790 31.13.127.5 MYSERVERIP TCP 583 47658 → 80 [PSH, ACK] Seq=1 Ack=1 Win=61440 Len=517 TSval=1921577859 TSecr=59275252 10702 15.848846 MYSERVERIP 31.13.127.5 HTTP 253 HTTP/1.0 400 Bad request (text/html) 10914 15.927603 31.13.127.5 MYSERVERIP TCP 66 47658 → 80 [FIN, ACK] Seq=518 Ack=189 Win=63488 Len=0 TSval=1921577937 TSecr=59275274 10915 15.927611 MYSERVERIP 31.13.127.5 TCP 66 80 → 47658 [ACK] Seq=189 Ack=519 Win=30080 Len=0 TSval=59275294 TSecr=1921577937 12044 17.419319 31.13.127.5 MYSERVERIP TCP 74 53712 → 80 [SYN] Seq=0 Win=61320 Len=0 MSS=1460 SACK_PERM=1 TSval=1921579431 TSecr=0 WS=2048 12045 17.419337 MYSERVERIP 31.13.127.5 TCP 74 80 → 53712 [SYN, ACK] Seq=0 Ack=1 Win=28960 Len=0 MSS=1460 SACK_PERM=1 TSval=59275667 TSecr=1921579431 WS=128 12125 17.493182 31.13.127.5 MYSERVERIP TCP 66 53712 → 80 [ACK] Seq=1 Ack=1 Win=61440 Len=0 TSval=1921579505 TSecr=59275667 12126 17.501269 31.13.127.5 MYSERVERIP TCP 583 53712 → 80 [PSH, ACK] Seq=1 Ack=1 Win=61440 Len=517 TSval=1921579513 TSecr=59275667 12127 17.501387 MYSERVERIP 31.13.127.5 HTTP 253 HTTP/1.0 400 Bad request (text/html) 12179 17.576974 31.13.127.5 MYSERVERIP TCP 66 53712 → 80 [FIN, ACK] Seq=518 Ack=189 Win=63488 Len=0 TSval=1921579589 TSecr=59275687
您在該日誌中看到的是 TLS 客戶端 Hello 消息。
這是客戶端發送的用於啟動協商的初始消息,因此該消息中沒有任何加密內容。您會注意到該消息中有兩個包含文本的欄位。這些是 SNI(伺服器名稱指示)和 ALPN(應用層協議協商)下一個協議欄位。消息的其餘部分是二進制數據,因此不那麼容易閱讀。
在 TLS 的早期階段,應用層協議尚未協商,會話密鑰尚未建立。客戶甚至沒有收到可以驗證的證書。這意味著客戶端還無法發送任何 HTTP 請求,並且沒有 HTTP 請求,就沒有任何東西可以發送狀態碼作為響應。
日誌條目聽起來肯定像是 HAProxy 認為它正在響應 HTTP 請求,即使沒有發送任何請求。
從這聽起來,這裡發生的事情是伺服器正在使用 HTTP,而客戶端正在使用 HTTPS。因此,TLS 客戶端 Hello 消息被誤解為 HTTP 請求並被視為無效而被拒絕。
擷取流量對您很有用,以便可以對其進行檢查以找出實際線上路上發送的內容。如果我對上述內容的看法是正確的,您應該會看到一個 TLS 客戶端 Hello,可以使用 Wireshark(或類似軟體)解碼,以及一個帶有 400 錯誤程式碼的未加密 HTTP 響應。
數據包擷取的有趣之處還在於埠號。
您看到的一種可能發生的情況是,如果使用者輸入了帶有協議和埠號的 URL,例如
https://example.com:80/
facebook 正試圖重複檢索該 URL(因為它一直失敗)。我自己嘗試將這種格式錯誤的 URL 放入 facebook,果然 facebook 向埠 80 發送了一條 Client Hello 消息。我的(Apache)Web 伺服器按預期響應了 400 狀態程式碼。
您的數據包擷取確認您的情況下的流量也發生在埠 80 上。所以大概有人給了 facebook 一個指向您的站點的 https URL,並用 80 覆蓋了正確的埠號。
您的伺服器使用 400 程式碼正確響應,並且 facebook 意識到獲取 URL 失敗。沒有什麼可以修復的。您的伺服器按預期工作,唯一的問題是在將 URL 輸入 facebook 時出現使用者錯誤。
通過讓您的伺服器自動檢測協議以便在同一埠上同時支持 HTTP 和 HTTPS,可以找到更多關於錯誤 URL 的資訊。但是我不推薦這樣的黑客,我不知道是否有任何網路伺服器軟體支持它。