接口403问题没这么容易解决
最近一同事反馈在后台保存某业务数据时一直报403,该数据由运营人员在后台录入,然后向后端发送POST请求保存数据;现象是如果内容过长如几十K则报403,如果只输入几个字符则没问题,多方排查无解。
这是一个典型的LNMP应用架构,WEB是Nginx,后端应用是PHP,数据库是Mysql。
出现问题第一反应是查日志,按这些链路查:
1、Nginx错误日志
一般403、502之类的Nginx错误日志中中相应记录;
每个server有error_log的配置,查找日志中是否有无线索;
2、PhpFpm日志
Php用的是PhpFpm作为容器,其也有error_log指令,可以查看这个日志有无响应线索;
3、应用日志
这个根据应用自己的情况搜索。
通过上述排查,都无线索。
日志不行再查配置,Nginx对body有些限制参数:
client_max_body_size 8M;
但上述场景才几十K,所以这个可能性排除。
再看Php的配置,Php也有相关Post参数,如
post_max_size = 25M
max_input_var=5000
post_max_size是限制请求体大小,而max_input_var是限制post中有多少个key的,案例也没有超过这些限制。
这些都不行,只能抓包了,nginx和php-fpm之间是通过fastcgi协议传输的,因为配置的upstream是127.0.0.1,因此要抓下本地回环的包:
tcpdump -i lo port 9000 -w /tmp/php.pcap
先看下正常的包,即只输入几个字符的情况:
上述场景我们输入的是123456789,抓包发现nginx是有将相应内容传递给PHP的,这里涉及到fastcgi协议的格式,因重点不是这个,有兴趣的同学可以自行百度下。
然后抓下输入为几十k的请求:
发现内容根本就没传递过去,因为我们的Nginx上有很多配置,为了调试方便先把一些不用的配置去掉,再删掉2处Lua的配置后重新启动Nginx,接口提交成功了。
再仔细分析一下其中一行Lua配置,原来是Lua防火墙,对一些敏感关键字做了处理,如果发现在相应内容会将内容清空,并返回错误,奇怪的是这些异常情况竟然没有错误日志。
短期解决办法是将防火墙相关配置关闭,长期还是需要对防火墙结合业务场景进行梳理,提高拦截的准确率,并且在拦截时提供相应日志便于快速定位问题。
最后总结下,主要问题是Lua防火墙对输入内容进行了拦截,但是拦截后没有明显的日志,导致排查问题比较麻烦。
本次排查问题的思路:
1、查日志
先中间件,如Nginx、PhpFpm,然后是应用日志
2、分析中间件配置
3、抓包分析
主要是验证传输链路有没问题,快速定位出问题的环节
如果上述还是无法解决问题,只有Debug源代码了。
- 1741: [Usaco2005 nov]Asteroids 穿越小行星群
- 3298: [USACO 2011Open]cow checkers
- 3433: [Usaco2014 Jan]Recording the Moolympics
- 3410: [Usaco2009 Dec]Selfish Grazing 自私的食草者
- 3391: [Usaco2004 Dec]Tree Cutting网络破坏
- 3404: [Usaco2009 Open]Cow Digit Game又见数字游戏
- GIF/PNG/JPG和WEBP/base64/apng图片优点和缺点整理
- 3400: [Usaco2009 Mar]Cow Frisbee Team 奶牛沙盘队
- 3409: [Usaco2009 Oct]Barn Echoes 牛棚回声
- 浅谈webp
- 3385: [Usaco2004 Nov]Lake Counting 数池塘
- 2761: [JLOI2011]不重复数字(平衡树)
- 无图片字体icon
- 数据结构(三):栈与队列
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法