由TCP保活引起的业务访问故障案例
作者:易隐者 发布于:2012-12-7 15:18 Friday 分类:网络分析
1 故障环境
1.1 故障拓扑
故障发生的网络拓扑结构如下图所示:
1.2 业务报文交互路径
1,客户端通过网闸映射地址218.X.X.151访问内部业务服务器10.X.X.209;
2,客户端经过网闸后,源地址变为网闸内口地址10.X.X.160访问真实的业务服务器。
2 故障现象
故障现象主要表现为:
客户端访问业务服务器出现中断现象,并且故障基本都发生是在夜间12点以后;
第二天重启网闸后,业务访问恢复正常,但是到夜间12点左右业务连接会再次中断;
在业务访问出现中断以后,偶尔会不定时的可以成功进行连接,但是持续时间不长就再次中断;
仅此业务应用存在这个异常,其他的业务基本正常。
3 故障分析
3.1 分析思路
考虑到故障都发生在夜间12点左右,因此在网闸内外网口同时部署网络分析产品,对内外网口交互的报文进行长时间的捕获存储,第二天,我们分别选取故障发生时间内的报文进行关联分析和对比分析。
3.2 分析过程
3.2.1 异常出现时,网闸外口的报文交互情况
我们选取故障发生时,网闸外网口的交互报文进行查看,我们在“TCP会话”视图中,发现了大量交互报文少、流量小、收发报文特征明显的TCP会话,如下图所示:
我们选取其中任意一个TCP会话,查看其详细的报文交互情况,如下图所示:
我们可以清楚地看到,客户端与服务器映射的外网地址通过三次握手建立TCP连接之后,服务器映射地址立即向客户端发送了FIN报文,主动释放TCP连接,后续的带有应用字段的客户端报文到达后,服务器直接向客户端回应RST报文。
我们查看了其他的TCP会话的详细报文交互情况,基本与上述情况一样。由此来看,似乎是网闸主动发送FIN报文导致了业务应用出现异常,网闸为什么会在已经建立三次握手之后立即主动发送FIN报文呢?难道是服务器主动发送的FIN报文?或者是网闸的BUG导致网闸主动发送FIN报文?我们需要在内网端做个关联对比分析才能确定。
3.2.2 在网闸内口发现保活报文
当我们取故障时内网的报文时,发现内网在做捕包存储时出现异常,抓包工具在故障出现之前崩溃了,并未将故障发生时的网闸内口报文捕获保存下来,而由于时间紧急,我们没有机会再花费一天的时间去捕获内网的报文,这些故障现场的不确定性现象发生了,我们只能抓取当下的网闸内口报文进行辅助分析。
我们在网闸内网口抓包发现大量的特征明显的TCP会话,如下图所示:
这些TCP会话仅有几个报文的交互,不像正常的业务数据交互报文,我们选择其中一个TCP会话查看其具体的交互报文,如下图所示:
这是服务器发给客户端的报文,下面是客户端给服务器的报文:
结合这两个报文,我们可以肯定,这是一个TCP保活报文。这些仅交互2个报文的TCP会话是服务器发给客户端的TCP保活行为!
3.2.3合理推测
这些数量众多的保活行为的TCP会话,引起了我们的关注,那么是否是保活行为导致业务应用出现问题呢?保活的功能之一是维持已有TCP连接,关于TCP保活的详尽描述大家可参考我博客的文章《TCP保活(TCP keepalive)》。
TCP保活的这个特性很自然的让我们想到可能是TCP保活功能引起网闸连接表满从而导致业务异常。但是网闸作为一个网关类设备一般都支持几十万甚至数百万的连接数,在无异常攻击报文的情况下不至于24小时连接表就全部满了,并且也只有这个业务应用出现异常,其他应用都是正常的。
我们发现外网的客户端访问到内网时,其源地址全部转换为网闸内口地址10.X.X.160,至此我们恍然大悟:源IP、源端口、目的IP、目的端口、协议类型等五元组信息决定一个连接,而在网闸内口,源IP、目的IP、目的端口、协议类型都已经确定,只有源端口是变换的,而端口范围只能在0-65535之间,还要去除一些常用的端口,如此一来,网闸内口跟服务器之间能够建立的TCP连接数只能在65535以内!
在这种情况下,客户端访问业务服务器的TCP连接在24小时内达到近65535个,从而导致后续的客户端与业务服务器无法正常建立连接,引起业务访问故障。
至于故障后又能偶尔连接正常但很快再次异常的原因也很好解释,那就是网闸内口在维护如此众多的连接时,总会由于各种原因导致几个连接异常释放,如此一来则紧接着的业务访问连接会正常建立,但是一旦用完为数不多的几个连接后,后续的业务连接将再次出现异常。
整个交互过程涉及到的客户端、网闸外口、网闸内口、服务器的状态变化如下图所示:
3.2.4验证
我们建议用户在下班后手动清空网闸内口已有连接,观察夜间12点故障是否出现来验证我们的推测。后经用户反馈,在清空连接后夜间12点左右故障未再现,如此充分证明我们上述的推测是正确的。
3.3 分析结论
服务器端设置了TCP保活功能,对所有的TCP连接主动实行TCP保活探测,这导致网闸内口与服务器建立的TCP连接无法得到释放,在24小时以内,TCP连接数接近65535个,而此时客户端再次发起与服务器之间的业务连接之后,网闸内口已经无法再与服务器新建TCP连接,如此导致业务连接无法建立。
4 故障解决
在找到导致此业务故障的真正原因之后,我们就可以对症下药,通过任意选择如下几种方式之一来彻底解决这个故障:
1, 可以在服务器上关闭TCP保活功能;
2, 在网闸内口关闭源地址转换(SNAT)功能;
3, 将网闸内口TCP连接释放时间调整至小于服务器发送TCP保活的间隔时间,这样可以在服务器发送保活报文之前,让网闸内口提前释放该连接;
4, 网闸内口使用TCP连接复用功能,让大部分的外网客户端访问连接仅通过少量的内部连接实现正常的业务交互,而服务器则可以与网闸内口之间少量连接保持保活。
日历
最新日志
链接
分类
最新碎语
- 如果一个人想要做一件真正忠于自己内心的事情,那么往往只能一个人独自去做"——理查德·耶茨
2019-06-25 21:34
- 日后我们知道,真正的人生道路是由内心决定的。不论我们的道路看上去如此曲折、如此荒谬地背离我们的愿望,它终归还是把我们引到我们看不见的目的地。(茨威格《昨日世界》)
2019-03-16 21:27
- 如果你渴望得到某样东西,你得让它自由,如果它回到你身边,它就是属于你的,如果它不会回来,你就从未拥有过它。——大仲马《基督山伯爵》
2018-10-09 22:07
- 人生有两大悲剧:一个是没有得到你心爱的东西;另一个是得到了你心爱的东西。人生有两大快乐:一个是没有得到你心爱的东西,于是可以寻求和创造;另一个是得到了你心爱的东西,于是可以去品味和体验。——弗洛伊德
2018-09-25 18:06
- 一个人越有思想,发现有个性的人就越多。普通人是看不出人与人之间的差别的——布莱兹·帕斯卡尔
2018-08-30 18:44
存档
- 2020年11月(2)
- 2018年1月(1)
- 2017年12月(1)
- 2017年11月(6)
- 2017年6月(1)
- 2017年5月(1)
- 2017年4月(1)
- 2017年3月(1)
- 2016年11月(1)
- 2016年4月(1)
- 2015年7月(2)
- 2015年6月(1)
- 2015年5月(5)
- 2014年12月(1)
- 2014年11月(1)
- 2014年10月(1)
- 2014年8月(1)
- 2014年7月(1)
- 2014年6月(1)
- 2014年5月(1)
- 2014年4月(3)
- 2014年2月(2)
- 2014年1月(2)
- 2013年12月(1)
- 2013年11月(1)
- 2013年10月(2)
- 2013年9月(1)
- 2013年8月(1)
- 2013年7月(3)
- 2013年6月(2)
- 2013年5月(1)
- 2013年4月(3)
- 2013年3月(1)
- 2013年2月(2)
- 2013年1月(2)
- 2012年12月(11)
- 2012年11月(12)
- 2012年10月(12)
- 2012年9月(26)
- 2012年8月(29)
- 2012年7月(18)
- 2012年6月(2)
- 2012年5月(25)
- 2012年4月(16)
- 2012年3月(13)
- 2012年2月(6)