TCP位于网络模型中的传输层,提供可靠的字节流服务,将大块数据分割成为以报文段(segment)为单位的数据包进行管理,目的是为了传送更大数据。
一个TCP连接中,仅有两方进行彼此通信,广播和多播不能用于TCP
TCP使用了校验和确认、重传极致保证可靠传输。要注意,TCP并不能保证数据一定会被对方收到,因为这是不能的。TCP能够做的事如果有可能就把数据递送到接收方,否则就(通过放弃重传并且终端连接这一手段)通知用户。因此准确说TCP也不是100%可靠的协议,它所能提供的是数据的可靠递送或故障的可靠通知。
为了确保数据传输的可靠性,TCP协议采取了三次握手(three-way handshaking)策略。握手过程衡中使用了TCP的标志——SYN(synchronize)和ACK(acknowledgement)。
所谓的三次握手,值得是建立一个TCP连接时,需要客户端和服务器总共发送三个包,握手过程如下:
(1)第一次握手
客户端首先发送一个带SYN标志(为1)的数据包给对方,指明客户端打算连接服务器的端口等信息。发送完成后,客户算进入SYN_SEND
状态
(2)第二次握手
服务器收到后,回送一个带有SYN/ACK标志的数据包以示传达确认信息,发送完成后服务端进入SYN_RCVD
状态
(3)第三次握手
最后客户端再回传一个带ACK标志的数据包,代表握手结束,客户端和服务端都进入ESTABLISED
状态,TCP握手结束。
DoS攻击就利用了三次握手的机制,客户端伪造不存在的IP作为源地址想服务器发送SYN报文,服务器收到之后会回应一个SYN+ACK报文,并且在自己的半连接队列中卫收到的SYN报文创建条目,等待客户端的ACK回应。
但是由于客户端采用了IP欺骗,服务端的ACK+SYN报文不会收到回应,就会等待、重传,直到重传次数超过系统规定的最大值后停止,并将这个SYN项目从半连接队列中删除。
如果在短时间内伪造大量不存在的IP地址,并快速发送大量这样的SYN保温给攻击目标,服务器的版连接队列就会被阻塞,系统资源被占用,正常的SYN请求得不到及时的处理,严重的还会硬气网络堵塞甚至系统瘫痪
TCP的连接断开需要发送四个包,因此称为四次挥手。客户端和服务端均可以主动发起挥手操作
(1)第一次挥手
假设客户端想要关闭连接,发送一个带有FIN标志的数据包给服务器,表明自己已经没有数据可以发送了,但是仍可以接受数据。
发送完毕后客户端进入FIN_WAIT_1
状态
(2)第二次挥手
服务端确认客户端的FIN包,发送一个ACK确认包,表明自己接收到了客户端关闭连接的请求,但是还没有准备好关闭连接,需要继续发送剩余的数据
(3)第三次挥手
服务端准备好关闭连接时,向客户端发送结束连接请求,发送带有FIN标志的数据包。发送完毕后,服务端进入LAST_ACK
状态,等待来自客户端的最后一个ACK
(4)第四次挥手
客户端接收到服务端的关闭请求,发送一个ACK确认包,进入TIME_WAIT
状态,等待可能出现的要求重传的ACK包
服务端接受到这个确认包后,关闭连接,进入CLOSED
状态。
客户端等待了某个固定时间之后,没有收到服务器端的ACK,认为服务器端已经正常关闭连接,于是自己也关闭连接,进入CLOSED
状态。
根本原因就是因为TCP是全双工通信的,双方都需要确保自己能被对方连接,以挥手为例:
(1)第一次挥手的FIN包,只代表主动方不会再发送数据报文,但是仍可以接受报文
(2)第二次挥手,被动方可能还有数据报文没发送完成,所以先发送ACK包,告诉对方“我已经知道想要断开连接的请求了”,这样主动方就不会再继续发送断开连接的请求(即FIN包)
(3)第三次挥手,被动方处理完数据报文了,发送FIN包,告诉主动方自己已经可以关闭了,发送FIN包后进入超时等待
(4)第四次挥手,如果主动方发送ACK报文,确认连接断开,双方释放连接。
之所以是四次,而不是三次,就是因为多了第二次挥手,这是被动方还没有做好断开连接的准备,还有数据要继续发送。