TPC报文格式
TCP/IP协议的详细信息参看《TCP/IP协议详解》三卷本。下面是TCP报文格式图:
上图中有几个字段需要重点介绍
- 序号: Seq序号,占32位,用来标识从TCP源端想目的端发送的字节流,发起方发送数据时对此进行标记。
- 确认序号: Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1
- 标志位:共6个,即URG,ACK,PSH,RST.SYN,FIN等,集体含义如下:
- URG:确认序号有效
- PSH:接收方应该尽快将这个报文交个应用层
- RST:重置连接
- SYN:发起一个新连接
- PIN:释放一个连接
需要注意的是:
(A)不要将确认序号Ack与标志位中的ACK搞混了。
(B)确认方Ack=发起方Req+1,两端配对。
TCP连接的三次握手
- 三次握手顾名思义就是TCP在建立连接时,需要客户端和服务器总共发送三个包,三次握手的目的就是连接服务器指定的端口,并同步连接双方的序列号和确认好,并奇偶啊换TCP窗口大小等信息。
- 图解如下
- 第一次握手: 客户端发送一个TCP的SYN标志位置1的包指明客户端打算连接的服务器的端口,以及初始序号x,保存在包头的序列号(Sequence Number)字段里面,此时客户端进入SYN_SEND状态,等待服务器B确认
- 第二次握手: 服务器返回确认包(ACK)应答,即SYN标志位和ACK标志位均为1,将确认序号设置为客户的ISN和加1即X+1。并设置发送序号为Y,此时服务器进入SYN_RECV状态
- 第三次握手: 客户端再次发送确认包ACK为1,此时的SYN标志位为0,并且把服务器发送过来的序号字段+1,即Y+1,放在确定字段中发送给对方,并且将发送序号的ISN+1,客户端和服务器端进入ESTABLISH状态完成三次握手。
为什么要三次握手:
- 三次握手完成了两个重要的功能,既要双方都做好发送数据的准备工作(双方都知道彼此准备好了),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。
- 假设把三次握手改成两次握手,client发送一个连接请求分组,server收到后返回确认应答分组,按照两次握手的协定,此时server认为连接已经成功建立,可以发送数据了,但是client在server应答被传输过程中丢失的情况下,client认为连接未能成功建立。只等待连接确认应答分组。而Server在发出的分组超时后,重复发送同样的分组。这样就形成了死循环。
三次握手有什么缺点?
答:在三次握手过程中,服务器发送SYN-ACK之后,收到客户端的ACK之前的TCP连接称为半连接(half-open connect).此时服务器处于Syn_RECV状态.当收到ACK后,服务器转入ESTABLISHED状态.
Syn攻击就是 攻击客户端 在短时间内伪造大量不存在的IP地址,向服务器不断地发送syn包,服务器回复确认包,并等待客户的确认,由于源地址是不存在的,服务器需要不断的重发直 至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
Syn攻击是一个典型的DDOS攻击。检测SYN攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源IP地址是随机的,基本上可以断定这是一次SYN攻击.在Linux下可以如下命令检测是否被Syn攻击
netstat -n -p TCP | grep SYN_RECV
一般较新的TCP/IP协议栈都对这一过程进行修正来防范Syn攻击,修改tcp协议实现。主要方法有SynAttackProtect保护机制、SYN cookies技术、增加最大半连接和缩短超时时间等.
但是不能完全防范syn攻击。
三次握手抓包入下:
四次挥手
- 四次挥手即断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开,在socket编程中,这一过程可以由服务端或者客户端任意一方执行close来触发,整个过程如下
- 由于TCP连接时是全双工的,因此每个方向都要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN知识意味着这一方向没有数据流动了,即不会再收到收据,但是这个TCP连接荏苒能够发送数据,知道这个方向也发送了FIN,首先进行关闭的一方将执行主动关闭,而另外一方则执行被动关闭。上图描述即使如此。
- 第一次挥手:client发送一个FIN,用来关闭client到Server的数据传输,client进入FIN_WAIT_1状态
- 第二次挥手:Server收到FIN后,发送一个ACK给client,确认序号为收到的序号+1(与SYN相同,一个FIN占用一个序号),server进入CLOSE_WAIT状态
- 第三次挥手:Serve发送一个FIN,用来关闭Server到client的数据传送,Server进入LAST_ACK状态
- 第四次挥手:client收到FIN后,client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,server进入CLOSED状态,完成四次挥手
- 实际使用中还会遇到同时关闭的情况,流程如下
同时挥手
流程和状态在上图中已经很明了了,在此不再赘述,可以参考前面的四次挥手解析步骤。
为什么连接是三次握手,断开连接是四次挥手
这是因为服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接受数据。己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以发送一些数据给对方后,在发送FIN报文给对方表示同意关闭连接,因此己方ACK和FIN一般会分开发送。