TCP/IP 协议族常用协议
应用层: TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 等等
传输层: TCP,UDP
网络层: IP,ICMP,OSPF,EIGRP,IGMP
数据链路层: SLIP,CSLIP,PPP,MTU
TCP 报头
FIN
: 表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志位的TCP数据包后,连接将被断开。这个标志的数据包也经常被用于进行端口扫描。SYN
:表示同步序号,用来建立连接。SYN标志位和ACK标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK=1;这个标志的数据包经常被用来进行端口扫描。扫描者发送一个只有SYN的数据包,如果对方主机响应了一个数据包回来,就表明这台主机存在这个端口;但是由于这种扫描方式只是进行TCP三次握手的第一次握手,因此这种扫描的成功表示被扫描的机器不很安全,一台安全的主机将会强制要求一个连接严格的进行TCP的三次握手;RST
:这个标志表示连接复位请求。用来复位那些产生错误的连接,也被用来拒绝错误和非法的数据包;ACK
:此标志表示应答域有效,就是说前面所说的TCP应答号将会包含在TCP数据包中;有两个取值:0和1,为1的时候表示应答域有效,反之为0;PSH
:这个标志位表示Push操作。所谓Push操作就是指在数据包到达接收端以后,立即传送给应用程序,而不是在缓冲区中排队;URG
:此标志表示TCP包的紧急指针,意为URG位有效的数据包,紧急处理的数据包需要接收端在接收到之后迅速处理;
TCP连接中的五个常见flag标志位
- FIN 表示关闭连接
- SYN 表示建立连接
- RST 表示连接重置
- PSH 表示有DATA数据传输
- ACK 表示响应
- URG 表示紧急指针
tcpdump
- F : FIN - 结束; 结束会话
- S : SYN - 同步; 表示开始会话请求
- R : RST - 复位;中断一个连接
- P : PUSH - 推送; 数据包立即发送
- A : ACK - 应答
TCP 三次握手
在建立 TCP 连接之前需要进行三次握手,以便于链接到服务器,如果要断开服务器需要进行四次挥手,具体流程如下。
- 第一次握手:Client将标志位
SYN置为1
,随机产生一个值seq=x
,并将该数据包发送给Server,Client进入SYN_SENT
状态,等待Server确认。 - 第二次握手:Server收到数据包后由标志位
SYN=1
知道Client请求建立连接,Server将标志位SYN和ACK都置为1
,ack=x+1
,随机产生一个值seq=y
,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD
状态。 - 第三次握手:Client收到确认后,检查标志位
ACK是否为1
,ack是否为x+1
,如果正确则将标志位ACK置为1
,ack=y+1
,并将该数据包发送给Server,Server检查 标志位ACK是否为1
,ack是否为y+1
,,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态
,完成三次握手,随后Client与Server之间可以开始传输数据了。
一个完整的三次握手也就是 请求 — 应答 — 再次确认
为什么需要三次握手,而不是二次握手?
主要是为了防止两次握手情况下已失效的连接请求报文段突然又传送到服务端,而产生的错误。举例如下:
Client向Server发出TCP连接请求,第一个连接请求报文在网络的某个节点长时间滞留,Client超时后认为报文丢失,于是再重传一次连接请求,Server收到后建立连接。数据传输完毕后双方断开连接。而此时,前一个滞留在网络中的连接请求到达了服务端Server,而Server认为Client又发来连接请求,若采用的是“两次握手”,则这种情况下Server认为传输连接已经建立,并一直等待Client传输数据,而Client此时并无连接请求,因此不予理睬,这样就造成了Server的资源白白浪费了;但此时若是使用“三次握手”,则Server向Client返回确认报文段,由于是一个失效的请求,因此Client不予理睬,建立连接失败。
第三次握手的作用:防止已失效的连接请求报文段突然又传送到了服务器。
第三次握手失败后怎么处理?
如果此时ACK在网络中丢失,那么Server端该TCP连接的状态为SYN_RECV,并且依次等待3秒、6秒、12秒后重新发送SYN+ACK包,以便Client重新发送ACK包,以便Client重新发送ACK包。
Server重发SYN+ACK包的次数,可以通过设置/proc/sys/net/ipv4/tcp_synack_retries
修改,默认值为5。
如果重发指定次数后,仍然未收到ACK应答,那么一段时间后,Server自动关闭这个连接。但是Client认为这个连接已经建立,如果Client端向Server写数据,Server端将以RST包响应,方能感知到Server的错误。
SYN 攻击
在三次握手过程中,服务器 发送 SYN-ACK 之后,收到客户端的 ACK 之前
的 TCP 连接称为半连接 (half-open connect)。此时服务器处于 SYN_RECV 状态,当收到 ACK 后,服务器转入 ESTABLISHED 状态.
SYN 攻击就是:攻击客户端在短时间内伪造大量不存在的 IP 地址,向服务器不断地发送 SYN 包,服务器回复 ACK 确认包,并等待客户的确认从而建立连接。由于源地址是不存在的,不会再发送 ACK 确认包,所以服务器需要不断的重发直至超时,这些伪造的 SYN 包将长时间占用未连接队列,正常的 SYN 请求被丢弃,目标系统运行缓慢,严重者引起网络堵塞甚至系统瘫痪。
SYN 攻击是一个典型的 DDOS 攻击。检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源 IP 地址是随机的,基本上可以断定这是一次 SYN 攻击
TCP 四次挥手
为什么要挥手,简单点来说就是既然建立了链接,那么肯定还要断开连接吖,连接总不能一直占用吧,这样多浪费系统该资源。
所谓四次挥手即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。下面让我们来看看四次挥手的流程。
- 1.第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
- 2.第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
- 3.第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
- 4.第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
这是因为服务端在 LISTEN 状态下,收到建立连接请求的 SYN 报文后,可以直接把 ACK 和 SYN 放在一个报文里发送给客户端。而关闭连接时,当收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即 close,也可以发送一些数据给对方后,再发送 FIN 报文给对方来表示同意现在关闭连接,因此,己方 ACK 和 FIN 一般都会分开发送。
为什么 TIME_WAIT 状态需要经过 2MSL (最大报文段生存时间) 才能返回到 CLOSE 状态?
-
Client的最后一个ACK报文在传输的时候丢失,Server并没有接收到这个报文。这个时候,Server就会超时重传这个FIN消息,然后Client就会重新返回最后一个ACK报文,等待两个时间周期,完成关闭。如果不等待这两个时间周期,Server重传的那条消息就不会收到。Server就因为接收不到Client的信息而无法正常关闭。
-
防止“已失效的连接请求报文段”出现在本连接中。在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段,都从网络中消失。这样就可以使下一个新的连接中不会出现这种就得连接请求报文段。
参考文章
TCP三次握手和四次挥手
TCP报头的标志位
TCP的CLOSE_WAIT 和 TIME_WAIT