Haproxy

在 HaProxy 上收到 BADREQ 400 錯誤?

  • October 29, 2018

我在我的 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 的資訊。但是我不推薦這樣的黑客,我不知道是否有任何網路伺服器軟體支持它。

引用自:https://serverfault.com/questions/933521