欢迎您访问广东某某机械环保科有限公司网站,公司主营某某机械、某某设备、某某模具等产品!
全国咨询热线: 400-123-4567

新闻资讯

哈希游戏| 哈希游戏平台| 哈希游戏APP

HAXIYOUXI-HAXIYOUXIPINGTAI-HAXIYOUXIAPP

哈希游戏- 哈希游戏平台- 官方网站TCP经典异常问题探讨与解决

作者:小编2025-05-01 12:18:49

  哈希游戏- 哈希游戏平台- 哈希游戏官方网站主动方调用close()的时候,发现全局的tcp可用的内存不够了(这个可以sysctl调整tcp mem第三个参数),或,发现已经有太多的orphans了,这时候系统就是摆烂的意思:我也没辙了”,那就只能干脆点长痛不如短痛,结束吧。这个案例可以搜索(dmesg日志)“too many orphaned sockets”或“out of memory -- consider tuning tcp_mem”,匹配其中一个就容易中rst。

  当server端看到第三行的ack的时候几乎同时也看到了第四行的数据,详细来说,这时候server端在握手最后一个环节,会在socket的hash表中删除一个老的socket(我们叫req sk),再插入一个新的socket(我们叫full sk),在删除和插入之间的这短暂的几微妙发生的时候,server收第行的数据的时候需要去到这个hash表中寻找(根据五元组)对应的socket来接受这个报文,结果在这个空档期间没有匹配到应该找到的socket,这时候没办法只能把当时上层最初监听的listener拿出来接收,这样就出现了错误,违背了协议栈的基本的设计:对于listener socket接收到了数据包,那么这个数据包是非预期的,应该发送RST!

  这个问题根因同上:rcu+hash表的使用问题,在挥手阶段发起close()的一方竞争的乱序的收到了一个ack和一个fin ack触发,导致socket在最后接收fin ack时候没有匹配到任何一个socket,又只能拿出最初监听的listener来收包的时候,这时候出现了错误。但是这个原始代码中,是先插入新的sk再删除了老的sk,乍一听没有任何问题,但是实际上插入新的sk出现了问题,源码中插入到头部,这里需要插入到尾部才行!出现问题的情景如下图。

  在本例中,我发现依然是熟知的一幕,skb无法lookup寻找到对应的socket,此时我们要相信一定不会lookup算法出错,因为此算法仅仅是做简单的4元组的hash计算与匹配。所以追溯异常的skb和socket的四元组信息是头等事情,经过对比果然发现skb的端口信息未能成功被iptables转化为B port,所以使用了含有A port的四元组信息去找socket,而socket当初的建立是使用了B port,所以skb与sk的相遇就这么擦身而过了。

  client-gw-server的流程中,由于gw侧发送了一些unknown skb再加上client端发送了一些out-of-window的包,导致进入到server的netfilter阶段会被识别出来INVALID异常,这个异常被识别后直接清除netfilter保持的该有的流信息,继而异常的skb抵达DNAT阶段后无法转化端口(因为判断转化的流信息没有了),最终skb无法成功转化port端口号。

  这个是netfilter+DNAT的设计上的bug,我认为:无论是否有netfilter,都不应当是TCP的行为被改变,所以如果netfilter识别到了问题所在,1)要么忽视,直接传给TCP,交给TCP处理,2)要么丢弃,这样也能避免RST的发生。但是,就这么一个小小的细节上,我和社区的几个维护者拉锯战的battle了三百回合(链接:),可惜虽然有一个维护者ACK了我的补丁,但是另外的维护者考虑netfilter不适合用于丢包功能,所以让用户去使用iptables --log功能、检测出invalid异常包、继而用iptables配置主动丢弃。就凭这点,我认为严重违背了user friendly的初衷,这些应该是default默认功能才对。此时的我虽然表面打不过,但是在内心世界里很显然我battle赢了...