OSI七层网络模型和TCP/IP协议介绍

339 阅读15分钟

介绍

开放系统互连参考模型 (Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。其目的是为异种计算机互连提供一个共同的基础和标准框架,并为保持相关标准的一致性和兼容性提供共同的参考。这里所说的开放系统,实质上指的是遵循OSI参考模型和相关协议能够实现互连的具有各种应用目的的计算机系统。

OSI七层模型

image.png

TCP/IP协议族

image.png

网络层协议 IP:用来确定网络中唯一的一台计算设备(类似电话号码或者通讯地址),可以用来确定网络传输的源地址目标地址

传输层 TCP:面向连接,两台机器建立连接后(三次握手)才开始传输数据, UDP:把数据直接发出去,不管对方是否接收,可能出现丢包现象,属于不可靠的传输。对于传输要求速度快,丢包影响不大的可以使用(视频通话等)

image.png

地址和端口号

MAC地址

物理地址,也叫局域网地址,由网络设备制造商生产时写在硬件(网卡)内部,MAC地址共48位(6个字节)。前24位由IEEE(电气和电子工程师协会)决定如何分配,后24位由实际生产该网络设备的厂商自行制定。

IP地址 IP地址分为:IPv4和IPv6。用来识别 TCP/IP 网络中互连的主机和路由器。IP地址基于逻辑,比较灵活,不受硬件限制,也容易记忆。

端口号 端口号用来识别同一台计算机中进行通信的不同应用程序。因此,它也被称为程序地址。一台计算机上同时可以运行多个程序。传输层协议正是利用这些端口号识别本机中正在进行通信的应用程序,并准确地将数据传输。

image.png

为什么端口号有65535个?

因为在TCP、UDP协议报文的开头,会分别有16位二进制来存储源端口号和目标端口号,所以端口个数是 2^16=65536个,但是0号端口用来表示所有端口,所以实际可用的端口号是65535个。

查看端口号

lsof -i:port

netstat

image.png

综上,操作系统是通过源IP地址、目标IP地址、协议号(协议类型)、源端口号以及目标端口号这五个元素唯一性的识别一个网络上的通信。

image.png

一台主机上能保持的TCP连接数

服务端

我们已经知道网络通信五元组是由过源IP地址、目标IP地址、协议号(协议类型)、源端口号以及目标端口号构成。现在确定是TCP 连接,自然五元组中的协议号已经定下来了,于是网络通信五元组就变化为TCP四元组。很明显当四元组中任意一个元素发生了改变,那么就代表的是一条完全不同的新连接

用户A和用户B构成的TCP连接四元组:

(A1,PA,X,3306)

(B1,PB,X,3306)

目的IP地址和目的端口(X,3306)是不变的,可变的是源IP地址源端口,IP 地址是一个 32 位的整数,所以源 IP 最大有 2 的 32 次方这么多个。 端口是一个 16 位的整数,所以端口的数量就是 2 的 16 次方。2 的 32 次方(ip数)× 2的 16 次方(port数)大约等于两百多万亿。

客户端

虽然客户端的 IP 和端口完全一样,但由于服务器侧的端口不同,所以仍然是两条不同的连接。问题来了,客户端同一个端口可以连接不同的服务器吗?答案是可以的。

客户端只要启动时不显示绑定到某个端口上,内核是可以使用一个端口连不同的服务端,内核会自己进行选择并恰当地复用的,而且完全不会产生数据混乱,因为“源IP地址、目标IP地址、源端口号以及目标端口号就能唯一性确定一个TCP连接”。

那么对客户端来说,四元组里有3个可变,自然客户端能同时支持的连接数比服务器还要大得多。

TCP

TCP是面向连接的通信协议,通过三次握手建立连接,然后才能开始数据的读写,通讯完成后断开连接,由于TCP是面向连接的所以只能用于端到端的通讯。

面向连接

TCP提供的是一种可靠的数据流服务,数据有可能被拆分后发送,那么采用超时重传机制应答确认机制是组成TCP可靠传输的关键设计。

超时重传机制中最最重要的就是重传超时(RTO,Retransmission TimeOut)的时间选择,超时的时长就需要根据网络情况动态调整,就需要采样统计一个数据包从发送端发送出去到接收到这个包的回复这段时长来动态设置重传超时值,这个时长就是为RTT(round-trip time),然后再根据这个RTT通过各种算法和公式平滑RTT值后,最终确定重传超时值。

IP层进行数据传输时,是不能保证数据包按照发送的顺序达到目的机器。当IP将把它们向‘上’传送到TCP层后,TCP将包排序并进行错误检查。TCP数据包中包括序号和确认,所以未按照顺序收到的包可以被排序,而损坏的包可以被重传。

TCP还采用一种称为滑动窗口的方式进行流量控制,所谓窗口实际表示接收能力,用以限制发送方的发送速度,实现流量控制

同时TCP还允许在一个TCP连接上,通信的双方可以同时传输数据,也就是所谓的全双工

TCP三次握手

image.png

第一次握手:客户端将请求报文标志位SYN设置为1,请求报文的Sequence Number字段(简称seq)中填入一个随机值J,并将该数据包发送给服务器端,客户端进入SYN_SENT状态,等待服务器端确认。

第二次握手:服务器端收到数据包后根据SYN=1知道客户端请求建立连接,服务器端将应答报文标志位SYN和ACK都置为1,应答报文的Acknowledgment Number字段(简称ack)中填入ack=J+1,应答报文的seq中填入一个随机值K,并将该数据包发送给客户端以确认连接请求,服务器端进入SYN_RCVD状态。

第三次握手:客户端收到应答报文后,检查ack是否为J+1ACK是否为1,如果正确则将第三个报文标志位ACK置为1,ack=K+1,并将该数据包发送给服务器端,服务器端检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,客户端和服务器端进入ESTABLISHED状态,完成三次握手,随后客户端与服务器端之间可以开始传输数据了。

为什么需要三次握手?

TCP是可靠的传输控制协议,三次握手可以保证数据可靠传输又能提高传输效率的最小次数

为了实现可靠数据传输, TCP协议的通信双方,都必须维护一个序列号, 以标识发送出去的数据包中,哪些是已经被对方收到的。

三次握手的过程即是通信双方相互告知序列号起始值,并确认对方已经收到了序列号起始值的必经步骤。如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。

SYN洪泛攻击

第二次握手时,服务端向客户端应答请求,应答请求是需要客户端IP的,而且因为握手过程没有完成,操作系统使用队列维持这个状态。于是攻击者就伪造客户端IP,往服务器端狂发送第一次握手的内容,当然第一次握手中的客户端IP地址是伪造的,从而服务端忙于进行第二次握手,但是第二次握手是不会有应答的,所以导致服务器队列被占满,而拒绝连接。

Linux维护一个处于半连接状态(三次握手)队列默认2048个

image.png

解决办法

  • 无效连接监视释放,不停监视所有连接,当达到一定阈值时拆除这些连接,从而释放系统资源。这种方法对于所有的连接一视同仁,不管是正常的还是攻击的,所以这种方式不推荐。
  • 延缓TCB分配方法,一般做完第一次握手之后,服务器就需要为该请求分配一个TCB(连接控制资源),通常这个资源需要200多个字节。延迟TCB的分配,当正常连接建立起来后再分配TCB则可以有效地减轻服务器资源的消耗。
  • 使用防火墙,防火墙在确认了连接的有效性后,才向内部的服务器(Listener)发起SYN请求

TCP四次挥手

由于TCP连接是全双工的,因此,每个方向都必须要单独进行关闭。首先进行关闭的一方(可以是服务端,也可以是客户端)将执行主动关闭,而另一方则执行被动关闭。

image.png

(1)客户A调用close,执行主动关闭(active close)。于是客户端的TCP发送一个FIN分节,表示数据发送完毕,应用进程进入FIN-WAIT-1(终止等待1)状态。

(2)接收到这个FIN的对端执行被动关闭(passive close),发出确认报文。因为FIN的接收意味着接收端应用进程在相应连接上再无额外数据可接收,接收端进入了CLOSE-WAIT(关闭等待)状态,这时候处于半关闭状态,即主动关闭端已经没有数据要发送了,但是被动关闭端若发送数据,主动关闭端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。主动关闭端收到确认报文后进入FIN-WAIT-2(终止等待2)状态。

(3)一段时间后,被动关闭的应用进程将调用close关闭它的套接字。这导致它的TCP也发送一个FIN,表示它也没数据需要发送了。

(4)接收这个最终FIN的原发送端TCP(即执行主动关闭的那一端)确认这个FIN发出一个确认ACK报文,并进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命/最长分节生命期 max segement lifetime,MSL是任何IP数据报能够在因特网中存活的最长时间,任何TCP实现都必须为MSL选择一个值。RFC 1122[Braden 1989]的建议值是2分钟,不过源自Berkelcy的实现传统上改用30秒这个值。这意味着TIME_WAIT状态的持续时间在1分钟到4分钟之间)的时间后,当主动关闭端撤销相应的TCB后,才进入CLOSED状态。

(5) 被动关闭端只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,被动关闭端结束TCP连接的时间要比主动关闭端早一些。

既然每个方向都需要一个FIN和一个ACK,因此通常需要4个分节。我们使用限定词“通常”是因为:某些情形下步骤1的FIN随数据一起发送;另外,步骤2和步骤3发送的分节都出自执行被动关闭那-一端,有可能被合并成一个分节。

为什么TCP挥手需要四次?

TCP是全双工的连接,必须两端同时关闭连接,连接才算真正关闭。

假设服务端准备关闭写,但是它还可以读到客户端发送的数据。发送给FIN结束报文给对方,对方收到后,回复ACK报文。当这方也已经写完了准备关闭,发送FIN报文,对方回复ACK。两端都关闭,TCP连接正常关闭。

为什么需要TIME-WAIT状态?

TIME_WAIT状态存在的原因有两点,TIME_WAIT存在于主动关闭连接的一端

1、可靠的终止TCP连接,四次挥手中,主动方发送最后一个ACK报文后,需要等待一段时间,确保被动方收到,如果没有收到(ACK丢失),被动方会重新发送FIN,再次确认关闭。

2、如果立即关闭连接,上一次连接的TCP响应数据被新建立的TCP连接收到。

UDP协议

把数据直接发出去,而不管对方是不是在接收,也不管对方是否能接收的了,也不需要接收方确认,属于不可靠的传输,可能会出现丢包现象

单播:发送消息给一个由唯一的地址所标识的单一的网络目的地。(TCP和UDP都支持)

广播:由于通讯不需要连接,可以把消息传输到网络(或者子网)上的所有主机。

常用的QQ,就是一个以UDP为主,TCP为辅的通讯协议。

UDT

基于UDP的一种互联网数据传输协议,UDT的主要目的是支持高速广域网上的海量数据传输,最典型的例子就是建立在光纤广域网上的网格计算.而互联网上的标准数据传输协议TCP在高带宽长距离网络上性能很差。

UDT建于UDP之上,并引入新的拥塞控制和数据可靠性控制机制。UDT是面向连接的双向的应用层协议。

特点:

  • 基于UDP的应用层协议,同时兼顾TCP协议的安全可靠和UDP协议的高效
  • 面向连接的协议,两个使用协议的应用在彼此交换数据之前必须先建立一个连接,UDT是逻辑上存在的连接通道。这种连接的维护是基于握手、Keep-alive(保活)以及关闭连接。
  • 可靠的协议,依靠包序号机制、接收者的ACK响应和丢包报告、ACK序号机制、重传机制(基于丢包报告和超时处理)来实现数据传输的可靠性。
  • 双工的协议:每个UDT实例包含发送端和接收端的信息
  • 新的拥塞算法,并且具有可扩展的拥塞控制框架:新的拥塞控制算法不同于基于窗口的TCP拥塞控制算法(慢启动和拥塞避免),是混合的基于窗口的、基于速率的拥塞控制算法。可扩展的拥塞控制框架开源的代码和拥塞控制的C++类架构,可支持开发者派生专用的拥塞控制算法。
  • 带宽估计:UDT使用对包(PP -- Packet pair)的机制来估计带宽值。即每16个包为一组,最后一个是对包,即发送方不用等到下一个发送周期内再发送。接收方接收到对包后对其到达时间进行记录,可结合上次记录的值计算出链路的带宽(计算的方法称为中值过滤法), 并在下次ACK中进行反馈。

QUIC

QUIC代表”快速UDP Internet连接”,基于UDP的传输层协议,它本身就是Google尝试将TCP协议重写为一种结合了HTTP/2、TCP、UDP和TLS(用于加密)等多种技术的改进技术。QUIC 协议的主要目的,是为了整合 TCP 协议的可靠性和 UDP 协议的速度和效率。

优势: 1、采用多路复用 思想,一个连接可以同时承载多个 流 ( stream ),同时发起多个请求。 请求间完全 独立 ,某个请求阻塞甚至报文出错均不影响其他请求。

2、QUIC只需要1RTT(Round-Trip Time)的延迟就可以建立可靠安全的连接,相对于TCP+TLS的3次RTT要更加快捷。之后客户端可以在本地缓存加密的认证信息,再次与服务器建立连接时可以实现0-RTT的连接建立延迟。

3、TCP 采用 重传 机制,而 QUIC 采用 纠错 机制。

TCP 发生丢包时,需要一个等待延时判断发生了丢包,然后再启动重传机制,这个过程会造成一定的阻塞,影响传输时间。

而 QUIC 则采用一种更主动的方案,有点类似 RAID5 ,每 n 个包额外发一个 校验和包 。 如果这 n 个包中丢了一个包,可以通过其他包和校验和恢复出来,完全不需要重传。

4、QUIC 直接基于客户端(应用进程)实现,而非基于内核,可以快速迭代更新,不需要操作系统层面的改造,部署灵活。

5、连接保持

QUIC 在客户端保存连接标识,当客户端 IP 或者端口发生变化时,可以快速恢复连接 —— 客户端以标识请求服务端,服务端验证标识后感知客户端新地址端口并重新关联,继续通讯。 这对于改善移动端应用连接体验意义重大(从 WiFi 切换到流量)。