【网络实验三】OSI 参考模型下

OSI 参考模型下

一、实验介绍

通过本节实验我们将认识 OSI 参考模型剩下的几层,以及相关常用的协议,本章节中 TCP 协议是我们学习的重点,很多应用层的协议与网络攻击都会涉及到 TCP。

1.1 实验涉及的知识点

  • 传输层
  • 会话层 & 表示层
  • 应用层

二、传输层

传输层(Transport Layer)是 OSI 中最重要, 最关键的一层,是负责总体的数据传输和数据控制的一层。

传输层提供端到端的交换数据的机制.传输层对会话层等高三层提供可靠的传输服务,对网络层提供可靠的目的地站点信息。

世界上各种通信子网在性能上存在着很大差异。例如电话交换网,分组交换网,公用数据交换网,局域网等通信子网都可互连,但它们提供的吞吐量、传输速率、数据延迟通信费用各不相同。对于会话层来说,却要求有一性能恒定的接口,传输层就承担了这一功能。它采用分流/合流,复用/解复用(分用)技术来调节上述通信子网的差异,使会话层感受不到。此外传输层还要具备差错检测,流量控制等功能,以此对会话层屏蔽通信子网在这些方面的细节与差异。

传输层提供的主要功能有:

  • 连接导向式通信:创建好连接,网络流量就固定,不会被其他通信影响;
  • 相同次序交付:网络层通常不保证数据包到达顺序与发送顺序相同,这通常是通过传输层给报文段编号来完成的,接收者按次序将它们传给应用进程。
  • 可靠性:由于网络拥塞和错误,数据包可能在传输过程中丢失。通过检错码(如校验和),传输协议可以检查数据是否损坏,并通过向发送者传ACK或NACK消息确认正确接收。自动重发请求方案可用于重新传输丢失或损坏的数据。
  • 流量控制:有时必须控制两个节点之间的数据传输速率以阻止快速的发送者传输超出接收缓冲器所能承受的数据,造成缓冲区溢出。这也可以通过减少缓冲区不足来提高效率。
  • 多路复用: 端口可以在单个节点上提供多个端点。每个计算机应用进程会监听它们自己的端口,这使得在同一时间可以使用多个网络服务。

总的来说传输层的功能,就是为应用程序间提供端口到端口的通信,相比之下,网络层的功能是建立主机到主机的逻辑通信。本质上主机间的通信主要的目的其实是为了实现主机里的应用程序之间的通信,只要确定主机和端口,我们就能实现程序之间的交流。因此,Unix系统就把 主机ip:端口,叫做”套接字”(socket)。

此处的端口是协议栈层间的抽象的协议端口号(Protocol Port number),应用程序通过这些端口提供其特定的服务。访问 80 端口我们可以得到 web 服务,访问 22 端口我们可以得到 ssh 服务等等。做个不太形象的比喻,我们去火车站的售票厅,它有改签窗口,售票窗口,退票窗口,这样的名字就像端口号,而每个窗口都有相应的功能,我们不必关心其如何实现,只需告诉他目的地,给钱就可以拿到车票,而在这里我们则是访问某个 IP 与 端口,他就给我们想要的服务。

端口号的产生是因为虽然我们可以通过 IP 来定位主机的所在,但是我们不知道与那个应用程序相互通信,信息该给谁,就像我们写信到对方单位,地址写了城市、街道、单元、多少号,没有写谁签收一样,送到目的地了,公司中这么多人怎么知道谁签收呢?你会说应用程序接收那他有相应的进程 ID 的标志信息,但是程序间的相互通信可能涉及到不同操作系统里的程序,不同操作系统里的进程标识也不同,格式也不同,并且进程是动态的,终止一下马上启动起来信息就变了,这样很难确定,就像你信息没有写签收人而是写的桌号,或许明天位置就变了,接收人就错了。所以就诞生了端口,每个程序在本地都有其使用的唯一端口号,如此就可以建立可靠的连接,不会有格式不统一,进程动态找不到的问题了。

在网络层中最主要的两个协议:

  • TCP:(Transmission Control Protocol)传输控制协议,TCP 提供的是面向连接的服务,在传输数据之前必须建立连接,数据传输之后释放连接,由此提供了可靠的、面向连接的、基于字节流的传输服务。
  • UDP:(User Datagram Protocol)用户数据报协议,UDP 提供的是面向无连接的服务,对一些简单事务的不可靠信息传输服务。

UDP 的特点:

  • UDP 是无连接的,发送数据之前不用建立连接,所以时延小。
  • UDP 是面向报文的,也就是 UDP 并不差分,也不合并报文,上层传输过来的数据不会有其他的处理,保留报文的边界。
  • UDP 没有拥塞控制,因为没有缓冲,数据直接添加首部就传输出去,实时性,发送效率高。
  • UDP 的首部开销小,因为只有 8 个字节。(源端口,目的端口,长度,校验和)

UDP header
(此图来自于 nmap.org

TCP 的特点:

  • TCP 是面向连接的,也就是若是需要以 TCP 来通信需要先建立连接,就像打电话一般,需要先拨号,对方接通了建立了连接,才能开始对话。
  • TCP 是可靠的交付服务,正因为面向连接,所以数据包需要得到接收方确认才会继续发送
  • TCP 提供全双工通信,与之相关的还有单工、半双工。单工就是单车道的单行道,只有一条路并且只能发送方发给接受方,接收方不能发送给发送方;半双工就是双向单车道,这条道可以过去也可以过来,但是在同一时间只能一辆车通过,同一时间只能 A 发给 B,或者 B 发给 A;全双工就是双向双车道。
  • TCP 是面向字节流的,也就是 TCP 将上层传输来的消息看成一连串的无结构的字节流。
  • TCP 的首部使用 20 个字节。(源端口号,目的端口号(第一行),序号(第二行),确认序号(第三行),首部长度、保留、TCP 的标示、窗口(第四行),校验和、紧急指针(第五行),参数(第六行))

tcp_header1.png
(此图来自于jbgsm wordpreess

TCP 到底是如何建立一个可靠的连接呢?我们可以通过这么一个实验来了解一下 TCP 建立连接,与断开连接的过程。(因为建立的过程需要三次交互,所以建立过程通常称之为 TCP 的三次握手,在断开连接的时候需要四次交互,所以断开的过程称为 TCP 的四次挥手)

因为 Telnet 这个应用协议是基于 TCP 建立连接来实现远程登陆的,所以我们的实验将通过抓取在使用 Telnet 时的数据包来查看 TCP 交互数据包的详情。

  • 实验目的:了解 TCP 建立与断开连接的过程
  • 实验材料:两台交换机
  • 实验方法:
    • 拖动两台交换机至画布
    • 配置交换机的名字
    • 开启设备与 wireshark 抓包与配置端口 IP,与开启其中一台的登陆权限
    • telnet 至设备,然后断开连接
    • 查看抓取的数据包
  • 实验备注:与实验一的小实验十分相似,能够独立完成配置吗?

首先往画布中拖动两台交换机,分别命名为 Switch1 与 Switch2,同时启动设备并开始抓包(抓取使用 Telnet 一方的数据包,在本实验中将使用 Switch2 Telnet Switch1,所以抓取 Switch2 的数据包):

TCP-add-device.png

接下来便是配置 Switch1 的 IP 地址与登陆权限:

TCP-config-switch1.png

#进入全局模式
switch1#conf t

#配置连接网线的接口
Switch1(config)#int e0/0

#更改至路由模式,
Switch1(config-if)#no switchport

#设置 IP 地址,命令+ IP + 子网掩码
Switch1(config-if)#ip address 192.168.1.1 255.255.255.0

#激活接口,此处默认都是打开的,但是真实机上不是如此,要有良好的习惯
Switch1(config-if)#no sh

#退出该接口的配置模式
Switch1(config-if)#exit

#进入控制台口
switch1(config)#line console 0

#进入设备的虚拟终端
switch1(config-line)#line vty 0 4

#允许其他设备远程登录,否则是拒绝访问的
switch1(config-line)#login

#设置登录密码xx,不设置不允许登陆
switch1(config-line)#password xx

接下来便是 Switch2 的接口配置:

Switch2#conf t

Switch2(config)#int e0/0

Switch2(config-if)#no swit

Switch2(config-if)#ip add 192.168.1.2 255.255.255.0

Switch2(config-if)#no sh

Switch2(config-if)#end

成功的做好了所有的准备工作我们便开始尝试 Telnet Switch1,连接成功后我们可以顺利登陆,然后退出,查看 Wirshark 抓取的数据包(在退出之后我们可以停止抓包与设备,因为我们已经获取到我们需要的数据了):

TCP-connect-disconnected.png

我们选择一个 TCP 的数据包,看到 Packet Detail 面板,展开 Transmission Control Protocol 的内容详情,我们可以看到 TCP 首部的内容,与上文提到的 TCP 首部对比者看:

TCP-detail.png

  • Source Port:这表示的是源端口(由 16 位组成,也就是 2 个字节),也就是发送数据包者使用的端口,此处应该 Switch 2 使用的端口;
  • Destination Port:这表示的是目的端口(由 16 位组成,也就是 2 个字节),也就是数据包到达目的地的端口,此处应该是 Switch 1 中 Telnet 监听的端口;
  • Sequence Number:这表示的是发送出该数据包的序列号(由 32 位组成,也就是 4 个字节),每个数据包都有对应的序列号,这样使得数据包才不会混乱;
  • Acknowledgment Number:这表示的是确认的序列号(由 32 位组成,也就是 4 个字节),主要用于响应请求时的序列号对应,值为所回应的序号值+1;
  • Offset:Offset 告知目的地首部长度,而其值的每一位表示的是首部里的 32 位,也就是说若是 Offset = 1,那么首部总长为 32 位,Offset 总共由 4 位组成,由此可以推算出 TCP 的首部最大容量是 (2^4-1)32 = 15 32 bit = 60 * 8 bit = 60 字节
  • Reserved:保留的位置
  • TCP Flags:TCP 的一些标志位
    • NS (1 bit) – ECN-nonce:隐蔽性保护
    • CWR(1 bit)-Congestion Window Reduced:用于拥塞控制,由传送主机设定,可管理传送视窗的大小
    • ECE (1 bit) – ECN-Echo:两重作用都关于拥塞控制,ECN两个作用,一个在TCP三次握手时表明TCP端是否支持ECN;一个在传输数据时,发送方是无法知道网络是否畅通的,具体的实现参考这篇博文
    • Urgent(1 bit):紧急数据标志,当 URG =1 时表示报文段为紧急数据,尽快优先传送
    • Acknowledgment(1 bit):确认位,表示这是一个确认的 TCP 包
    • Push(1 bit):推送功能。要求将缓冲数据尽快推送至接收应用程序
    • SYN(1 bit):同步标志位
    • FIN(1 bit)-Finish:表示发送端没有其他数据发送了,请求断开
  • Window size:表示接收窗口的大小(由 16 位组成,也就是 2 个字节),TCP通过滑动窗口的概念来进行流量控制。窗口具体的了解我们可以通过这篇文章来了解;
  • Checksum:用于对首部与数据的差错校验(由 16 位组成,也就是 2 个字节);
  • Urgent pointer:如果 URG 标志设置,那么这16位字段是表示最后的紧急数据字节的顺序号偏移(由 16 位组成,也就是 2 个字节);
  • Options:是可变长的可选信息。这部分最多包含40字节.

由此我们看到了 TCP 首部在数据包中实际存在的位置与内容,接下来我们就来了解一下 TCP 建立连接的三次握手具体流程与传递的信息(查看过滤出来的第一个 TCP 数据包,Info 中带有 SYN 的数据包):

提示:32 位的 ACK 字段表示的是确认的序列号,是请求序列号 + 1,而 1 位 ACK 标志位表示的是确认建立连接。在看的过程中切勿混淆了。

客户端也就是我们的 Switch 2 要 Telnet(远程连接) Switch 1,而 Telnet 需要建立 TCP 连接,所以在我输入 Telnet 命令之后,便调用了 Socket() 函数创建了套件字,因为没有建立连接,所以还是处于 Closed 状态,而服务端只要开启了 Telnet 就会处于 Listen 状态监听端口(就像去食堂,5 元的荤菜区有食堂大妈站在窗口前,随时准备为我们服务)

1.第一次握手:此时客户端 Switch 2 调用负责连接的函数,TCP 会组建一个数据包,该数据包中 SYN 标志位设置为 1,表示数据包是用来建立连接的,同时为 Sequence Number 设置一个值表示发送的数据包序列号,因为是第一个所以此处值为 0(为了与后面将讲到的服务端的值区别,假设为 x = 0)。

发出该数据包之后将自己的状态设置为 SYN-SEND 状态:

TCP-connect-SYN1.png

2.第二次握手:此时服务端的 Switch 1 收到了数据包,并且检测到了 SYN 标志位,知道这是客户端发来的建立连接的请求包。既然提出了请求的申请,便回复他同意建立连接,所以服务端 Switch 1 就组建一个数据包,该数据包中确认序列号 ACK = 1 便是确认收到了客户端发送来的请求数据包。因为是回复上一条的请求所以 ACK = X(请求时序列号)+ 1,而当前的 Seq 是自己发送的,所以 Seq = y = 0(Y 便是用来区别上面的 X 的,这是两个不同的值)。TCP 提供的是全双工通信,所以还要请求与客户端 Switch 2 建立连接,SYN = 1 表示用来请求建立连接的。

发送了该数据包之后 Switch 1 服务端会把自己的状态从 Listen 修改成 SYN-RECV:

TCP-connect-ACK1.png

3.第三次握手:客户端收到了来自服务端的数据包,检测到了已经设置的 ACK 的标志位,明白这是确认包,并且 32 位的 ACK 字段是 x+1 的值,表明回复之前的那个请求,由此 Switch 2 –> Switch 1 的通道就建立成功了。上文提到过 TCP 提供的是全双工的服务,所以还需要建立 Switch 1 –> Switch 2 的通道,所以 ACK 标志位设置为 1,回复服务端同意建立连接的请求,并且 ACK 的 32 位字段设置 ACK = y + 1(回复他的请求,所以是在他发送的请求序列号 +1)。同时这是自己发送的第二条请求信息所以序列号 Seq = x + 1

发送了该数据包之后 Switch 2 客户端将自己的状态从 SYN-SEND 设置为 Established:

TCP-connect-finialpacket.png

Switch 1 服务端收到了数据包,检测到了 ACK 的值是回复自己请求的序列号(y+1),并且 ACK 标志位设置成 1,明白了 Switch 2 客户端同意了自己的建立连接的请求,所以将自己的状态从 SYN-RECV 设置为 Established。由此两条通道都建立好了,便成功的提供了全双工服务。

这便是 TCP 的三次握手的整个过程,简单来说就是这样的一个过程:

  • 客户端说:“和我建立通向你的连接好不好?”
  • 服务端说:“好呀,好呀!那和我建立通向你的连接好不好?”
  • 客户端说:“好呀,好呀”

双方确认了关系,建立了连接,从此就可以提供高质量的通信服务了。当数据发送完毕,就像电话里交代的事情交代完了,需要挂电话了(需要断开连接了),就会有这样一个过程:

  • 打电话的人就会说:“我的话说完了,准备挂电话了”(客户端说:“我的数据发送完了,我要断开通向你的连接”)
  • 接电话的人就会说:“好的,我知道了”(服务端会说:“我知道了,你断开把”)
  • 接电话的人想了一下又说:“我也没事交代,我挂了”(服务端会说:“我也要断开通向你的连接”)
  • 打电话的人就会说:”嗯“(客户端会说:”断开吧!“)

在我们的例子中,实际是这样的一个过程。

一般客户端会知道自己的数据是否传输完,然后主动提出断开连接的请求,而此处比较特殊,Switch 2 这个客户端在远程控制 Switch 1 服务端,就像是灵魂附体在服务端一样,客户端 Switch 2 觉得数据传输完毕,可以断开连接了,所以客户端提出断开连接,但是表面上我们看到的是服务端提出的断开连接,因为是由 Switch 1 执行的 exit 的命令,所以我们看到的是服务端提出了断开连接的请求。

1.服务端想要断开连接,便发出这样的请求数据包,数据包中将 FIN 标志位设置为 1,表示想断开连接,同时 ACK 设置为 1,因为在 TCP 中一旦连接成功,两边都是 Established 的状态时,所有发送向对端的数据包必须设置 ACK,即使是重复确认。而将 PSH 的标志位设置为 1,是为了让接收数据的机器立即处理该消息免得被缓存耽误了(若是不太理解 TCP 的 Buffer 而使用这个标志位的同学可以看看这篇文章)。同时将自己的状态从 Established 转换到 FIN_WAIT_1。

TCP-disconnect-1.png

2.客户端接收到了服务端发来数据包,检测到设置了 FIN 标志位知道这是请求断开连接的数据包,于是向服务端发送确认包,设置 ACK 标志位为 1,同时设置确认序列为 ACK = b + 1,因为是回复上一个请求序列的。Seq 依然是自己的发送序号。发送之后将自己的状态从 Established 转变成 CLOSE_WAIT。服务端收到确认的数据包之后将自己的状态从 FIN_WAIT_1 转变成 FIN_WAIT_2。由此全双工便断开了一边,就像两个根绳子,剪掉一根一样。

TCP-disconnect-2.png

3.等待一会儿之后,客户端处理好相关的资源与数据包之后,主动向服务端发送 FIN 包,将 FIN 标志位设置成 1,告诉它自己准备好了,可以断开连接,同时请求断开,同时 ACK 标志位设置为 1,这就是上文所提到过的重复确认的情况,同时设置了 PSH 的标志位,让对方及时处理该数据包。然后将自己的状态从 CLOSE_WAIT 转变成 LAST_ACK。

TCP-disconnect-3.png

4.服务端收到客户端的 FIN 后再向客户端发送确认的 ACK 包,然后进入 TIME_WAIT 状态。而客户端在收到服务端的 ACK 确认包之后就断开连接,关闭套接字,进入 CLOSED 的状态,到此为止两条连接都已经断开,而服务端在过一段时间之后才会转变成 CLOSED 的状态。

TCP-disconnect-4.png

看到此时可能会有这样一个疑惑,为什么不直接编程 CLOSED 的状态,而要变成 TIME_WAIT 的状态,需要等一下在转换过去,而且等,需要等多久呢?

TCP 是面向连接的传输方式,必须保证数据能够正确到达目标机器,不能丢失或出错,而网络是不稳定的,随时可能出现包丢失,包的数据损坏的情况,所以两台设备之间发送数据发送方总会在发送数据之后要求接收方”确认“,回传 ACK 包,告诉接收方收到了,这样接收方才能知道数据传送成功了。如果没有回传 ACK 包,发送方会重新发送,直到回传 ACK 包。

服务端 Switch 1 最后一次向客户端 Switch 2回传 ACK 包时,有可能会因为网络问题导致 Switch 2 收不到或者有延迟,那么 Switch 2 以为服务端的 Switch 1 没有收到 FIN 的请求数据包,数据包可能损坏或者掉了,所以会再次发送 FIN 包,而如果此时的 Switch 1 直接跳过 TIME_WAIT,从 FIN_WAIT2 进入 CLOSED 完全关闭了连接,那么客户端 Switch 2 无论如何也收不到 ACK 包了,可能还会收到 RST 的包,重新建立连接,而若是延时的包到了,又会出现干扰,所以需要等待片刻才能进入 CLOSED 状态。那么,要等待多久呢?

数据包在网络中是有生存时间的,超过这个时间还未到达目标主机就会被丢弃,并通知源主机。这称为报文最大生存时间(MSL,Maximum Segment Lifetime)。TIME_WAIT 要等待 2MSL 才会进入 CLOSED 状态。ACK 包到达需要 MSL 时间,服务器重传 FIN 包也需要 MSL 时间,2MSL 是数据包往返的最大时间,所以一旦 2MSL 后还未收到服务器重传的 FIN 包,就说明对方已经收到了 ACK 包。这样就可以安全的进入 CLOSED 状态了。(TIME_WAIT 更深的理解与处理可以参看这篇文章

由此我们了解了 TCP 建立连接与释放连接的整个过程,或许大家还有很多疑惑之处,对于后续的学习并不会太大的影响,只是为了让大家对这一层,这个协议有个具体的认识,大概了解它会我们做哪些服务。

当然有兴趣的同学,我们可以通过这篇文章来学习到 TCP 是如何建立可靠的传输连接(无差错,超时重传,停止等待,滑动窗口,拥塞、流量控制等等的具体过程),以及通过这篇 Gitbook来学习 TCP 首部每个参数的具体含义,当然此书也讲解了其他层次的见解。

这便是我们对网络层的粗略认识,TCP 协议的重要性从 TCP/IP 模型直接以此命名就可以看出。

三、会话层 & 表示层

会话层提供的服务可使应用建立和维持会话,并能使会话获得同步。会话层使用校验点可 使通信会话在通信失效时从校验点继续恢复通信。会话层同样要担负应用进程服务要求,

主要功能有:为会话实体间建立连接、数据传输阶段、连接释放。

常用的会话层协议有:

  • PPTP: Point-to-Point Tunneling Protocol
  • RPC:远程过程调用
  • RTCP: 实时传输控制协议
  • SCP: Secure Copy Protocol

表示层位于OSI分层结构的第六层,它的主要作用之一是为异种机通信提供一种公共语言,以便能进行互操作,为不同终端的上层用户提供数据和信息正确的语法表示变换方法。

主要的功能有:数据语法转换、语法表示、连接管理、数据处理(数据加密和解密、数据压缩和解压、数据编码和解码)

常用的协议有:

  • 虚拟终端协议(VTP)

因为在实际生活中用的更多的是 TCP/IP 模型,而 TCP/IP 模型中并没有会话层与表示层,这两层的功能大多都放在了应用层,所以这两层我们只是做个简单的了解,并没有过多的深入。

四、应用层

应用层是一个抽象层,它指定在通信网络中的主机使用的共享协议和接口方法,它是离终端用户最近的一层,与用户的交互,与通信接口的连接都靠这一层。不同类型的网络应用有不同的通信规则,因此应用层协议是多种多样的,比如 DNS、FTP、Telnet、SMTP、HTTP、NFS 等协议都是用于解决其各自的一类问题。

DNS (Domain Name Service 域名服务) 协议基于 UDP,使用端口号 53。由数字组成的 IP 地址很难记忆,没有任何意义,所以我们上网使用网站 IP 地址的别名——域名。实际使用中,域名与 IP 地址是对应的,这种对应关系保存在 DNS 服务器之中。我们可以通过这篇文章学习到 DNS 的运作方式。

HTTP (HyperText Transfer Protocol 超文本传输协议) 基于 TCP,使用端口号 80 或 8080。每当你在浏览器里输入一个网址或点击一个链接时,浏览器就通过 HTTP 协议将网页信息从服务器提取再显示出来,这是现在使用频率最高的应用层协议。我们可以通过这篇文章学习到 HTTP 的运作方式。

OSI 参考模型的所有层次便介绍到这里了,最重要的便是传输层与网络层,其中的 TCP 与 IP 这两个协议更是我们重点的理解对象。若是我们不能很好的理解这些协议的原理,在以后的网络安全方面我们将很难去理解与实现,如 SYN 攻击(利用 TCP 的三次握手)、DHCP 攻击(利用应用层的 DHCP 功能与 IP 协议),ARP 攻击(利用数据链路层的攻击)等等。

这里提供一张 OSI 与 TCP/IP 协议栈的一张总图帮助大家对各层的协议有个更具体的认识和了解:

TCP/IP 协议栈
(此图来自于 红黑联盟

五、实验总结

通过本节实验我们深入的了解传输层相关的内容,特别是对 TCP 协议相关的原理,三次握手,四次分手,稳定的传输连接,重传,超时等等。到此为止我们已经学完了 OSI 的七层模型,通过三个小实验对一些协议做了一定的了解。

六、参考资料

[1] 维基百科,传输层:https://zh.wikipedia.org/wiki/%E4%BC%A0%E8%BE%93%E5%B1%82
[2] Microsoft TechNet:https://www.microsoft.com/taiwan/technet/community/columns/cableguy/cg1006.mspx
[3] ACK set when establish:https://ask.wireshark.org/questions/20423/pshack-wireshark-capture
[4] RFC about TCP:https://tools.ietf.org/html/rfc793

发表评论

电子邮件地址不会被公开。 必填项已用*标注