tcp常用命令
了解tcp之前,先了解几个命令:
linux查看tcp的状态命令:
1)、netstat -nat 查看tcp各个状态的数量
2)、lsof -i:port 可以检测到打开套接字的状况
3)、 sar -n sock 查看tcp创建的连接数
4)、tcpdump -iany tcp port 9000 对tcp端口为9000的进行抓包
网络测试常用命令;
1)ping:检测网络连接的正常与否,主要是测试延时、抖动、丢包率。
但是很多服务器为了防止攻击,一般会关闭对ping的响应。所以ping一般作为测试连通性使用。ping命令后,会接收到对方发送的回馈信息,其中记录着对方的ip地址和ttl。ttl是该字段指定ip包被路由器丢弃之前允许通过的最大网段数量。ttl是ipv4包头的一个8 bit字段。例如ip包在服务器中发送前设置的ttl是64,你使用ping命令后,得到服务器反馈的信息,其中的ttl为56,说明途中一共经过了8道路由器的转发,每经过一个路由,ttl减1。
2)traceroute:raceroute 跟踪数据包到达网络主机所经过的路由工具
traceroute hostname
3)pathping:是一个路由跟踪工具,它将 ping 和 tracert 命令的功能与这两个工具所不提供的其他信息结合起来,综合了二者的功能
pathping www.baidu.com
4)mtr:以结合ping nslookup tracert 来判断网络的相关特性
5) nslookup:用于解析域名,一般用来检测本机的dns设置是否配置正确。
tcp状态分析
listening:侦听来自远方的tcp端口的连接请求。
首先服务端需要打开一个socket进行监听,状态为listen。
有提供某种服务才会处于listening状态,tcp状态变化就是某个端口的状态变化,提供一个服务就打开一个端口,例如:提供www服务默认开的是80端口,提供ftp服务默认的端口为21,当提供的服务没有被连接时就处于listening状态。ftp服务启动后首先处于侦听(listening)状态。处于侦听listening状态时,该端口是开放的,等待连接,但还没有被连接。就像你房子的门已经敞开的,但还没有人进来。
看listening状态最主要的是看本机开了哪些端口,这些端口都是哪个程序开的,关闭不必要的端口是保证安全的一个非常重要的方面,服务端口都对应一个服务(应用程序),停止该服务就关闭了该端口,例如要关闭21端口只要停止iis服务中的ftp服务即可。关于这方面的知识请参阅其它文章。
如果你不幸中了服务端口的木马,木马也开个端口处于listening状态。
syn-sent:客户端syn_sent状态:
再发送连接请求后等待匹配的连接请求:客户端通过应用程序调用connect进行active open.于是客户端tcp发送一个syn以请求建立一个连接。之后状态置为syn_sent. /*the socket is actively attempting to establish a connection. 在发送连接请求后等待匹配的连接请求 */
当请求连接时客户端首先要发送同步信号给要访问的机器,此时状态为syn_sent,如果连接成功了就变为established,正常情况下syn_sent状态非常短暂。例如要访问网站http://www.baidu.com,如果是正常连接的话,用tcpview观察iexplore.exe(ie)建立的连接会发现很快从syn_sent变为established,表示连接成功。syn_sent状态快的也许看不到。
如果发现有很多syn_sent出现,那一般有这么几种情况,一是你要访问的网站不存在或线路不好,二是用扫描软件扫描一个网段的机器,也会出出现很多syn_sent,另外就是可能中了病毒了,例如中了“冲击波”,病毒发作时会扫描其它机器,这样会有很多syn_sent出现。
syn-received:服务器端状态syn_rcvd
再收到和发送一个连接请求后等待对方对连接请求的确认
当服务器收到客户端发送的同步信号时,将标志位ack和syn置1发送给客户端,此时服务器端处于syn_rcvd状态,如果连接成功了就变为established,正常情况下syn_rcvd状态非常短暂。
如果发现有很多syn_rcvd状态,那你的机器有可能被syn flood的dos(拒绝服务攻击)攻击了。
syn flood的攻击原理是:
在进行三次握手时,攻击软件向被攻击的服务器发送syn连接请求(握手的第一步),但是这个地址是伪造的,如攻击软件随机伪造了51.133.163.104、65.158.99.152等等地址。服务器在收到连接请求时将标志位ack和syn置1发送给客户端(握手的第二步),但是这些客户端的ip地址都是伪造的,服务器根本找不到客户机,也就是说握手的第三步不可能完成。
这种情况下服务器端一般会重试(再次发送syn+ack给客户端)并等待一段时间后丢弃这个未完成的连接,这段时间的长度我们称为syn timeout,一般来说这个时间是分钟的数量级(大约为30秒-2分钟);一个用户出现异常导致服务器的一个线程等待1分钟并不是什么很大的问题,但如果有一个恶意的攻击者大量模拟这种情况,服务器端将为了维护一个非常大的半连接列表而消耗非常多的资源----数以万计的半连接,即使是简单的保存并遍历也会消耗非常多的cpu时间和内存,何况还要不断对这个列表中的ip进行syn+ack的重试。此时从正常客户的角度看来,服务器失去响应,这种情况我们称做:服务器端受到了syn flood攻击(syn洪水攻击)
established:代表一个打开的连接。
established状态是表示两台机器正在传输数据,观察这个状态最主要的就是看哪个程序正在处于established状态。
服务器出现很多established状态: netstat -nat |grep 9502或者使用lsof -i:9502可以检测到。
当客户端未主动close的时候就断开连接:即客户端发送的fin丢失或未发送。
这时候若客户端断开的时候发送了fin包,则服务端将会处于close_wait状态;
这时候若客户端断开的时候未发送fin包,则服务端处还是显示established状态;
结果客户端重新连接服务器。
而新连接上来的客户端(也就是刚才断掉的重新连上来了)在服务端肯定是established; 如果客户端重复的上演这种情况,那么服务端将会出现大量的假的established连接和close_wait连接。
最终结果就是新的其他客户端无法连接上来,但是利用netstat还是能看到一条连接已经建立,并显示established,但始终无法进入程序代码。
fin-wait-1:等待远程tcp连接中断请求,或先前的连接中断请求的确认
主动关闭(active close)端应用程序调用close,于是其tcp发出fin请求主动关闭连接,之后进入fin_wait1状态。/* the socket is closed, and the connection is shutting down. 等待远程tcp的连接中断请求,或先前的连接中断请求的确认 */
如果服务器出现shutdown再重启,使用netstat -nat查看,就会看到很多fin-wait-1的状态。就是因为服务器当前有很多客户端连接,直接关闭服务器后,无法接收到客户端的ack。
fin-wait-2:从远程tcp等待连接中断请求
主动关闭端接到ack后,就进入了fin-wait-2 。/* connection is closed, and the socket is waiting for a shutdown from the remote end. 从远程tcp等待连接中断请求 */
这就是著名的半关闭的状态了,这是在关闭连接时,客户端和服务器两次握手之后的状态。在这个状态下,应用程序还有接受数据的能力,但是已经无法发送数据,但是也有一种可能是,客户端一直处于fin_wait_2状态,而服务器则一直处于wait_close状态,而直到应用层来决定关闭这个状态。
close-wait:等待从本地用户发来的连接中断请求
被动关闭(passive close)端tcp接到fin后,就发出ack以回应fin请求(它的接收也作为文件结束符传递给上层应用程序),并进入close_wait. /* the remote end has shut down, waiting for the socket to close. 等待从本地用户发来的连接中断请求 */
closing:等待远程tcp对连接中断的确认
比较少见。/* both sockets are shut down but we still don‘t have all our data sent. 等待远程tcp对连接中断的确认 */
last-ack:等待原来的发向远程tcp的连接中断请求的确认
被动关闭端一段时间后,接收到文件结束符的应用程序将调用close关闭连接。这导致它的tcp也发送一个 fin,等待对方的ack.就进入了last-ack 。 /* the remote end has shut down, and the socket is closed. waiting for acknowledgement. 等待原来发向远程tcp的连接中断请求的确认 */
使用并发压力测试的时候,突然断开压力测试客户端,服务器会看到很多last-ack。
time-wait:等待足够的时间以确保远程tcp接收到连接中断请求的确认
在主动关闭端接收到fin后,tcp就发送ack包,并进入time-wait状态。/* the socket is waiting after close to handle packets still in the network.等待足够的时间以确保远程tcp接收到连接中断请求的确认 */
time_wait等待状态,这个状态又叫做2msl状态,说的是在time_wait2发送了最后一个ack数据报以后,要进入time_wait状态,这个状态是防止最后一次握手的数据报没有传送到对方那里而准备的(注意这不是四次握手,这是第四次握手的保险状态)。这个状态在很大程度上保证了双方都可以正常结束,但是,问题也来了。
由于插口的2msl状态(插口是ip和端口对的意思,socket),使得应用程序在2msl时间内是无法再次使用同一个插口的,对于客户程序还好一些,但是对于服务程序,例如httpd,它总是要使用同一个端口来进行服务,而在2msl时间内,启动httpd就会出现错误(插口被使用)。为了避免这个错误,服务器给出了一个平静时间的概念,这是说在2msl时间内,虽然可以重新启动服务器,但是这个服务器还是要平静的等待2msl时间的过去才能进行下一次连接。
closed:没有任何连接状态
被动关闭端在接受到ack包后,就进入了closed的状态。连接结束。/* the socket is not being used. 没有任何连接状态 */
tcp 连接断链分析
在官方的正式文档中,tcp/ip 协议簇也称为国际互联网协议簇。tcp/ip 协议簇是目前使用最为广泛的全球互联网技术,其分层结构如图 1 所示:
图 1. tcp/ip 协议簇分层结构
如图 1 所示,数据链路层主要负责处理传输媒介等众多的物理接口细节;网络层负责处理数据分组在网络中的活动,包括上层数据报文的分割、选路 phost2008-08-21t00:00:00 等;传输层则负责为两台主机提供端到端的通信;应用层将负责处理应用程序的特定细节。其中,ip 协议是网络层的核心协议,用来提供不可靠、无连接的数据传递服务;而 tcp 协议则处于传输层,其基于不可靠无连接的 ip 协议能够为两台主机提供面向连接的、可靠的通信。udp?
由于 tcp 是面向连接的协议,因此在两台主机通信之前,需要首先建立起一条连接。下面我们将简要介绍 tcp 连接的建立以及通信双方是如何保持已建立的 tcp 连接的。
tcp 连接的建立及保持
一个 tcp 连接的建立需要通过著名的“三次握手”来完成。下面的例子将直观给出一个 tcp 连接的建立过程。
在本文的下述描述中,客户端主机均为 testclient.cn.ibm.com(linux),服务器主机均为 testserver.cn.ibm.com(aix)。在 testclient 主机的一终端上执行 tcpdump –i eth0 host testserver 命令,启动 tcpdump 监听网络数据(其中,eth0 是客户主机与外部网络进行通信所使用的网卡);与此同时,在客户主机的另一个终端上执行下述命令: (root@testclient /)》telnet testserver。此时客户主机上 tcpdump 的输出如清单 1 所示。
清单 1. 创建一个 tcp 连接的三次握手
# tcpdump –s -i en0 host testserver
1 14:02:38.384918 ip testclient.cn.ibm.com.43370 》
testserver.cn.ibm.com.telnet: s 3392458353:3392458353(0) …
2 14:02:38.629578 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.43370: s 881279296:881279296(0) ack 3392458354 …
3 14:02:38.629592 ip testclient.cn.ibm.com.43370 》
testserver.cn.ibm.com.telnet: 。 ack 881279297 …
注意:我们删除了 tcpdump 输出结果中的部分无关信息。为了便于理解,我们将上述输出转换为实际序列图 2。
图 2. tcp 建立创建三次握手的实际序列
从图 2 中我们可以清楚地看到,在 testclient 与 testserver 之间建立连接时,要经过以下三次握手过程:
testclient 向 testserver 主动发送握手协议,报文序列号为 3392458353,大小为 1 个字节。
testserver 向 testclient 主动发送握手协议,报文序列号为 881279296,大小为 1 个字节;同时返回 ack 3392458354,作为对 testclient 发来的 3392458354 包的应答。
testclient 向 testserver 返回 ack 881279297,作为对 testserver 发来的 881279296 包的应答。
一个 tcp 连接在完成上述的三次握手之后便建立完毕;此后,连接的两端即可进行信息的相互传递。因此,tcp 连接可以认为是以两端 ip 地址和端口进行标识的一个通信信道,而 tcp 连接的建立就是向通信双方进行上述通信信道注册的过程。tcp 连接一旦建立,只要通信双方之间的中间结点(包括网关和交换机、路由器等网络设备)工作正常,那么在通信双方中的任何一方主动关闭连接之前,tcp 连接都将被一直保持下去。
tcp 连接的这种特性,使得一个长期不交换任何信息的空闲连接可以长期保持数小时、数天甚至数月。中间路由器可以崩溃、重启,网线可以被挂断再连通,只要两端的主机没有被重启,tcp 连接就可以被一直保持下来。
导致 tcp 连接断连的因素
理想状态下,一个 tcp 连接可以被长期保持。然而,在实际应用中,客户端或服务器端上维持的一个看似正常的 tcp 连接可能已经断连。tcp 连接主要受到两个方面的影响而导致断连:网络中间节点和客户端 / 服务器节点参与通信的两方节点?
在实际网络应用中,两个主机之间的通信往往需要穿越多个中间节点,例如路由器、网关、防火墙等。因此,两个主机之间 tcp 连接的保持同样会受到中间节点的影响,尤其是会受到防火墙(软件或硬件防火墙)的限制。防火墙是一种装置,有多种不同的实现方式(软件实现、硬件设备实现 或是软硬件相结合实现),它需要依据一系列规则对进出的信息流进行扫描,并允许安全(符合规则)的信息交互、阻止不安全(违反规则)的信息交互。防火墙的 工作特性决定了要维护一个网络连接就需要耗费较多的资源,并且企业防火墙常常位于企业网络的出入口,长时间维护非活跃的 tcp 连接必将导致网络性能的下降。因此,大部分防火墙默认会关闭长时间处于非活跃状态的连接而导致 tcp 连接断连。类似的,如果中间节点异常导致来自客户端关闭连接的请求无法传递到服务器端,也将导致服务器端的相应连接发生断连。
另一方面,对于一个 tcp 连接两端的主机而言,创建 tcp 连接需要耗费一定的系统资源。如果不再使用某个连接,那么我们总是希望进行通信的两个主机能够主动关闭相应的连接,以便释放所占用的系统资源。然而,如果 由于客户端出现异常 ( 例如崩溃或异常重启 ) 而导致连接未能正常关闭,这将导致服务器端的连接断连。
无论是客户端节点或是服务器端节点,断连的 tcp 连接已经不能传递任何信息,因此,维护大量断连的 tcp 连接将导致系统资源的浪费。这种系统资源的浪费可能并不会对客户端节点带来太大问题;然而,对于服务器主机而言,这可能会导致系统资源(尤指内存资源和 socket 资源)被耗尽而拒绝为新的用户请求提供服务。因此在实际应用中,服务器端需要采取相应的方法来探测 tcp 连接是否已经断连。
探测 tcp 连接断连的三种常用方法
探测 tcp 连接是否断连或是工作正常的原理比较简单:定期向连接的远程通信节点发送一定格式的信息并等待远程通信节点的反馈,如果在规定时间内收到来自远程节点的正 确的反馈信息,那么该连接就是正常的,否则该连接已经断连。依据该原理,目前常用的探测方法有以下三种。
应用程序的自我探测
应用程序本身附带探测其自身建立的 tcp 连接的功能。这种方法具有极大的灵活性,可以依据应用本身的特点选择相应的探测机制和功能实现。然而,实际应用中,大部分应用程序均没有附带自我探测的功能。
第三方应用程序的探测
此种方法就是在服务节点上安装相应的第三方应用程序来探测该节点上所有的 tcp 连接是否正常或是已经断连。该方法最大的不足就是需要所有支持探测的客户端能够识别来自该探测应用的数据报文,因此,实际应用中比较少见。
tcp 协议层的保活探测
最常用的探测方法就是采用 tcp 协议层提供的保活探测功能即 tcp 连接保活定时器。尽管该功能并不是 rfc 规范的一部分,但是几乎所有的类 unix 系统均实现了该功能,所以使得该探测方法被广泛使用。
接下来的部分,我们将重点讨论来自 tcp 协议层的保活探测方法。
类 unix 系统上的 tcp 连接保活定时器
tcp 连接的保活定时器可以在应用层实现,也可以在 tcp 中提供。这个问题存在争议,因此 tcp 连接的保活探测并不是 tcp 规范中的一部分。但为了方便,几乎所有类 unix 系统均在 tcp 中提供了相应的功能。
清单 2. 常见 unix 系统上的保活定时器
操作系统 保活定时器
aix# no -a | grep keep
tcp_keepcnt = 8
tcp_keepidle = 14400
tcp_keepintvl = 150
linux# sysctl -a | grep keep
net.ipv4.tcp_keepalive_intvl = 75
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_time = 7200
freebsd#sysctl -a | grep net.inet.tcp
net.inet.tcp.keepidle=…
net.inet.tcp.keepintvl=…
不同系统上的各参数的时间单位不尽相同。在 aix 上,tcp_keeidle/tcp_keepinit/tcp_keepintvl 的时间单位是 0.5 秒;而在 linux 上,net.ipv4.tcp_keepalive_intvl 和 net.ipv4.tcp_keepalive_time 的时间单位则为秒。并且,上述参数仅对运行在其上的服务器应用连接有效。
注:在 solaris 上可通过“ndd /dev/tcp \?”命令显示上述类似参数信息,而在 hp unix 上则可通过 nettune 或 ndd 命令进行查询。
由于所有类 unix 系统上均支持这种功能,因此,在接下来的部分中我们将基于 aix 系统具体讲述上述参数的意义和作用机制。
aix 中的 tcp 连接保活探测机制及原理
正如清单 2 中列出的一样,aix 上的保活探测机制由 4 个参数来控制,其具体意义见清单 3:
清单 3. aix 上的保活定时器控制参数
控制参数 参数说明
tcp_keepcnt关闭一个非活跃连接之前进行探测的最大次数,默认为 8 次
tcp_keepidle对一个连接进行有效性探测之前运行的最大非活跃时间间隔,默认值为 14400(即 2 个小时)
tcp_keepintvl两个探测的时间间隔,默认值为 150 即 75 秒
我们来看一个具体的例子。在 testserver 端(aix 主机)采用 tcp_keepidel=240(即 2 分钟):tcp_keepcnt=8:tcp_keepintvl=150(即 75 秒)的参数值;启动 testserver 上的 tcpdump 查看网络包的交互情况;从 testclient 端发起请求建立和 testserver 之间的一个 telnet 连接。在连接建立完成之后,拔出 testclient 端的网线并观察服务器端的数据输出(见清单 4)。
清单 4. telnet 连接在服务器端的 tcpdump 输出
1 # tcpdump -i en1 host testserver.cn.ibm.com
2 04:51:51.379716 ip testclient.cn.ibm.com.telnet.40621 》
testserver.cn.ibm.com.telnet: s 4097149880:4097149880(0)
3 04:51:51.379755 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: s 2543529892:2543529892(0) ack 4097149881
4 04:51:51.380609 ip testclient.cn.ibm.com.telnet.40621 》
testserver.cn.ibm.com.telnet: 。 ack 1
5 。。。
6 04:51:54.924058 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: p 676:696(20) ack 87
7 04:51:54.924909 ip testclient.cn.ibm.com.telnet.40621 》
testserver.cn.ibm.com.telnet: 。 ack 696
8 04:53:54.550192 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: 。 695:696(1) ack 86
9 04:55:09.550997 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: 。 695:696(1) ack 86
10 04:56:24.552053 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: 。 695:696(1) ack 86
11 04:57:39.552615 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: 。 695:696(1) ack 86
12 04:58:54.553446 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: 。 695:696(1) ack 86
13 05:00:09.554287 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: 。 695:696(1) ack 86
14 05:01:24.555117 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: 。 695:696(1) ack 86
15 05:02:39.555958 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: 。 695:696(1) ack 86
16 05:03:54.557282 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: 。 695:696(1) ack 86
17 05:05:09.559795 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.40621: r 696:696(0) ack 87
从清单 4 中可以看出,第 6 行的报文是本连接发送的最后数据,而第 7 行则是对第 6 行数据的确认。其后,该连接上没有任何数据交互,从而使得该连接一直处于非活跃状态。经过 2 分钟(第 8 行数据报时间 04:53:54 和第 7 行数据报时间 04:51:54 之差,即 tcp_keepidle 的值)的非活跃时间后,第 8 行是服务器端发起第一个保活探测数据报。由于服务器端没有收到客户端关于探测报文的相应,因此再经过 tcp_keepintvl 的时间间隔(75 秒)之后,第 9 行显示服务器端再次发起保活探测数据报。服务器端持续发送了 tcp_keepcnt 个探测报文(上面结果显示,在 aix 上是持续发送 tcp_keepcnt+1 个探测报文)之后,仍然没有收到来自客户端的任何回应,所以服务器在第 17 行向客户端发送复位报文同时在服务器端关闭了该连接。
需要注意的是,保活探测虽然通过发送 tcp 探测报文,但探测报文不会对正常的 tcp 连接产生任何影响。从清单 4 可以看出,第 8 行发送数据的 tcp 报文序号为 695 起始的 1byte 数据,而该数据在第 6 行已经发送并被客户端确认。对于正常状态的连接,客户端在收到探测报文之后将返回一个第 7 行所示的 ack 报文并借此向服务器端表明连接工作正常。
接下来,我们将通过一个实际的 tcp 断连的例子来分析上述机制对 tcp 连接保持的影响,并针对需要长时间保持 tcp 连接的应用提出两种可选的解决方案。
aix 上的 tcp 断连及数据分析
图 3. 出现 tcp 断连的网络拓扑结构示意图
所有服务器主机均划为一个局域网,并处于防火墙 b 之后。由于工作需要,来自工作区局域网的主机 testclient 需和服务器局域网内的 testserver 上的数据库使用 tcp/ip 建立一个连接,testclient 上的上层应用将通过该连接对 testserver 上的数据库进行相应操作。
在实际测试中,我们发现,在 testclient 和 testserver 均工作正常的情况下,testclient 上的客户端在事先没有收到任何异常信息的情况下,所持有的连接会出现非预期的断连现象(在试图通过连接进行数据库操作时,会被告知 connection is reset by foreign host 的错误)。
由于该现象不断出现,并且网络内的中间节点(路由器和交换机等)均工作正常,因此可以排除物理因素(如掉电、宕机等)的可能。为了便于分析断连原因,我们首先查看了 testserver 机器上的默认保活设置:
# no -a | grep keep
tcp_keepcnt = 8
tcp_keepidle = 14400
tcp_keepintvl = 150
testserver 上的 tcp_keepidle 为 14400,即 2 个小时。既然中间节点工作正常,为什么保活机制没有其作用呢?为了进行分析,我们采用 tcpdump 工具捕获 testclient 和 testserver 上的报文信息,见清单 5 和清单 6 所示。
清单 5. 服务器端的 tcpdump 数据输出
1 10:18:58.881950 ip testclient.cn.ibm.com.59098 》
testserver.cn.ibm.com.telnet: s 1182666808:1182666808(0) 。。。
2 10:18:58.882001 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.59098: s 3333341833:3333341833(0) ack 1182666809 。。。
3 10:18:58.882845 ip testclient.cn.ibm.com.59098 》
testserver.cn.ibm.com.telnet: 。 ack 1 。。。
4 。。。
5 10:19:03.165568 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.59098: p 1010:1032(22) ack 87 。。。
6 10:19:03.166457 ip testclient.cn.ibm.com.59098 》
testserver.cn.ibm.com.telnet: 。 ack 1032 。。。
7 12:19:05.445336 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.59098: 。 1031:1032(1) ack 86 。。。
8 12:19:05.445464 ip testclient.cn.ibm.com.59098 》
testserver.cn.ibm.com.telnet: r 86:87(1) ack 1031 。。。
清单 6. 客户端的 tcpdump 数据输出
1 # tcpdump -e -i eth0 host testserver.cn.ibm.com
2 10:18:55.800553 ip testclient.cn.ibm.com.59098 》
testserver.cn.ibm.com.telnet: s 1182666808:1182666808(0) 。。。
3 10:18:55.801778 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.59098: s 3333341833:3333341833(0) ack 1182666809 。。。
4 10:18:55.801799 ip testclient.cn.ibm.com.59098 》
testserver.cn.ibm.com.telnet: 。 ack 1 。。。
5 。。。
6 10:19:00.084662 ip testserver.cn.ibm.com.telnet 》
testclient.cn.ibm.com.59098: p 1010:1032(22) ack 87 。。。
7 10:19:00.084678 ip testclient.cn.ibm.com.59098 》
testserver.cn.ibm.com.telnet: 。 ack 1032 。。。
从清单 5 中可以看出,在该连接处于非活跃状态的时间达到 tcp_keepidle 设定的 2 小时时,服务器主机发出了第一个连接保活的探测报文(清单 5 中的第 7 行)。紧接着,服务器主机就收到了来自 testclient 的连接复位报文(清单 5 中的第 8 行)。之后,服务器便关闭了该连接(可以通过 netstat –ni 来查看)。然而,从清单 6 的 tcpdump 数据可以看出, testclient 端并未发送任何报文。那么,是谁向 testserver 发送了复位报文呢?
为了查看上述复位报文的发送者,同样采用上述 tcpdump 命令再次捕获服务器端和防火墙 b 的报文信息(注意:通常需要捕获防火墙主机上网络数据的出口网卡和入口网卡数据),结果显示,防火墙 b 在收到来自 testserver 的第一个探测报文之后就立刻向 testserver 发送了一个复位报文。
上述分析说明,在连接传递完最后一个交互数据之后到服务器端发送第一个保活探测之间,该连接已经被防火墙 b 终止;在此之后,基于该连接的任何报文传递在试图穿过防火墙的时候均会被防火墙丢弃并发送复位报文。
两种常用的解决方案
针对上述 tcp 断连现象,有两种常用的解决方案可供选择:
方案 1、延长防火墙终止非活跃的 tcp 连接的时间。例如,针对上述案例,可以调节防火墙设置,将时间设置为大于服务器端设定的 2 小时。
方案 2、缩短服务器端的 tcp 连接保活时间。缩短该时间的目的是为了在连接被防火墙终止之前发送保活探测报文,既可以探测客户端状态,又可以使连接变为活跃状态。
对于第一种方案而言,延长 tcp 连接的保持时间可能会导致防火墙性能的降低,尤其是在维持大量长时间处于非活跃状态的连接的情况下更是如此;而对于第二种方案,如果缩短服务器端的 tcp 连接保活时间,意味着会增加网络中的数据报文数而占用额外的网络带宽。因此,两种方案各有利弊,需要依据不同的实际应用情况进行选择。
总结
本文介绍了 tcp 连接的建立和保持的相关概念以及影响 tcp 连接保持的常见因素。给出了常见的类 unix 系统上 tcp 连接保活探测的相关配置参数,并基于 aix 借助 tcpdump 工具分析了一个实际的 tcp 断连的案例。最后,针对 tcp 断连的情况给出了两种可行的解决方案。
2019年手机市场中的关键词大盘点 这些元素值得我们关注
华为开发者大会讲了什么?看完你就懂了!
分布式存储与传统数据存储方式有什么区别
目前智慧城市的规划已经步入了理性化的发展阶段
dfrobotTurtle 3PA三轮小车机器人套件简介
tcp连接断链分析
RS232串行数据截取器的设计方案
零跑T03信息曝光 L2级辅助驾驶功能满足了年轻消费者的需求
小米6逆天配置,满血版骁龙835,4月16号正式发布
刘昊然实力带货,其代言新品vivo S6获年轻人喜爱
摩托车里程表可使用双极霍尔传感器AH402F,兼容SS360
Flash盘的FAT结构分析
电子标签辅助拣货系统在工业生产行业的未来可期
四通道RS-422差动线路驱动器,速率最高10Mbps,常用于电机编码器
奇数分频器的设计
江苏移动成功开通全球首个基于O-RAN架构的4G室分云基站
IGBT模块机械构造相关的电气特性参数
同惠LCR测试仪TH2817C+产品详解介绍
湖北电信抢抓进度,加速5G“新基建”
iPhone 12 助力,韩国 5G 用户在 10 月底接近 1000 万