TCP断开时的状态与Linux nf_conntrack

简介:
题目有点大了,但是难免有一些愤怒!
我们的网关产品目前处在系统测试阶段,不太顺利,是太不顺利!各方面都在懈怠,包括我!我除了懈怠,还在找机会逆袭!顺便蔑视一下测试者,希望产生一种想象,即他发现的问题其实不是问题,而是因为他的无知所导致!就在昨天,机会来了,我便气扬了!
       很多人觉得我是下三层网络的专家,对于TCP之类的无权问津,但是我对TCP除了辱骂还是辱骂!因为它太复杂了,作为一个低层的设施,如果太复杂,应用层 的复杂空间便小了!编程的人,特别是socket编程的人,总是将IP以及网卡作为一个黑盒子,而着重看待TCP,他们对UDP是不屑一顾的,也不会关注 什么非合作UDP流量。这是搞通讯网络和人和编程的人的本质区别,毕竟分工不同。但是我也是从研究TCP开始的,起初我并无法触及路由器之类的东西,更不 晓得什么流量工程,可是到了后来当我懂了IP以后,我发现IP是多么的美妙,可以让人瞬间高潮!而TCP,就是一团乱麻,在产品系统测试的时候,一个 TCP的疑难杂症可以让一个研发人员折腾一下午甚至好几天,而这几天时间,测试人员爽了,没什么事,可以聊天,看新闻,这是多么悲哀,让人没法释怀!真 TMD想给测试人员上椅刑!旋转升降座椅一定会爆炸,菊花残,满地伤,花落人断肠!
       只可惜,昨天的事在我愤怒状态时,彻底灭了这种格局!事情是这样的。
客户端A:128.129.1.2
网关外网口(连接客户端):128.129.1.1
网关内网口(连接服务器):192.168.220.223
服务器:192.168.30.75

网关上做NAT的redirect转换,将访问服务器的流量重定向到本地的apache服务器,apache服务器行使正向代理功能(正向代理是一个重要概念,请深入理解)。规则如下:
iptables -t nat -A PREROUTING -d 192.168.30.75 -j REDIRECT --to-ports 80
多么简单的规则,然而多么痛的领悟。

测试人员,严格说是黑盒测试人员(非白盒),测试功能就算了,不影响业务就可以了,偏偏要搞什么抓包,关键是抓包还误会我们!问题如下:
连接的建立以及数据的传输,均经过了代理,但是连接的拆除却没有被NAT,直接forward出去了,导致192.168.30.75服务器直接接收到了源IP地址为128.129.1.2的数据包。这是怎么回事?!
       实际上,这是毫无影响的,只要应用程序能够坚持足够长的时间!
       我发现,这是服务器30.75主动断开的连接,也就是它主动发送了FIN,此后客户端发送了ACK,然而客户端迟迟没有发送自己方面的FIN,过了两分钟 才发送了FIN/ACK,此时连接只是单方面断开了。此时,在客户端没有发送FIN之前,它处在CLOSE_WAIT状态。由于目前的产品是基于前一个产 品构建的,在前一个产品中,我由于一些特殊的原因将conntrack的和TCP相关的timeout都减到了足够小,比如我将TCP的 conntrack的establish的timeout减少到了120秒(默认是5天),因此断开连接时的各状态timeout更小,因此在两分钟 内,conntrack早就删除了!
       此时客户端的FIN来了,由于conntrack已经删除,网关会为其建立一个新的conntrack吗?这要看有没有设置loose,我当然设置了,也 就是不再以syn为建立新conntrack的依据,按理说,Linux网关会创建一个新的conntrack,然而它携带了fin标志!这就意味着 Linux不会创建新的conntrack!因此数据包就直接forward了。但是这不会造成什么影响!因为携带fin的数据包拥有自己的控制通道 timeout期限。到期后会自动转换,这是和establish状态的截然不同!这是为什么呢?
       这样从TCP/IP的设计说起。有一种设计方案叫做带内控制,也就是控制通道和数据通道共享一条网络路径,TCP协议就是这种设计的典型,另一种就是 IP,比如ICMP就是IP的控制协议,然而你不能说IP不是一种完全的带内控制,它虽然和TCP有所区别,那只是因为它的无状态所致!
       TCP的控制通道用标志来区分,携带SYN,FIN的数据段都是控制段,Linux的conntrack对TCP的行为就是以这种控制标志为依据的,如果 来了一个establish的数据包-没有syn,没有fin,没有查找到conntrack,在设置loose标志的情况下,Linux为创建一个新的 conntrack项,然后对于控制信号,比如fin段,就不同了,Linux不会创建。然而这并不影响终端的结果,虽然由于Linux没有NAT成功导 致了数据不会正确到达服务器,可是由于已经fin了,终端会自动用timeout处理。
       但是一定要注意方向,这可能会稍微带来一些问题。如果主动发出的FIN被拦截,会有大问题吗?不会的,因为主动发出FIN的一端不管它会不会被拦截,都会更改状态,而被动关闭的那一端虽然收不到FIN,也会行使超时重传限制权利,虽然可能慢一点。

       持续饥饿!保持饥饿!



 本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1670776


相关文章
|
29天前
|
运维 Java Linux
Linux 下命令后台运行秘籍:无惧终端断开的魔法
本文详细介绍了在 Linux 系统下使命令不受终端断开影响、持续在后台运行的多种方法及其原理。包括使用 `nohup`、`setsid`、括号括起来、作业调度和 `screen` 等技巧,帮助读者提高工作效率,确保任务不被意外中断。
61 0
Linux 下命令后台运行秘籍:无惧终端断开的魔法
|
1月前
|
网络协议 Linux 网络性能优化
Linux C/C++之TCP / UDP通信
这篇文章详细介绍了Linux下C/C++语言实现TCP和UDP通信的方法,包括网络基础、通信模型、编程示例以及TCP和UDP的优缺点比较。
35 0
Linux C/C++之TCP / UDP通信
|
1月前
|
网络协议 Linux 网络性能优化
Linux基础-socket详解、TCP/UDP
综上所述,Linux下的Socket编程是网络通信的重要组成部分,通过灵活运用TCP和UDP协议,开发者能够构建出满足不同需求的网络应用程序。掌握这些基础知识,是进行更复杂网络编程任务的基石。
91 1
|
3月前
|
移动开发 监控 网络协议
在Linux中,如何查看 http 的并发请求数与其 TCP 连接状态?
在Linux中,如何查看 http 的并发请求数与其 TCP 连接状态?
|
3月前
|
监控 网络协议 Linux
在Linux中,如何实时抓取并显示当前系统中tcp 80 端口的网络数据信息?
在Linux中,如何实时抓取并显示当前系统中tcp 80 端口的网络数据信息?
|
3月前
|
存储 监控 网络协议
在Linux中,如何使用 tcpdump 监听主机为 192.168.1.1,tcp 端⼝为 80 的数据,并将将输出结果保存输出到tcpdump.log?
在Linux中,如何使用 tcpdump 监听主机为 192.168.1.1,tcp 端⼝为 80 的数据,并将将输出结果保存输出到tcpdump.log?
|
3月前
|
缓存 负载均衡 网络协议
Linux的TCP连接数量与百万千万并发应对策略
【8月更文挑战第15天】在Linux系统中,关于TCP连接数量的一个常见误解是认为其最大不能超过65535个。这一数字实际上是TCP端口号的上限,而非TCP连接数的直接限制。实际上,Linux服务器能够处理的TCP连接数远远超过这一数字,关键在于理解TCP连接的标识方式、系统配置优化以及应用架构设计。
464 2
|
3月前
|
网络协议 安全 Linux
在Linux中,tcp三次握⼿的过程及原理?
在Linux中,tcp三次握⼿的过程及原理?
|
3月前
|
域名解析 网络协议 Linux
在Linux中,我们都知道,dns采用了tcp协议,又采用了udp协议,什么时候采用tcp协议?什么 时候采用udp协议?为什么要这么设计?
在Linux中,我们都知道,dns采用了tcp协议,又采用了udp协议,什么时候采用tcp协议?什么 时候采用udp协议?为什么要这么设计?
|
3月前
|
网络协议 Linux
在Linux中,如何查看 http 的并发请求数与其 TCP 连接状态?
在Linux中,如何查看 http 的并发请求数与其 TCP 连接状态?
下一篇
无影云桌面