加入收藏 | 设为首页 | 会员中心 | 我要投稿 威海站长网 (https://www.0631zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 安全 > 正文

从400错误引发的故障入手,谈谈如何分析和修复常见的Nginx异常

发布时间:2021-01-12 14:43:02 所属栏目:安全 来源:网络整理
导读:《从400错误引发的故障入手,谈谈如何分析和修复常见的Nginx异常》要点: 本文介绍了从400错误引发的故障入手,谈谈如何分析和修复常见的Nginx异常,希望对您有用。如果有疑问,可以联系我们。 作者介绍 林伟壕,网络安全DevOps新司机,先后在中国电信和网易游
副标题[/!--empirenews.page--]

《从400错误引发的故障入手,谈谈如何分析和修复常见的Nginx异常》要点:
本文介绍了从400错误引发的故障入手,谈谈如何分析和修复常见的Nginx异常,希望对您有用。如果有疑问,可以联系我们。


作者介绍

林伟壕,网络安全DevOps新司机,先后在中国电信和网易游戏从事数据网络、网络安全和游戏运维工作.对Linux运维、虚拟化和网络安全防护等研究颇多,目前专注于网络安全自动化检测、防御系统构建.

众所周知,Nginx是目前最流行的Web Server之一,也广泛应用于负载均衡、反向代理等服务,使用过程中可能因为对Nginx工作原理、变量含义、参数大小等问题的理解错误,导致Nginx工作异常.

因此,本文将从一个Nginx错误代码400引发的故障入手,谈谈如何分析和修复常见的Nginx异常.

故障简述

小明某天中午在线优化一个敏感服务的Nginx配置时,发现5分钟内Nginx errorlog里出现了大量400错误,于是迅速回滚了Nginx配置.

故障详情

原来的Nginx配置存在重复或者需废弃的内容,于是在多次diff了新旧两份配置内容后,小明认为最新配置是不影响业务的,因此在线推送更新配置后,直接reload了Nginx,出于double check原则,在线观察了5分钟Nginx日志:

发现出现大量类似下面的400错误:

400错误的产生,很可能影响服务端或客户端的后续业务逻辑判断,因此需要引起重视.

处理过程

节点1

当时回滚配置后,小明先在搜索引擎查找了Nginx 400错误的可能原因和解决办法,初步确定有下面两种可能:1是空主机头,2是请求包头过大.

小明跟客户端同学确认了客户端请求方式,发现他们使用的是类似telnet的方式发起的http请求,类似下面的:

为了方便后续排查,小明参考线上环境临时搭建了一套Nginx测试环境,重现了故障:

后来小明了解到原来客户端不是从代码的http库调用,而是按照上面的方式走TCP/telnet传递http参数来调用服务端http接口.但是为什么一样的客户端请求方式,旧配置完全ok,新配置则会出现大量400错误?

节点2

至此,小明怀疑自己没有完全diff出新旧两份配置的差别,于是他使用vimdiff再次对比新旧两份配置.下面仅贴出关键配置:

旧配置:

新配置:

本次排查中,小明考虑的重点是新配置里遗漏了某些配置,于是他把location ~ (.*)的相关逻辑加上,发现问题依旧:

节点3

既然前面往缺失配置的思路走不通,下面就按照新增配置的思路排查,结果发现新配置增加了一些包头信息,小明怀疑是请求包过大,于是优先排查了Nginx针对包头大小的设置,其中有这么几个配置:

client_header_buffer_size:默认是1k,所以header小于1k的话是不会出现问题的.
large_client_header_buffers:该命令用于设置客户端请求的Header头缓冲区的大小,默认值为4KB.
客户端请求行不能超过large_client_header_buffers指令设置的值,客户端请求的Header头信息不能大于large_client_header_buffers指令设置的缓冲区大小,否则会报“Request URL too large”(414)或者“Bad-request”(400)错误,如果客户端Cookie信息较大,则须增加缓冲区大小.于是小明将client_header_buffer_size和large_client_header_buffers都设置为128k.结果问题也重现了.

接下来,小明发现新配置中多了“proxy_set_header Host $http_host;”查找了Nginx官方文档发现跟$http_host类似功能的还有$server_name和$host等变量,在他将$http_host更换成$host后,问题修复了.

原因分析

根据Nginx官方文档介绍,400状态码含义如下:

上面是http1.1的rfc关于host部分的解释,从上面我们了解到如果一个http1.1的请求没有host域,那么server应该给client段发送400的状态码,表明这个请求server不能处理.而对于Nginx server来说,也遵循这样的方式,说明client发送了一个无效的请求,Nginx server无法处理,于是返回了400的状态码.

另外,关于$host和$http_host这两个变量的区别如下:

(编辑:威海站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读