我的 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
答案1
您在该日志中看到的是 TLS 客户端 Hello 消息。
这是客户端发送的用于启动协商的初始消息,因此该消息中没有任何加密内容。您会注意到该消息中有两个字段包含文本。它们是 SNI(服务器名称指示)和 ALPN(应用层协议协商)下一个协议字段。消息的其余部分是二进制数据,因此不太容易阅读。
在 TLS 的早期阶段,应用层协议尚未协商,会话密钥也尚未建立。客户端甚至还没有收到可以验证的证书。这意味着客户端还无法发送任何 HTTP 请求,而没有 HTTP 请求,就没有任何内容可以发送状态代码来响应。
日志条目听起来确实像 HAProxy 认为它正在响应 HTTP 请求,即使尚未发送任何请求。
由此看来,这里发生的事情似乎是服务器使用 HTTP,而客户端使用 HTTPS。因此,TLS Client Hello 消息被误解为 HTTP 请求并被拒绝为无效。
捕获流量以便检查流量以了解网络上实际发送的内容对您来说很有用。如果我对上述内容的理解正确,您应该会看到一个可以使用 Wireshark(或类似程序)解码的 TLS Client Hello 和一个带有 400 错误代码的未加密 HTTP 响应。
数据包捕获的另一个有趣之处是端口号。
您所看到的情况可能发生的一种情况是,如果用户输入了带有协议和端口号的 URL,例如,https://example.com:80/
并且 Facebook 正在尝试反复检索该 URL(因为它一直失败)。
我自己尝试将这种格式错误的 URL 放入 Facebook,果然 Facebook 向端口 80 发送了客户端 Hello 消息。我的(Apache)Web 服务器按预期响应了 400 状态代码。
您的数据包捕获确认您遇到的流量也发生在端口 80 上。因此,大概有人为 Facebook 提供了一个指向您网站的 https URL,并用 80 覆盖了正确的端口号。
您的服务器正确地响应了 400 代码,Facebook 意识到获取 URL 失败。没有什么需要修复的。您的服务器按预期运行,唯一的问题是用户在 Facebook 输入 URL 时出错。
可以通过让服务器自动检测协议以在同一端口上同时支持 HTTP 和 HTTPS 来查找有关错误 URL 的更多信息。但是我不建议使用这种黑客手段,而且我不知道是否有任何 Web 服务器软件支持它。