网络知识点 OSI 开放式互联参考模型
七层协议
1物理层
- 解决:机器1向机器2发送比特流,机器2接收比特流。
- 定义:物理设备的标准,网线类型,设备接口类型,各种传输介质的传输速率
- 作用:传输比特流010101数据,将比特流转化为电流强弱信号,到达后再转化为0101机器码-> 数模转换和模数转换。网卡定义在这一层
2数据链路层
- 解决:传输比特流的过程中解决数据传输不完整的可能
- 定义:如何格式化数据以进行传输以及对物理介质的访问
- 作用:错误检测和纠正,确保数据传输的可靠性,将比特数据组成了帧,交换机工作在这层,对帧解码,根据帧中的数据发送到网络接收方
3网络层
- 解决:找到目标节点选择最佳路径,帧数据点对点通信经过多个节点
- 定义:将网络地址翻译成物理地址并决定将发送方路由到接收方,通过综合考虑选择优先权和最佳路径,TCP/IP 路由器属于网络层,数据为数据包
- 作用:将数据包切割为一个一个段落进行发送。
4传输层
- 解决:数据丢失要不要重传,每个段落要按顺序达到么,解决了主机间的数据传输,传输质量的问题
- 定义:传输协议,流量控制,速率,传输顺序, TCP、UDP
5 会话层
- 解决:建立和管理应用程序间的通信,解决不同系统之间通信语法的问题,再表示成网络能理解的方案格式化,方案也因为网络的类型不同而不同,
- 定义: RPC 远程过程调用协议在此层
7 应用层
发送方发送的数据接收方是不知道他的字节数组和内容格式的
- 解决:规定发送方接收方使用固定的消息头,规定头的组成,消息体的长度,用来正确解析发送的数据,应用从网络中接收到的数据。
- 定义:TCP/IP 协议对应的 HTTP HTTPS 协议
模型参考
发送方解释数据,分段,分组成帧解释成比特流,通过电缆发送到目标方在向上解析传递。
TCP/IP 模型
OSI概念七层实现:TCP/IP 四层模型
TCP/IP 模型关注应用程序实现,OSI模型在协议开发之前设计的,具有通用性
TCP/IP 解释
TCP 和 IP 协议
单独的 TCP IP 协议-
TCP/IP通信时用到的协议群-网ji协议群
TCP,UDP 都属于 TCP/IP 协议
- OSI模型注重通信协议必要的功能是什么
- TCP/IP模型更强调在计算机上实现协议应该开发哪种程序
一层层包裹在一层层解套出来
TCP 三次握手
传输控制协议TCP
- 面向连接、可靠、基于字节流的传输层通信协议
- 将应用层的数据流分割成报文段并发送给目标节点的TCP层
- 数据包有都有序号,对方接收到则发送ACK 确认,未收到则重传
- 使用校验和检验数据在传输过程中是否有误
TCP 报文头
- 传输中使用协议端口号,ip地址+协议+端口号产生唯一标识网络进程, 也成为套接字 socket。
source port 原端口,destination port 目的端口 - Sequence Number 序号字段占4字节
对每个字节标识,比如一段报文序号107携带100个字段,下一个报文段就是 107 + 100 = 207 开始 - Acknowledgment Number 期望收到对方下个字节的序号
例如B收到A 301序号200字节大小的报文段,B接收500字节,B发送给A501 ACK Number,告诉A期望下次接收501序号的报文段
TCP Flage
- URG: 紧急指针标志 0忽略
- ACK:确认序号标志1
- PSH:push 标志 1就有push 将数据尽快交给应用程序而不是缓存区排队
- RST:重置连接标志
- SYN:同步序列号1,用户建立连接过程
- FIN:finish标志,用于释放连接
三次握手
握手是为了建立连接,TCP 三次握手的流程
第一次握手
- B服务器创建传输控制块TCP 时刻准备接收客户端进程发送的请求,进入 listen 状态
- A客户端创建传输控制块TCP向服务器发送连接请求报文 - sent 报文段,SYN同步序号1,seq报文段序号正整数值
- A客户端进入 SYN-SENT 同步已发送状态,发送的称为 sent 报文段, 不能携带数据,但是要消耗掉一个 seq 序号,这便是第一次握手
第二次握手
- B服务器接收到请求后如果同意则发送确认接收报文
- 接收报文包含 SYN1 ACK1 两个字段,而为自己的缓存初始化一个序列号 seq 确认报文序号为 y,ack期待报文序号为 x + 1,因为第一次握手 seq为x
- 进入 SYN-RCVD 同步收到状态,这时候报文要不能携带数据需要消耗一个 序号
第三次握手
- TCP 客户端进程A 收到确认报文后还要给服务进程一个报文
- 确认报文 ACK=1,seq=x+1, ack=y+1
- 此时TCP 连接建立,客户端进入ESTAB-LISHED 已建立连接的状态,此时ACK报文段可以携带数据(不携带则不消耗序号),之前不可携带数据
- 服务端进入 SETAB-LISHED 状态 双方就可以通信了。
Wireshark 抓包理解 TCP 三次握手
win 参数为滑动窗口,进行流量控制
总结三次握手
在 TCP/IP 协议中, TCP 采用三次握手建立可靠的连接。
- 第一次握手
建立连接时客户端发送 SYN 包 syn=1 到服务器并进入 SYN_SEND 状态 等待服务器确认 - 第二次握手
服务器收到 SYN 包,必须给客户端发送确认包 ACK ack=1,同时发送一个 SYN syn=k,也就是 SYN+ACK 包,此时服务器进入 SYN_RECV 状态 -
第三次握手
客户端收到服务器的 SYN+ACK 包后向服务器发送确认包 ACK ack=k+1,此包发送完毕后客户端和服务端后进入 ESTABLISHED 状态,三次握手完毕
为什么要三次握手建立连接
- 初始化 sequence number 的初始值
通信双方要通知双方 seq num,用来以后通信的序号,保证应用层接收到的数据不会因为网络传输问题导致乱序,TCP用序号拼接数据,而且还要发送确认报文 ack
SYN 超时隐患
首次握手出现
原因
- server 收到 client 的SYN 回复 SYN-ACK的时候未收到 ACK 确认
- server 不断重试直至超时,linux 默认63秒等待才断开
目前,Linux下默认会进行5次重发SYN-ACK包,重试的间隔时间从1s开始,下次的重试间隔时间是前一次的双倍,5次的重试时间间隔为1s, 2s, 4s, 8s, 16s, 总共31s, 称为指数退避,第5次发出后还要等32s才知道第5次也超时了,所以,总共需要 1s + 2s + 4s+ 8s+ 16s + 32s = 63s, TCP才会把断开这个连接。由于,SYN超时需要63秒,那么就给攻击者一个攻击服务器的机会,攻击者在短时间内发送大量的SYN包给Server(俗称SYN flood攻击),用于耗尽Server的SYN队列。
恶意攻击 SYN Flood
发送SYN 而不回应,每次都等待63秒,让正常连接不能处理
最基本的DoS攻击就是利用合理的服务请求来占用过多的服务资源,从而使合法用户无法得到服务的响应。syn flood属于Dos攻击的一种。
如果恶意的向某个服务器端口发送大量的SYN包,则可以使服务器打开大量的半开连接,分配TCB(Transmission Control Block), 从而消耗大量的服务器资源,同时也使得正常的连接请求无法被相应。当开放了一个TCP端口后,该端口就处于Listening状态,不停地监视发到该端口的Syn报文,一 旦接收到Client发来的Syn报文,就需要为该请求分配一个TCB,通常一个TCB至少需要280个字节,在某些操作系统中TCB甚至需要1300个字节,并返回一个SYN ACK命令,立即转为SYN-RECEIVED即半开连接状态。系统会为此耗尽资源。
防护措施
Syn Cache
服务端在收到SYN报文时,在一个专用HASH表中保存这种半连接信息,直到收到正确的回应ACK报文再分配TCB。这个开销远小于TCB的开销。还需要保存序列号。Syn Cookie
1.使用对方的IP、端口、己方IP、端口的固定信息,生成 Sequence Number
2.SYN 队列满后,通过 tcp_syncookies 参数回发 SYN cookie
3.若为正常连接则 client 会回发 SYN cookie,直接建立连接分配 TCB 。
4.攻击者不会回复所以,正常的回复了SYN cookie 就可以在队列外直接建立
建立后 client 出现故障
- 保活机制
向对方发送保活探测报文,如果未收到响应则继续发送
尝试次数达到保活探测数仍未收到响应则中断
连接队列
在外部请求到达时,被服务程序最终感知到前,连接可能处于SYN_RCVD状态或是ESTABLISHED状态,但还未被应用程序接受。
对应地,服务器端也会维护两种队列,处于SYN_RCVD状态的半连接队列,而处于ESTABLISHED状态但仍未被应用程序accept的为全连接队列。如果这两个队列满了之后,就会出现各种丢包的情形。
sync queue (半连接队列)
- sync queue 的作用
三次握手中,第一次握手服务端收到客户端的 SYN 包后,把相关信息放到半连接队列中,同时进行第二次握手回复客户端 SYN + ACK - 当 sync queue 满时
该队列保存服务器已收到客户端的 SYN 包,并向客户发出确认,正在等待客户的确认包。这些所标识的连接在服务器处于 SYN_RECV 状态,当服务器收到客户的确认包时,删除该 SYN 包的信息,服务器进入 ESTABLISHED 状态。
accept queue (全连接队列)
accept queue 作用
第三次握手时服务器收到客户端的 ack,如果这时全连接队列没满,那么从半连接队列拿出相关信息放入到全连接队列中,否则按 tcp_abort_on_overflow 指示的执行。当 accept queue 满时
如果全连接队列满了并且 tcp_abort_on_overflow 是 0 直接丢弃该ACK,服务器会进行过一段时间再次进行第二次握手发送 SYN + ACK 给客户端,如果客户端超时等待比较短,就很容易异常。
tcp_abort_on_overflow 1 表示发送 RST(重置连接) 通知客户端
TCP 四次挥手
为了终止连接, 要发送四个包
1挥手
- server client 都处于 ESTAB-LISHED 状态
- client 主动关闭
- 客户端发送连接释放报文并且停止发送数据
- 释放报文 FIN=1,seq=u u是最后一个字节的序号+1, 不携带数据也要消耗序号
- 客户端进入 FIN-WAIT-1
2挥手
- server 接收到释放报文 发出确认报文
- 确认报文 ACK=1,seq=v,ack=u+1
- 进入CLOSE-WAIT状态(重要)半关闭状态,客户端不发送数据,但server 发送的数据 client 还是可以接收
3挥手
- client 接收到 server 的确认报文进入 FIN-WAIT-2 状态, 等待 server 发送释放连接报文(等待第三次挥手)
- 此时 client 还要接收 server 发送的最后数据
- server 发送完最后数据后,发送连接释放报文,FIN=1,ACK=1,seq=w,ack=u+1
- server 进入 LAST-ACK 最后确认状态
4挥手
- client 收到释放报文后必须发送确认报文,ACK=1,seq=u+1,ack=w+1
- client 进入 TIME-WAIT 状态,这时候 client TCP 连接还没释放,必须等待 2MSL(最长报文段寿命liux30s) 才释放
- server 收到 client 的确认报文后立即关闭,server 比client 稍早点关闭
四次挥手总结
- 第一次挥手
客户端发送一个 FIN 序号 seq=u,用来关闭 客户端到服务器的数据传送,客户端进入 FIN_WAIT_1 状态 - 第二次挥手
服务器收到 FIN 后,发送一个 ACK 给客户端,确认序号为收到的序号 ack=u+1 FIN 也占一个序号 seq=v,服务器进入 CLOSE_WAITE状态, 这时服务器要把剩下的数据发送完毕 - 第三次挥手
服务器剩余数据发送完毕,发送一个 FIN seq=w ack=u+1,用来关闭服务器到客户端的数据传送,服务器进入 LAST_ACK 状态 - 第四次挥手
客户端收到 FIN 后,客户端进入 TIME_WAIT 状态,接着发送一个 ACK 给服务器,确认序号为收到序号 ack=w+1和 seq=u+1,服务器进入 CLOSED 状态,客户端等待 2MSL 时间进入 CLOSED 结束。
client TIME_WAIT 状态
等待 2MSL 时间
- 保证让被动关闭方有足够的时间收到ACK包(确认报文)
- 如果被动关闭方没有收到则重新发送 FIN 包,一来一回刚好 2MSL
- 避免新旧连接混淆, 有的路由器缓存的连接跟新连接混淆
为什么要四次挥手才断开连接
双工是允许双向发送,发送方和接收方都需要 FIN 报文和 ACK 报文
各自需要2次挥手,但是一方是被动的,才看上去是4次挥手
服务端出现大量 CLOSE_WAIT
客户端一直请求,但是返回时异常的
当对方发送 FIN 报文后,应用没有返回 ACK
对方关闭 socket 连接,我方忙于读写,没有及时关闭
检查代码,释放资源代码
检查配置,处理请求的线程配置