概览
背景:
有部分数据状态变更时,需要通过回调地址通知客户内部系统更新数据状态。
网络链路如下所示:
云平台----->客户nginx前置机 (或其他防火墙)---->客户内网nginx ---->java应用
现象:
有些数据回调正常,有少量数据回调异常!客户本地数据无法更新状态,导致查询本地库数据状态错误。
拿具体的某个异常id查询相关日志发现以下现象
(1)云平台回调客户本地服务,云平台的回调服务日志中显示connection reset
(2)客户nginx的error日志显示 connect() failed (connection refused)
2024/10/12 16:59:29 [error] 87689#0: *197553200 connect() failed (111: Connection refused) while connecting to upstream, client: 47.94.142.197, server: localhost, request: "POST /gateway/call/signDataSynCall HTTP/1.1", upstream: "http://0.0.0.0:9999/回调接口url", host: "回调地址外网ip:端口"
(3)客户nginx打开了request_body开关,但异常回调的数据看不到accesslog的请求体,只能看到一个http请求 400的错误
分析过程
一 确认nginx配置
http 400的错误,搜网上大部分说请求参数的问题,比如请求体太大等,看nginx配置 最大500m没有超啊。
二 跳过nginx直接访问java应用接口
既然nginx到后台应用连接拒绝,直接通过内网curl -xpost方式是否能回调成功呢?
直接应用是成功的;说明java应用没问题。
三 内网nginx访问接口
直接内网访问nginx内网的ip+80端口也是通的。映射出的外网访问就不通,这很容易联想到是不是防火墙等其他拦截了?
问题到底出在哪儿里呢?最终还是找到我们运维老大帮忙,老大提供的建议是安全设备限制了…
看nginx配置 upstream除了正常的ip:端口外,还有个 0:端口 weight=1是什么鬼,大佬给去掉了,但问题依然存在。回调不通的订单还是回调不通,还是connection reset,但和之前不同的是:
nginx的error日志里连接拒绝的没有了,accesslog里的400也没有了,其实error里显示了连接拒绝的ip:端口 ,我还好奇0.0.0.0:9999怎么ip都是0,原来配置的upstream问题。
最终百思不得其解的我还是联系了客户的网络技术进行分析,触发接口调用,他进行抓包分析。
四 问题大揭秘
原来确实是被拦截了,客户使用了Discuz,这是一个门户的软件,有些版本有漏洞;回调的参数中字符串有的可能恰好和规则库里面Discuz!漏洞的字段吻合了导致被拦截
客户添加来源ip白名单,对于白名单里的回调内容,排除拦截放行!