TCP/IP三次握手具体过程?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TCP/IP三次握手具体过程?相关的知识,希望对你有一定的参考价值。

TCP/IP三次握手具体过程?
还有全扫描,半扫描,秘密扫描,三种扫描分别利用三次握手的哪个?

一、TCP握手协议

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接。

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。

完成三次握手,客户端与服务器开始传送数据,在上述过程中,还有一些重要的概念:

未连接队列:在三次握手协议中,服务器维护一个未连接队列,该队列为每个客户端的SYN包(syn=j)开设一个条目,该条目表明服务器已收到SYN包,并向客户发出确认,正在等待客户的确认包。这些条目所标识的连接在服务器处于Syn_RECV状态,当服务器收到客户的确认包时,删除该条目,服务器进入ESTABLISHED状态。
Backlog参数:表示未连接队列的最大容纳数目。

SYN-ACK 重传次数 服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传,如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。注意,每次重传等待的时间不一定相同。

半连接存活时间:是指半连接队列的条目存活的最长时间,也即服务从收到SYN包到确认这个报文无效的最长时间,该时间值是所有重传请求包的最长等待时间总和。有时我们也称半连接存活时间为Timeout时间、SYN_RECV存活时间。
参考技术A 端口扫描,这种入侵检测方法大家想必都经常用到,但是你对这些方法的基本原理又了解多少呢?
首先,你可以选择都种工具,本人喜欢nmap for linux,但不是常在linux下混,毕竟还是windows方便点,呵呵,高手别笑我哦!
下面谈下端口扫描方式!大体可以分为两种,TCP扫描和秘密扫描
TCP扫描最常见的有两种
全扫描、半扫描
说到TCP,就一定要谈3次握手
客户端——SYN——>服务器
客户端<——SYN+ACK——服务器
客户端——ACK——〉服务器
这就是3次握手,也就是全扫描的全过程,但是,由于这种方式要与目标建立连接,所以一定会被记录下来,所以,这种扫描方式是不隐密的,容易暴露身份。
所以,就有了半扫描这种扫描方式,会发送一个SYN包给目标服务器,然后如果对方在特定端口监听,就会回复一个ACK+SYN,如果主机在活动,但没有监听特定端口,就会回一个RST包。这种方法并没有完成3次握手,所以一般不会被主机记录。
下面,我们就抛开TCP协议,看看有没有办法通过其他方式扫描!
说到文件传送,大家最先想到的就应该是FTP协议了,那么,能不能通过FTP扫描呢?
答案是可以,出于设计上的需要,当FTP客户端要以主动模式请求传送数据时,服务器必须要建立一个返回到客户机端口上的连接客户端发出PORT命令,以IP和端口作为参数,如果参数中有另一台主机的IP数据,服务器将与这台主机相连。
我们就利用FTP的这种特点来执行代理端口扫描。
还有FIN,ident,XMAS扫描等等,由于时间关系和其他种种原因,我现在就不讲了,lz有兴趣,可以加我大家一起探讨~
参考技术B 三次握手? 参考技术C 深刻解放大会 参考技术D http://wenku.baidu.com/view/89ee5a3e580216fc700afd71.html###

TCP三次握手详解,滑动窗口,网络包路由过程,全连接队列,半连接队列

众所周知,网络分层有传统的OSI七层模型和后来的基于TCP/IP的四层模型,这里面各层的作用如下:

那么在一次网络的传输过程中具体的流程是怎么样的,我们先从一个数据包的传输说起(以TCP为例):

  1. TCP协议根据上层应用提供的信息生成TCP报文
    TCP包头

  2. TCP报文在交由下面的IP层(网络层)进行处理,委托IP模块将TCP报文封装成网络包发送给对应的接收端:
    IP协议里需要有源IP和目标IP,这个在整个的传输过程中都是不变的
    对于源IP来说,就是发送者的IP,但是对于一台服务器来说,可能存在多个网卡,即存在多个IP,那么应该用哪一个呢?
    这时候就需要用到路由表,在linux中可以通过route -n来获取,然后会将目标IP地址和路由表中每条记录的子网
    掩码进行与运算,得到与目标IP在同一个网段的路由(从这里看,通过与子网掩码进行与运算,能够判断IP是否属于同一个网段
    这样我们就能够知道从哪个网卡将我们的数据发送出去
    这样我们就将IP报文生成
    IP包头

  3. 生成了IP报文之后接下来还需要在IP报文中增加MAC地址信息,进行实际的两端出书,那么如何获取呢 ?
    发送方的MAC地址比较简单,在上面的步骤我们确定好了哪块网卡发送数据实际上就能够获取到对应网卡的MAC地址
    但是对于原目标MAC地址则比较麻烦,只要我们填写上MAC地址,那么以太网就会将数据发送到对应的MAC地址的机器上
    我们需要确定需要发送给哪个MAC地址?根据上一步的了解,我们通过路由表知道需要将数据发往哪里,通过和路由表
    中的条目匹配,我们知道发送给路由表中哪个IP,那么我们如何知道这个IP对应的MAC地址呢?
    这个时候通过ARP协议能够帮我们知道一个IP地址对应的MAC地址
    ARP协议会在以太网中通过广播形式对以太网中所有设备发出请求询问,这个IP是谁的,收到ARP的请求后,设备判断
    这个IP和自己是否在同一个网段,如果在同一个网段,则给出响应并返回自己的MAC地址
    通过ARP,我们能够获取到目标MAC地址,
    mac包头

  4. 上述IP网络包生产之后接下来需要通过网卡将数据从本机发送出去,网卡会将IP网络包的二进制数据转换成
    电信号。网卡从IP模块接收到数据之后会将数据复制到网卡的缓存区中,接着会在其开头加上报头和起始 帧分界符,在末尾加上用于检测错误的帧校验序列FCS。

  5. 交换机。 交换机的作用是将网络包原样转发到目标设备,交换机工作在MAC层,是二层网络设备,和网卡不同,交换机的端口不具有 MAC 地址
    交换机将包存入缓冲区后,接下来需要查询一下这个包的接收方 MAC 地址是否已经在 MAC 地址表中有记录 了。
    交换机的 MAC 地址表主要包含两个信息: 一个是设备的 MAC 地址,另一个是该设备连接在交换机的哪个端口上 。
    接下来交换机就会将数据原样发送到对应设备的对应端口上。
    如果地址表中找不到对应的MAC地址,那么可能是因为具有该地址的设备还没有向交换机发送过包,
    或者这 个设备一段时间没有工作导致地址被从地址表中删除了,交换机无法判断应该把包转发到哪个端口,只能将包转发到除了源端口之外的所有端口
    上,无论该设备连接在哪个端口上都能收到这个包。
    交换机会将接收到的电信号转换为数字信号,然后判断FCS是否正确,如果没问题,则通过上述逻辑,发送到对应的地址上

  6. 路由器。 经过交换机之后,数据包现在来到了路由器这里,路由器是基于IP协议涉及的,是三层网络设备,路由器每个端口 都具有MAC地址和IP地址,而交换机是基于以太网设计的,交换机的端口不具有MAC地址
    路由器接收到数据后会将电信号转换为数字信号,然后会丢掉包中的MAC头部MAC 头部的作用就是将包送达路由器,其中的接收方 MAC 地址就是路由器端口的 MAC 地址。因此, 当包到达路由器之后,MAC 头部的任务就完成了,于是 MAC 头部就会被丢弃。
    然后查询路由器中的路由地址进行发送操作,首先,我们需要根据路由表的网关列判断对方的地址。
    如果网关是一个 IP 地址,则这个IP 地址就是我们要转发到的目标地址,还未抵达终点,还需继续 需要路由器转发。
    如果网关为空,则 IP 头部中的接收方 IP 地址就是要转发到的目标地址,也是就终于找到 IP 包头 里的目标地址了,说明已抵达终点。
    然后通过ARP协议获取到需要发送的MAC地址,然后将包中的目标MAC地址设置为获取到的MAC地址

网络包完成后,接下来会将其转换成电信号并通过端口发送出去。这一步的工作过程和计算机也是相同
的。
发送出去的网络包会通过交换机到达下一个路由器。由于接收方 MAC 地址就是下一个路由器的地址, 所以交换机会根据这一地址将包传输到下一个路由器。
接下来,下一个路由器会将包转发给再下一个路由器,经过层层转发之后,网络包就到达了最终的目的
地。

在网络包传输的过程中,源 IP 和目标 IP 始终是不会变的,一直变化的是 MAC 地 址,因为需要 MAC 地址在以太网内进行两个设备之间的包传输

这里介绍几个概念:

MTU(Maximum Transmission Unit,MTU),最大传输单元

以太网和802.3对数据帧的长度都有一个限制,其最大值分别是1500和1492个字节。链路层的这个特性称作MTU。如果IP层有数据包需要传送,但是这个数据包的大小比MTU还大,则在IP层会进行分片传输,让传输的数据包小于MTU,然后在目的端的IP层进行组装。
在IP层,即使丢失一个分片数据都要重传整个数据包,因为IP层没有超时重传机制,需要由上层TCP层来实现

MSS(Maxitum Segment Size)最大分段大小

MSS是TCP每次传送数据段的最大大小,TCP在进行数据包的传输的时候,会按照MSS来切分数据包,一般MSS<MTU,这样到达IP层的时候一般不需要IP层在进行切分。

在这里插入图片描述

TCP三次握手连接

在这里插入图片描述

由于TCP是面向连接的,因此在使用TCP之前必须先建立TCP的连接,而TCP建立连接则是通过三次握手来建立连接
在这里插入图片描述

  • 一开始,客户端和服务端的状态都是CLOSED,服务端开启TCP服务,绑定端口并监听该端口,处于LISTEN状态
    -

  • 客户端会随机初始化序号( client_isn ),将此序号置于 TCP 首部的「序号」字段中,同时把SYN 标志位置为 1 ,表示 SYN 报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于 SYN-SENT 状态。
    在这里插入图片描述

  • 服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号( server_isn ),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn +1 , 接着把 SYN 和 ACK 标志位置为 1 。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。
    -

  • 客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。

  • 服务器收到客户端的应答报文后,也进入 ESTABLISHED 状态。

三次握手过程中第三次是可以携带数据的

一旦完成三次握手,双方都处于ESTABLISHED状态,此时连接已经建立完成,客户端和服务端就可以相关发送数据
TCP建立需要三次握手的主要原因如下:

  1. 阻止重复历史连接的初始化(主要原因)
  2. 同步双方的初始序列号
  3. 避免资浪费
  • 阻止重复历史连接。我们知道网络中的数据传输是不固定的,有的包先发但是可能会比后发的数据包晚到,有的包后发,但是会比先发的数据包早到。三次握手条件下,在网络不好的情况下,旧的SYN报文比新的SYN报文先到,此时服务端会返回一个SYN+ACK报文给客户端,客户端收到报文后根据上下文判断这是一个历史连接(通过序列号或者超时),客户端会发送RST给服务端终止这次连接,如果是两次握手,则无法判断

  • 同步双方初始序列号。 TCP传输过程中,客户端和服务端都必须维护一个自身的序列号,序列号是TCP可靠传输的一个保证,序列号的作用如下:

  1. 接收方可以根据序列号去除重复数据
  2. 接收方可以根据序列号顺序接收
  3. 发送方可以根据返回的ACK中判断哪些数据是对方已经收到的
  • 避免资源浪费。如果只有两次握手,那么客户端发送SYN后,服务端返回ACK,但是由于网络堵塞,客户端没有收到,这时候客户端只能再发SYN,而服务端不知道客户端是否收到自己发送的ACK,只能没收到一个SYN就建立一个连接,这会造成服务端有多个连接,造成冗余

TCP四次挥手断开连接

在这里插入图片描述

  1. 客户端准备关闭连接,发送FIN报文,将TCP首部FIN标志位设置为1,然后客户端进入FIN_WAIT_1状态
  2. 服务端收到客户端的FIN报文之后,向客户端返回ACK报文,服务端进入CLOSED_WAIT状态
  3. 客户端收到服务端的ACK报文之后进入FIN_WAIT_2状态
  4. 服务端将所有的数据发送完成之后,也向客户端发送FIN报文,服务端进入LAST_ACK状态
  5. 客户端收到服务端的FIN报文之后,返回ACK给服务端,客户端进入TIME_WAIT状态
  6. 服务端收到ACK报文后,进入CLOSED状态,到这里服务端完成了连接的关闭
  7. 客户端经过2MSL时间之后,进入CLOSED状态,到这里客户端完成了连接的关闭

TCP可靠性传输

TCP在建立连接的时候,有一个重要的功能就是同步双方的序列号,而TCP称为可靠性传输,其中一种方式就是通过序列号和确认应答机制。
在TCP中当目标主机接收到数据后,会返回一个确认应答消息给到源主机,表示已经收到消息,但是大家需要注意的是,网络环境错综复杂是不稳定的,如果在传输的过程中,数据丢失了,应该怎么处理?
为此TCP针对数据包丢失的情况,采用了重传机制来解决,常见的重传机制有如下几种:

  • 超时重传
  • 快速重传
  • SACK
  • D-SACK
超时重传

超时重传的原理就是源主机发送一个数据包之后会设定一个定时器,到达指定的时间后没有收到目标主机返回的确认应该报文ACK之后,重新发送该数据。
那么这个时间多长呢?
RTT (Round-Trip Time) 表示一个数据包在网络中从一端到另一端需要用的时间超时重传时间是以 RTO (Retransmission Timeout )来表示,RTO是通过算法计算而来,是一个动态变化的值,具体大家可以百度看下Linux采用的算法

快速重传

快速重传不是通过时间来判断,而是通过数据,通过一幅图大家就明白了:
在这里插入图片描述

  1. 源主机发送报文Seq=1的时候,目标主机返回ACK=2
  2. 源主机发送Seq=2,但是由于未知原因,该报文丢失了,目标主机未收到
  3. 源主机发送Seq=3,目标主机收到,但是期望的是Seq=2,目标主机还是返回ACK=2
  4. 源主机发送Seq=4,目标主机收到,还是返回ACK=2
  5. 源主机发送Seq=5,目标主机收到,还是返回ACK=2
  6. 源主机收到了三个ACK=2,知道目标主机Seq=2尚未收到,在定时器过期之前,重传Seq=2
  7. 目标主机收到了Seq=2,也收到了Seq=3,Seq=4,Seq=5,这时候目标主机返回ACK=6

但是上述也有问题,就是这个重传是重传Seq=2还是重传Seq=2,Seq=3,Seq=4,Seq=5呢?因为这时候源主机并不知道ACK=2到底是哪个数据包的确认信息,因此有了SACK算法
在发送数据的时候,会在TCP头部选项里增加SACK信息,这样在给源主机返回ACK信息时,源主机通过SACK信息,就能够知道哪些数据接收到了,哪些数据没有接收到,然后只重传丢失部分的数据

Duplicate SACK又称 D-SACK主要使用了SACK来告诉源主机有哪些数据被重复发送了。

TCP滑动窗口

我们知道,在网络中都是一个网络包一个网络包的传输,如果每次发送一个数据包就返回一个ACK应答,这种效率会特别低。TCP中引入了窗口的概念,在一个窗口中,发送端可以不等接收端相应继续发送数据,知道发送窗口大小为0,必须等待接收端相应才能继续发送。TCP中窗口的实现实际上是开辟了一段缓存空间,将发送的数据缓存在这,如果收到确认应答则会将该数据从缓存中移除。

接收端在返回相应给发送端的时候会告诉发送端自己还有多大的缓冲区能够接收数据,发送端可以根据接收端的处理能力来发送数据

TCP流量控制,拥塞控制

TCP流量控制: 发送方不能无脑的往接收方发送数据,需要考虑接收方是否能够处理过来,如果一直发送但是接收方处理不过来,则会导致重发,导致网络流量的无端浪费,基于此,TCP提供了流量控制,让发送方根据接收方的接收能力来控制发送的数据量
拥塞控制 在网络出现拥堵时,如果发送方继续发送大量数据,会导致数据的延时、丢失等,这时候TCP又会重传,而重传会加重网络的负担,导致更大的延时、丢包,如果一直进行下去则会不断恶性循环,因此TCP中设置了拥塞控制,避免发送发的数据填满整个网络空间。

TCP全连接队列、半连接队列

在这里插入图片描述

当我们在进行TCP编程的时候,服务端会开启通过bind -> listen来监听对应端口的连接,当客户端第一次请求连接发送SYN信号后,服务端收到该请求且验证请求有效,则会将这个连接放入到半连接队列
当三次握手成功之后,将半连接队列中连接放入到全连接队列中。
服务端程序调用read系统命令,从全连接队列中取走已经建立好的连接并获得这些连接的句柄,后续的发送接收消息,服务端通过持有的连接的句柄进行操作。
不管是全连接队列还是半连接队队列都有最大的长度限制,超过限制,TCP会直接丢弃或者返回RST

参数名称说明
tcp_syncookies当TCP半连接队列SYN队列满之后,开启tcp_syncookies,连接校验通过会直接进入到accept队列
tcp_abort_on_overflow当TCP全连接队列满之后的策略,0:如果全连接队列满了,服务器端会丢掉客户单发送的ACK,1服务端会发送一个RST给客户端,表示废弃这次连接
TCP全连接队列大小设置取值是 somaxconnbacklog之间的最小值,cat /proc/sys/net/core/somaxconn,backlog在TCP程序中指定
tcp_syn_retries当客户端发送SYN包之后等待服务端返回SYN_ACK,如果客户端很长时间没有收到SYN+ACK报文,会重发SYN包,重发的次数由该参数控制,cat /proc/sys/net/ipv4/tcp_syn_retries
tcp_fastopnTCP Fastopen,可以减少三次握手的时延,当第一次握手成功后,后续再次握手客户端会携带有第一次握手中服务端返回的cookie,后续不用在进行三次握手,直接连接,0 关闭 1 作为客户端使用 Fast Open 功能 2 作为服务端使用 Fast Open 功能 3 无论作为客户端还是服务器,都可以使用 Fast Open 功能 。 cat /proc/sys/net/ipv4/tcp_fastopen
tcp_orphan_retriesTCP四次挥手中,当主动方第一次发哦送FIN报文后出与FIN_WAIT1状态,如果没有收到ACK时,会重发FIN报文,重发次数由该参数控制,默认0表示8次,cat /proc/sys/net/ipv4/tcp_orphan_retries
tcp_max_orphans系统中孤儿连接的最大数量,当连接一直处于FIN_WAIT1状态的时候,为孤儿连接,如果大于改参数,新增的孤儿连接不会走四次挥手,直接发送RST,cat /proc/sys/net/ipv4/tcp_max_orphans
tcp_fin_timeout控制连接处于FIN_WAIT2的时长,默认是60S,cat /proc/sys/net/ipv4/tcp_fin_timeout
tcp_max_tw_buckets当处于TIME_WAIT状态的连接超过该参数时,新关闭的连接不在经历TIME_WAIT,直接关闭,cat /proc/sys/net/ipv4/tcp_max_tw_buckets
tcp_tw_reuse,tcp_timestamps仅适用于客户端,复用处于TIME_WAIT的连接,前提是打开tcp_timestamps
tcp_wmemTCP发送缓冲区大小,单位是字节echo "4096 16384 4194304" > /proc/sys/net/ipv4/tcp_wmem ,第一个表示动态范围的最小值,4K,二个是初始默认值,86K,第三个是动态范围的最大值,4M
tcp_rmemTCP接收缓冲区大小,单位是字节echo "4096 87380 4194304" > /proc/sys/net/ipv4/tcp_rmem 第一个表示动态范围的最小值,4K,二个是初始默认值,86K,第三个是动态范围的最大值,4M
tcp_moderate_rcvbuf开启接收缓冲区自动调节,发送缓冲区是自动调节的echo 1 > /proc/sys/net/ipv4/tcp_moderate_rcvbuf
tcp_memTCP内存大小,单位是页,默认一页是4KB,echo "382806 510409 765612" > /proc/sys/net/ipv4/tcp_mem ,,第一个表示TCP内存小于该值时不需要自动调节,在第一个和第二个值之间时,调节接收缓冲区大小,大于第三个值时,不在为TCP分配新内存,此时无法建立新的连接.千万不要在 socket 上直接设置 SO_SNDBUF 或者 SO_RCVBUF,这样会关闭缓冲区的动态调整功能。
tcp_window_scaling不限制默认TCP窗口64KB大小,开启滑动窗口因子,echo “1” > /proc/sys/net/ipv4/tcp_window_scaling

以上是关于TCP/IP三次握手具体过程?的主要内容,如果未能解决你的问题,请参考以下文章

三次握手及四次挥手在TCP/ip模型的哪一层进行的?最好有理由~

TCP/ip 的三次握手 和 socket 是啥关系?

TCP 三次握手(SYN,SYN-ACK,ACK)

TCP协议的三次握手漏洞问题!

TCP/IP三次握手四次挥手过程

干货超具体讲解TCP/IP三次握手与四次挥手