对于一个初学者,所以我希望能与大家一起分享见解。有说错的、误导的地方,还请大家多多指点,我们可是说好的一起成长!让后来人能站在前人的肩膀上,走得更远,少走弯路。
三次握手
三次握手流程:
- 客户端发送一个SYN数据包序列号为seq1,请求建立TCP数据包,客户端进入SYN_SENT状态。
- 服务端收到数据包之后,发送一个ACK数据包确认号为SYN+seq1以及发送一个SYN数据包包含一个序列号seq2,服务端进入SYN_RCVD.
- 客户端收到数据包之后,回复一个ACK数据包序列号为SYN_seq1,确认号为SYN+seq2,双方进入ESTABLISH,开始数据传输。
为什么要三次握手呢?
主要是防止已失效的连接请求报文忽然传送到服务端,从而浪费资源去等待。
理解:当主机A向主机B请求数据连接的时候,由于网络原因,导致请求数据包滞留在网络中。此时主机A会认为发送的请求数据包失效,会再次发送请求数据包,连接–>数据连接–>关闭连接。如果"已失效的请求数据包",到达了B,如果是两次握手的话,B确认之后,就开始等待数据通信了。浪费了资源
1.第一次握手。
客户端发送数据包,服务端收到数据包。
得出结论:服务端接收能力正常,但是由于此时客户端未收到ACK确认包,所以不能确定客户端发送能力正常。
2.第二次握手
服务端发送数据包,客户端收到数据包。
得出结论,客户端发送能力接收能力正常。同理,不能确定服务端的发送能力是否正常。
3.第三次握手
客户端发送确认包。
得出结论,服务端的发送能力正常。
四次挥手
四次挥手流程
- 第一次挥手:客户端发送一个FIN=M,用来关闭客户端到服务器端的数据传送,客户端进入FIN_WAIT_1状态。(告诉服务端,没有数据需要发送了,服务器端还有数据没有发送完成,则不必急着关闭连接,可以继续发送数据)
- 服务器端收到FIN后,先发送ack=M+1,服务端进入CLOSE_WAIT,客户端就进入FIN_WAIT_2 状态,继续等待服务器端的FIN报文。(告诉客户端,你的请求我收到了,但是我还没准备好,请继续你等我的消息)。
- 第三次挥手:当服务器端确定数据已发送完成,则向客户端发送FIN=N报文,服务器端进入LAST_ACK状态。(告诉客户端,好了,我这边数据发完了,准备好关闭连接了。)
- 第四次挥手:客户端收到FIN=N报文后,就知道可以关闭连接了,但是他还是不相信网络,怕服务器端不知道要关闭,所以发送ack=N+1后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。
四次挥手的实质
TCP连接是双向传输对等的模式,就是说可以同时接受和发送数据。当一方发送数据完成,需要关闭连接的时候,发送FIN指令。对方收到后,会回复一个ACK,此时单向通道关闭。当接收方发送数据完成后,同样发送一个FIN,对方回复一个ACK。
拓展知识:
- 为什么建立连接的是三次握手,关闭连接的是四次挥手?
在建立连接的第二次握手时,服务端同时发送ACK和SYN报文发送给客户端。而由于TCP是双向发送数据,当其中一方数据发送完全之后,不能确定此时另外一方数据也发送完成,需要等待第三、四次握手。
- syn flood攻击
DoS攻击就是模仿合理的请求来占用服务资源,从而导致合法用户请求无法得到处理。而syn flood就是其中的DoS攻击的一种。
原理:向服务器发送大量的SYN包,服务器同时需要发送大量的ACK包用于回复,但黑客却不回复,使之一直保持在半开连接(SYN-RCVD)的状态。服务器每收到一个SYN包就会分配一个TCB,而每个TCB大小在280-1300字节,系统会耗尽资源无法处理正常请求。
防攻击方法
- 无效连接的监视释放。监视系统中的半开连接,当达到一个阈值时拆解这些连接,释放系统资源。但是,合法的半开连接也会被释放。
- 延缓TCB分配方法:Syn Cache技术,Syn Cookie技术
Syn Cache:当系统收到Syn数据包的时候,将半连接信息存储在hash表中,直到收到ACK再分配TCB。开销远比TCB小的多。
Syn Cookie:使用特殊的算法生成seq,由Dip,Dport,Sip,Sport等固定信息生成。当收到ACK时,重新计算一遍,相同则分配TCB,不需要开销。- 半连接队列满了。服务端在接收到SYN包的时候,就已经创建了request_sock结构,存储在半连接队列中。这些条目所标识的连接处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。对于应对SYN 过多的问题,linux提供了几个TCP参数:tcp_syncookies、tcp_synack_retries、tcp_max_syn_backlog、tcp_abort_on_overflow 来调整应对。