【问题标题】:Why always receive status code 400 when sending HTTP request to HAProxy为什么向 HAProxy 发送 HTTP 请求时总是收到状态码 400
【发布时间】:2019-06-06 13:46:44
【问题描述】:

我有一个在 HTTP 模式下工作的 HAProxy,一切都很顺利。

但是当我在 URI 中发送带有空格(是 ASCII 32)的请求时,发生了一些奇怪的事情!

我收到状态码 400:您的浏览器发送了无效请求。

这是请求,你可以使用curl来测试:

# Do not use browser like Chrome or Firefox, or the request will be encoded
# before is was sent to HAProxy
# haproxy is my testing server here
curl -i -v 'http://haproxy/search?oq=haproxy invalid request'

这是回复:

* About to connect() to haproxy port 80 (#0)
*   Trying xx.xxx.xxx.xxx... connected
* Connected to haproxy (xx.xxx.xxx.xxx) port 80 (#0)
> GET /search?oq=haproxy invalid request HTTP/1.1
> User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
> Host: haproxy
> Accept: */*
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 400 Bad request
HTTP/1.0 400 Bad request
< Cache-Control: no-cache
Cache-Control: no-cache
< Connection: close
Connection: close
< Content-Type: text/html
Content-Type: text/html

< 
<html><body><h1>400 Bad request</h1>
Your browser sent an invalid request.
</body></html>
* Closing connection #0

当我将空格编码为“+”或“%20”时,一切正常。

这样的请求:

curl -i 'http://haproxy/search?oq=haproxy+invalid+request'
curl -i 'http://haproxy/search?oq=haproxy%20invalid%20request'

回复:

HTTP/1.1 302 Found
Cache-Control: no-cache
Content-length: 0
Location: http://www.google.com/search?oq=haproxy%20invalid%20request
Connection: close

由于某些原因,我们无法对请求中的每个空格进行编码,因此我尝试在此处为 HAProxy 设置一个参数,并遵循以下解决方案:

Configuration Manual

extra-space-in-http-headers-gives-400-error-on-haproxy

但两者都不起作用。

这是建议的参数:

# Enable or disable relaxing of HTTP request parsing
option accept-invalid-http-request

这是我的 haproxy.cfg

global
    log 127.0.0.1 local2 info
    chroot /usr/local/haproxy
    pidfile /var/run/haproxy.pid
    nbproc 1
    maxconn 32768
    user root
    group root
    daemon
    stats socket /var/lib/haproxy/stats

defaults
    log global
    mode http
    timeout client 10s
    timeout connect 10s
    timeout server 10s

# This is for HTTP over port 80
frontend http_in
    bind 0.0.0.0:80
    maxconn 4096
    option accept-invalid-http-request
    default_backend google

# This is for backend server
backend google
    mode http
    balance roundrobin
    server google1 127.0.0.1:80 redir http://www.google.com check

这是 HTTP 日志:

Jun  6 12:07:17 localhost haproxy[32059]: 61.155.184.119:45028 [06/Jun/2019:12:07:17.944] http_in http_in/<NOSRV> -1/-1/-1/-1/0 400 187 - - PR-- 1/1/0/0/0 0/0 "<BADREQ>"
Jun  6 12:07:26 localhost haproxy[32059]: 61.155.184.119:45029 [06/Jun/2019:12:07:26.083] http_in http_in/<NOSRV> -1/-1/-1/-1/0 400 187 - - PR-- 1/1/0/0/0 0/0 "<BADREQ>"

这是 socat 错误:

echo "show errors" | socat stdio /var/lib/haproxy/stats

Total events captured on [06/Jun/2019:13:17:41.009] : 6

[06/Jun/2019:12:07:26.083] frontend http_in (#2): invalid request
  backend <NONE> (#-1), server <NONE> (#-1), event #5, src xx.xxx.xxx.xxx:45029
  buffer starts at 0 (including 0 out), 16189 free,
  len 195, wraps at 16384, error at position 23
  stream #10, stream flags 0x00000000, tx flags 0x00000000
  HTTP msg state MSG_RQVER(6), msg flags 0x00000000
  HTTP chunk len 0 bytes, HTTP body len 0 bytes, channel flags 0x00d08002 :

  00000  GET /search?oq=haproxy invalid request HTTP/1.1\r\n
  00049  User-Agent: curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3
  00119+ .13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2\r\n
  00165  Host: haproxy\r\n
  00180  Accept: */*\r\n
  00193  \r\n

经过测试的 HAProxy 版本:

HA-Proxy version 1.9.8 2019/05/13
HA-Proxy version 1.5.18 2016/05/10

HAProxy 服务器环境:

CentOS release 6.8 (Final)
Linux version 2.6.32-696.23.1.el6.x86_64 (mockbuild@x86-01.bsys.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-18) (GCC) ) #1 SMP Tue Mar 13 22:44:18 UTC 2018

有没有人遇到过类似的问题?

任何意见和建议将不胜感激。

谢谢。

【问题讨论】:

    标签: http request haproxy space http-status-code-400


    【解决方案1】:

    URI 中不能有空格字符。 HAProxy 纠正它是正确的。

    能否详细说明:

    “由于某些原因,我们不可能对请求中的每个空格进行编码”

    ?

    另请注意,请求行不是 HTTP 标头字段,因此您正在查看一个不相关的配置选项。

    【讨论】:

    • 感谢您的回复,我同意 HAProxy 纠正它是正确的,但我们可以将相同的请求发送到 Nginx 服务器,并且我们有很多这样的老式请求。
    • 那么应该报一个NGINX服务器的bug。
    猜你喜欢
    • 1970-01-01
    • 2013-01-26
    • 2020-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-04
    • 2020-07-05
    • 2020-12-11
    相关资源
    最近更新 更多