关于Linux内核4.12之前版本中, tcp_tw_recycle开启后NAT环境总是出问题的分析
1 2 3 4 5 6 7 8 9 | isn = TCP_SKB_CB(skb)->when;<br> if (!isn){<br>......<br> if (tmp_opt.saw_tstamp && tcp_death_row.sysctl_tw_recycle && (dst = inet_csk_route_req(sk, &fl4, req)) != NULL && fl4.daddr == saddr) { if (!tcp_peer_is_proven(req, dst, true )) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); goto drop_and_release; } } |
补充:这里有条件 !isn, 没有特别懂这个isn是干嘛的,(如果非要牵强的解释,貌似isn是上面提到的初始化序列号, 但是吧,又觉得不太对,因为tcp_skb_cb里when后面的解释是用来计算 RTT的(路由往返时间)感觉这东西跟时间戳有关??(当然,在connect中,SEQ非要算时延,也是可以的吧? +1 = 4MS,不过乱糟糟的,wireshark里面有个raw_seq,又不知道是咋整出来的?所以理论上,不为0的可能性很大,所以这个判断条件,是会命中的),不过肯定不是IS SYNC标识,因为 TCP_SKB_CB中,有个TCP_FLAGS的属性,这个应该是那些各种SYN ACK FIN之类的标志)
这里可以大概看出来,如果数据包中的option属性中,包含了tstamp(也就是如果client如果开了时间戳),且本地(服务端)tw_recycle属性也开启了,就从 inet_csk_route_req中取出 f14, 这里的inet_csk_route_req,有介绍说是出路由缓存,大概意思就是跟本次连接有关的上次传输(或者连接???)的信息吧???
然后紧接着比较了f14的目标IP和本次请求的来源IP, 按照出路由,那么目标IP肯定是NAT的外网IP, 而本次请求的来源IP,自然也是NAT的IP
那么,只看IP地址相同,就会进入tcp_peer_is_proven,这里面会检查时间戳,自然就会出现如果时间戳有差异,会被API服务器丢弃连接的情况了。
这个问题,其实很多人都在网上有分析过,但是,看了不少文章,很少有人把per-host PAWS检查明确的解释为只检查两次连接的IP,就会继续检查时间戳。
当然,这个问题,也是因为自己对内核的一些逻辑实在不清楚导致的,也许大家的知识储备中,对这种情况十分清楚,导致文章里,也仅是一笔带过。
这个分析里,依然很多细节都不清楚:
PAWS具体是为了解决什么问题?
SEQ到底如何递增到最大值?
INET_CSK_ROUTE_REQ函数的具体功能和逻辑是什么?
这些留待之后有时间,再继续深入了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2015-01-29 nginx源码学习资源
2015-01-29 成为高级程序员的10个步骤
2015-01-29 编译cvaux错误的原因