TCP及三次握手四次挥手

TCP是传输层重要的协议之一,我们要想了解这个协议,首先必须了解他的头部报文数据格式。



源端口和目的端口用于寻找发端和收端应用进程,这两个值加上IP首部中的源端IP地址和目的端IP地址唯一确认一个TCP连接

序号:32位的序号标志从TCP发送端到接收端发送的数据字节流,序号是本报文段发送数据的第一个字节序号,TCP传输流中,每一个字节编上一个序号,当我们建立一个新连接时候,SYN标志变为1.序号字段包含由这个主机选择的初始序号ISN。该主机要发送的数据第一个字节序号为这个ISN+1,因为SYN标志占用了一个序号呐!

确认序号:占4字节,是期望收到对方下次发送的数据的第一个字节的序号,也就是期望收到的下一个报文段的首部中的序号。只有ACK标志位为1时候确认序号才有效

数据偏移:也称为头部长度,4位长度,因为TCP头部包含可选项,所以TCP头部长度是变化的,4位头部长度最大值是1111,10进制也就是15,而数据偏移是以32位为长度单位,因此TCP首部最大长度为15*4=60字节

保留字段:原先6位已经使用2位,所以还剩4位,供往后使用

6位标志位:

    URG:将URG设置为1,紧急指针有效标识。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。

    ACK:取值为1代表确认序号字段有效,当ACK=0时,确认号无效

    PSH:标识接收方应该尽快将这个报文段交给应用层。接收到PSH = 1的TCP报文段,应尽快的交付接收应用进程,而不再             等待整个缓存都填满了后再向上交付,在处理telnet等交互模式时该标志总是被置位

    RST:重建连接标识。当RST=1时,表明TCP连接中出现严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重        新建立连接.

    SYN:同步序号标识,用来发起一个连接。SYN=1表示这是一个连接请求或连接接受请求。

    FIN:发端完成发送任务标识。用来释放一个连接。FIN=1表明此报文段的发送端的数据已经发送完毕,并要求释放连接。

窗口(16位):这个字段定义对方必须维持这个窗口值(以字节为单位),因为是16位,所以最大长度是65535字节,这个字节通常作为接收窗口(rwnd),并且由接收端确定。

数据校验和(16位):强制性字段,由发送端计算一个数值,由接收端接收计算,以此校验数据有效性

紧急指针(16位):只有当URG标志位为1时才有效,和序号字段的值相加表示紧急数据最后一个字节序号

选项:最常见的可选字段是最长报文大小,又称MSS,每个连接方通常在通信第一个报文段(为建立连接而设置SYN的那个段)中指明这个选项,指明本端所能接受的最大长度报文段

填充:可选,在一个连接建立和一个连接终止时,双方交换的报文段仅有TCP首部,如果一方没有数据发送,也使用没有任何数据的首部来确认收到的数据

三次握手:

我们使用tcpdump抓包工具来分析TCP的三次握手和四次挥手。关于tcpdump更详细介绍及使用可以参考其他文章


在linux下使用该命令,-S是获得ack的绝对值,如果不加该参数,第三次握手的ack为相对值+1,如下


-nn:Don’t convert protocol and port numbers etc. to names either.意思是不会将协议和端口号转换为我们易于理解的名字,比如他就不会把端口号转为我们认识的80数字

-c:后面跟数字,表示收到这么多封包之后就退出不再接收

然后是上面数据显示对应什么意思:

21:07:11 ---emmmm就是抓取的时间了

IP:协议

192.168.126.1.65465 > 192.168.126.130.80 源IP,源端口,目的IP,目的端口

FLAG[] --也就是上面所说的标志位了

S代表SYN,F代表FIN,R代表RST,P代表PSH,'.'代表以上四个标志位均为0

win 64240:代表数据窗口大小,windows下默认是64240

[mss 1460,nop,wscale 8,nop,nop,sackOK]代表的是可选字段,其中mss是最大可接受报文段

ok大致了解上面之后三次握手也就清楚了,上图吧



客户端将标志位SYN置1,随机产生序号seq=x,对应下图的1494255889,并且将该数据包发送给服务端,客户端随即进入SYN_SENT状态,等待服务端确认;

服务端收到数据包后由标志位SYN=1知道客户端需要建立连接,于是应答将SYN和ACK标志位都置为1,并随机产生一个序号seq=y,如下图2320960092,确认序号为第一次握手序号+1,即ack确认序号=x+1,如下图1494255890,服务端进入SYN_RCVD

服务端收到确认数据包后,检查ACK标志位是否为1,确认序号是否为x+1,如果正确则将ACK置为1,ack确认序号为y+1,即2320960093,随机序号为x+1,即1494255890(因为SYN占用一个序号并且服务端确认收到了,所以+1)

没有其他状况发生,经过上述三次握手就建立连接了。

如下图是wireshark抓包的三次握手过程


下面讲一下三次握手的相关状态:

LISTEN:表示服务器某个SOCKET处于监听状态,可以接受连接;

SYN_SENT:当客户端SOCKET执行连接操作时,他首先发送SYN报文段,因为进入SYN_SENT状态,表示客户端已经发送SYN报文;

SYN_RCVD:表示接收到了SYN报文,正常过程中,这个状态是服务器端SOCKET在建立TCP连接时的三次握手会话过程的一个中间状态,很短暂;

当然还有一种是同时打开连接的状况:


两个应用程序同时彼此执行主动打开,在这个过程中,每一方必须发送一个SYN,并且彼此知道对方端口号,而对于同时打开,它仅仅是建立一条连接。如上图,两端同时进入SYN_SENT状态,当每一方收的到SYN报文时进入SYN_RCVD,同时再发送SYN并对收到的SYN进行确认,当双方都收到SYN及相应ACK时连接建立。

在三次握手期间可能会被恶意用户使用一种叫SYN泛洪的方式攻击:

在三次握手过程中,服务端发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect),此时服务端处于SYN_RCVD状态,当收到ACK后,服务端转入ESTABLISHED状态。SYN攻击就是客户端在短时间内伪造大量不存在的IP地址,并向服务端不断地发送SYN包,服务端分配必要的资源,如创建TCB表和设置一些计时器等,这样子将会占用大量的资源,这个过程SYN报文数量很大,直接导致服务器资源耗尽瘫痪。

而抵御这种攻击方式也有很多吗,这里简述其中一种---SYN“小甜饼”(SYN Cookie),主机选择不去记忆序号,而是选择加密生成序号,将他放在出境段,如果三次握手成功之后,该序号(加1)才返回给主机,主机运用相同加密函数,重新生成正确序号。

四次挥手:

TCP终止一个连接需要经过四次挥手,这是因为TCP的半关闭造成的,我们知道TCP是一个全双工(数据在两个方向上能同时传递),所以需要每个方向单独进行关闭。


如图是wireshark抓包的四次挥手相关数据:


客户端A想要终止连接,于是将标志位FIN,ACK都置为1,序列号为1342869094,确认序号为服务器B发送的上一个序号+该数据包数据大小,随即进入FIN_WAIT_1状态

服务器B回应了一个标志ACK为1342869095,并且发送一个随随机序号seq=3148155110,随即进入CLOSE_WAIT状态,客户端A收到ACK确认报文后进入FIN_WAIT_2状态;

服务端B发送一个FIN报文,用来关闭服务端B到客户端A的数据传送,服务端B进入LAST_ACK状态。

客户端A收到FIN后,客户端A进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,服务端B收到验证后进入CLOSED状态,完成四次挥手。


下面说一下状态:

FIN_WAIT_1:当某一端(这里举例客户端)SOCKET在连接时想要主动关闭,就向服务端发送FIN报文,此时客户端就会进入此状态;

FIN_WAIT_2:这个状态下的SOCKET表示半连接,客户端要求close,但是服务端还有数据传给客户端,所以需要稍后关闭连接,于是发送ACK报文给客户端,客户端收到后进入此状态等待服务端FIN报文;

CLOSE_WAIT:等待关闭,查看自己是否有数据需要发送;

TIME_WAIT:表示收到了服务端的FIN报文,然后发送了ACK报文,就等待2MSL后就会进入CLOSED状态;

CLOSING:这种情况特殊,客户端和服务端同时发送了FIN报文

LAST_ACK:被动关闭的一方在发送FIN报文之后,最后等待对方的ACK报文,当接收到ACK报文之后没有意外也进入CLOSED状态了;


同时关闭:

在上图同时关闭时,两端都从连接状态变为FIN_WAIT_1,这样双方各自发送一个FIN,两个SYN经过网络传送到另一端,收到FIN后状态变为CLOSING,并发送最后的ACK,当收到最后的ACK时,状态变为TIME_WAIT

MSL是一个短文在被丢弃之前在网络中最长的生存时间,而TCP报文是以IP数据报在网络中传输,IP数据报的生存时间是TTL字段,当IP数据报丢失之后,封装在其中的TCP报文也就丢失,这里的LAST_ACK等待2MSL主要是有以下两个原因:

1、如果最后一个ACK报文段丢失了,服务器没有收到会以为是自己FIN报文丢失,所以会重传,但是如果客户端是传输ACK之后立刻关闭连接,那么就不会收到重传的FIN报文,服务端就不能关闭这个连接,2MSL是为了等待足够长的时间,使得当ACK丢失(一个MSL),还可以等到下一个FIN的到来(另一个MSL)

2、假设都已经确认关闭连接后,再很短的时间内使用相同SOCKET重新打开一个连接,而前一个连接的报文因为网络延迟因素就会发送给这个新的连接,这样这个报文就会被新的连接解释


下图是完整的状态转移图:


粗线代表客户端正常路径,粗虚线服务器端正常路径,细线是不长发生的事件

最后,我相信因为我目前接触的知识而此篇文章略有不足,如若有其他意见,虚心聆听!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值