在 HaProxy 上收到 BADREQ 400 错误?

在 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

答案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 服务器软件支持它。

相关内容