目前有个嵌入式设备,发出的http请求是不标准的
POST /dev_heart_info HTTP/1.1
Host: Host /HTTP/1.0
User-Agent: My Device
Connection: Keep-Alive
accept: application/json
content-type: application/json;charset=UTF-8
Content-Length: 95
{
"devId": "FS4051-C21SJ30A4900",
"moduleId": 0,
"msgType": 4106,
"devIp": "192.168.8.52"
}HTTP/1.1 400 Bad Request
Server: nginx/1.21.5
Date: Fri, 28 Oct 2022 11:19:37 GMT
Content-Type: text/html
Content-Length: 157
Connection: close
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx/1.21.5</center>
</body>
</html>
请求过来的header
中的host
字段不标准,所以nginx不做解析和转发直接报400了。
想请教下这种情况如何处理,禁用Host
校验或者nginx重设掉该Host
均可。
最后看了nginx源码发现确实是强制不支持了,最后解决方案是自己修改了那段代码,自己编译nginx,这里把步骤给后来人参考下
- 下载nginx源码
wget http://nginx.org/download/nginx-1.21.5.tar.gz
- 修改检测
Host
的函数,文件ngx_http_request.c
static ngx_int_t
ngx_http_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
{
return NGX_OK;
}
改为直接return正常
- 构建
nginx
镜像,Dockerfile
如下
FROM centos:7.8.2003
MAINTAINER wudengguang (wu_dengguang@finsung.com)
ADD nginx-1.21.5 /usr/local/src/nginx-1.21.5
WORKDIR /usr/local/src/nginx-1.21.5
RUN yum install -y gcc gcc-c++ glibc make autoconf openssl openssl-devel \
&& yum install -y libxslt-devel -y gd gd-devel GeoIP GeoIP-devel pcre pcre-devel \
&& useradd -M -s /sbin/nologin nginx && BUILD_CONFIG="--prefix=/usr/local/nginx \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-stream \
--with-http_v2_module \
--with-threads" && ./configure $BUILD_CONFIG \
&& mkdir -p /var/cache/nginx && make && make install
ENV PATH /usr/local/nginx/sbin:$PATH
EXPOSE 80
EXPOSE 443
ENTRYPOINT ["nginx"]
CMD ["-g","daemon off;"]
我用nginx验证了一下,找了资料,发现nginx似乎没办法处理这个非法的Host。
但是我用haproxy测试了一下,haproxy可以正常处理非法的host,重写host之后可以正常传给后端。
haproxy配置:
这里我把Host 替换成了 localhost
===
处理之后,后端接收到的请求是这样的:
要是不方便更新终端的话,可以考虑在nginx前面再套一个haproxy,让haproxy处理后再转给nginx或者后端服务。