学习自极客时间《趣谈网络协议》 作者:刘超
1. 从物理层到MAC层
1.1 物理层
主要定义物理设备标准,如网线的接口类型、光纤的接口类型、各种传输介质的传输速率等。它的主要作用是传输比特流(就是由1、0转化为电流强弱来进行传输,到达目的地后在转化为1、0,也就是我们常说的数模转换与模数转换),这一层的数据叫做比特,单位是bit比特。
集线器(hub):和交换机不同,集线器没有大脑,它完全在物理层工作。它会将自己收到的每一个字节,都复制到其他端口上去。这是第一层物理层联通的方案。
1.2 数据链路层
1.2.1 解决三个问题
Hub 采取的是广播的模式,如果每一台电脑发出的包,局域网的每个电脑都能收到,这就需要解决几个问题:
- 这个包是发给谁的?谁应该接收?
- 大家都在发,会不会产生混乱?有没有谁先发、谁后发的规则?
- 如果发送的时候出现了错误,怎么办?
这几个问题,都是第二层,数据链路层,也即 MAC 层要解决的问题。MAC 的全称是 Medium Access Control,即媒体访问控制。控制什么呢?其实就是控制在往媒体上发数据的时候,谁先发、谁后发的问题。防止发生混乱。这解决的是第二个问题。这个问题中的规则,学名叫多路访问。解决的方式有信道划分; 轮流协议;随机接入协议(著名的以太网,用的就是这个方式)。
接下来要解决第一个问题:发给谁,谁接收?这里用到一个物理地址,叫作链路层地址。但是因为第二层主要解决媒体接入控制的问题,所以它常被称为MAC 地址。解决第一个问题就牵扯到第二层的网络包格式。对于以太网,第二层的最开始,就是目标的 MAC 地址和源的 MAC 地址。
类型中多部分是IP数据包,ip又包含了运输层和应用层的信息,层层封装。
有了目标mac地址,数据包就可以在链路上广播,当有网卡发现mac地址正好是它的,就把这个数据包收起来,然后在打开IP,发现IP地址也是自己的,再打开TCP,端口也是自己的,就交给应用层去处理。应用层处理好后,又层层封装返回,这时候之前的源mac地址就变成了目标mac地址。
对于以太网,第二层的最后面是 CRC,也就是循环冗余检测。通过 XOR 异或的算法,来计算整个包是否在发送的过程中出现了错误,主要解决第三个问题。
1.2.2 如何获取目标mac地址?
一个广播的网络里面接入了 N 台机器,我怎么知道每个 MAC 地址是谁呢?这就是 ARP 协议,也就是已知 IP 地址,求 MAC 地址的协议。
1.2.3 ARP协议的报文格式如下:
1.2.4 ARP协议的流程大致如下:
当 A 想要与B通信时,A是知道B的IP地址的,但是不知道mac地址
A主机先是在自己的本地ARP缓存中检查主机B的匹配MAC地址。
如果主机A在ARP缓存中没有找到映射,它将询问自己所属的局域网的硬件地址,从而将ARP请求帧广播到本地网络上的所有主机。源主机A的IP地址和MAC地址都包括在ARP请求中。本地网络上的每台主机都接收到ARP请求并且检查是否与自己的IP地址匹配。如果主机发现请求的IP地址与自己的IP地址不匹配,它将丢弃ARP请求。
这里ARP协议报文头部的第一个的目标mac 为 ff ff ff ff ff ff
,这是一个广播地址,相当于在局域网里吼;ARP报文内容里的目标mac留空,就是为了找到想要的mac地址。
主机B确定ARP请求中的IP地址与自己的IP地址匹配,则将主机A的IP地址和MAC地址映射添加到本地ARP缓存
主机B将包含其MAC地址的ARP回复消息直接发送回主机A。
当主机A收到从主机B发来的ARP回复消息时,会用主机B的IP和MAC地址映射更新ARP缓存。本机缓存是有生存期的,生存期结束后,将再次重复上面的过程。主机B的MAC地址一旦确定,主机A就能向主机B发送IP通信了。
1.3 总结
第一,MAC 层是用来解决多路访问的堵车问题的;
第二,ARP 是通过吼的方式来寻找目标 MAC 地址的,吼完之后记住一段时间,这个叫作缓存;
第三,交换机是有 MAC 地址学习能力的,学完了它就知道谁在哪儿了,不用广播了。
2. 交换机与VLAN
2.1 网络拓补结构的形成
两台交换机将网络划分成了三个局域网,一开始大家都不知道对方的任何信息,然后靠广播将信息群发到所以的机器中,然后找到对应的MAC地址,交换机有学习功能,他就知道了该机器所在的局域网,下次广播就不会发送到其他的局域网,就这样慢慢形成了拓补结构。
2.2 拓补结构中的环路问题
机器 1 的广播包到达交换机 A 和交换机 B 的时候,本来两个交换机都学会了机器 1 是在局域网一的,但是当交换机 A 将包广播到局域网二之后,交换机 B 右边的网口收到了来自交换机 A 的广播包。根据学习机制,这彻底损坏了交换机 B 的三观,刚才机器 1 还在左边的网口呢,怎么又出现在右边的网口呢?哦,那肯定是机器 1 换位置了,于是就误会了,交换机 B 就学会了,机器 1 是从右边这个网口来的,把刚才学习的那一条清理掉。同理,交换机 A 右边的网口,也能收到交换机 B 转发过来的广播包,同样也误会了,于是也学会了,机器 1 从右边的网口来,不是从左边的网口来。
然而当广播包从左边的局域网一广播的时候,两个交换机再次刷新三观,原来机器 1 是在左边的,过一会儿,又发现不对,是在右边的,过一会,又发现不对,是在左边的。
STP(最小生成树)协议 将图的环破坏变成树,解决环路问题。
2.3 如何解决广播问题和安全问题?
如果机器多了,交换机也多了,就算交换机比 Hub 智能一些,但是还是难免有广播的问题,一大波机器,相关的部门、不相关的部门,广播一大堆,性能就下来了。而且每一个部门所接触的信息不一样,有的部门信息可能比较敏感,不希望别的部门接收到这个包。
两个隔离的方法:
一个是物理隔离。每个部门设一个单独的会议室,对应到网络方面,就是每个部门有单独的交换机,配置单独的子网,这样部门之间的沟通就需要路由器了。这样的问题在于,有的部门人多,有的部门人少。人少的部门慢慢人会变多,人多的部门也可能人越变越少。如果每个部门有单独的交换机,口多了浪费,少了又不够用。
另外一种方式是虚拟隔离,就是用我们常说的 VLAN,或者叫虚拟局域网。使用 VLAN,一个交换机上会连属于多个局域网的机器,那交换机怎么区分哪个机器属于哪个局域网呢?
我们只需要在原来的二层的头上加一个 TAG,里面有一个 VLAN ID,一共 12 位。12 位可以划分 4096 个 VLAN。
如果我们买的交换机是支持 VLAN 的,当这个交换机把二层的头取下来的时候,就能够识别这个 VLAN ID。这样只有相同 VLAN 的包,才会互相转发,不同 VLAN 的包,是看不到的。这样广播问题和安全问题就都能够解决了。
将两个交换机连接起来的口应该设置成什么 VLAN 呢?对于支持 VLAN 的交换机,有一种口叫作 Trunk 口。它可以转发属于任何 VLAN 的口。交换机之间可以通过这种口相互连接。
2.4 总结
- 当交换机的数目越来越多的时候,会遭遇环路问题,让网络包迷路,这就需要使用 STP 协议,将有环路的图变成没有环路的树,从而解决环路问题。但是STP 对于跨地域甚至跨国组织的网络支持,就很难做了,计算量太大。
- 交换机数目多会面临隔离问题,可以通过 VLAN 形成虚拟局域网,从而解决广播问题和安全问题。
3. ICMP与ping
3.1 ICMP 协议的格式
ping 是基于 ICMP 协议工作的。ICMP 全称 Internet Control Message Protocol,就是互联网控制报文协议。这里面的关键词是“控制”,那具体是怎么控制的呢?
网络包在异常复杂的网络环境中传输时,常常会遇到各种各样的问题。当遇到问题的时候,总不能“不明不白”,要传出消息来,报告情况,这样才可以调整传输策略。ICMP就是相当于这个侦察兵。
ICMP 报文是封装在 IP 包里面的。因为传输指令的时候,肯定需要源地址和目标地址。它本身非常简单。因为作为侦查兵,要轻装上阵,不能携带大量的包袱。
ICMP 报文有很多的类型,不同的类型有不同的代码。最常用的类型是主动请求为 8,主动请求的应答为 0。
1. 查询报文类型
这种主动发起的,主动查看敌情,对应 ICMP 的查询报文类型。例如,常用的 ping 就是查询报文,是一种主动请求,并且获得主动应答的 ICMP 协议。所以,ping 发的包也是符合 ICMP 协议格式的,只不过它在后面增加了自己的格式。
对 ping 的主动请求,进行网络抓包,称为 ICMP ECHO REQUEST。同理主动请求的回复,称为ICMP ECHO REPLY。比起原生的 ICMP,这里面多了两个字段,一个是标识符。这要用标识侦查的对象是什么,另一个是序号,用来确认回收包的情况,如果派出去 10 个,回来 10 个,就说明前方战况不错;如果派出去 10 个,回来 2 个,说明情况可能不妙。
在选项数据中,ping 还会存放发送请求的时间值,来计算往返时间,说明路程的长短。
2. 差错报文类型
这种是异常情况发起的,来报告发生了不好的事情,对应 ICMP 的差错报文类型。几个 ICMP 差错报文的例子:终点不可达为 3,源抑制为 4,超时为 11,重定向为 5。
- 终点不可达: 具体的原因在代码中表示就是,网络不可达代码为 0,主机不可达代码为 1,协议不可达代码为 2,端口不可达代码为 3,需要进行分片但设置了不分片位代码为 4。
- 第二种是源站抑制,也就是让源站放慢发送速度。
- 第三种是时间超时,也就是超过网络包的生存时间还是没到。
- 第四种是路由重定向,也就是让下次发给另一个路由器。
差错报文的结构相对复杂一些。除了前面还是 IP,ICMP 的前 8 字节不变,后面则跟上出错的那个 IP 包的 IP 头和 IP 正文的前 8 个字节。
3.2 ping:查询报文类型的使用
ping 命令执行的时候,源主机首先会构建一个 ICMP 请求数据包,ICMP 数据包内包含多个字段。最重要的是两个,第一个是类型字段,对于请求数据包而言该字段为 8;另外一个是顺序号,主要用于区分连续 ping 的时候发出的多个数据包。每发出一个请求数据包,顺序号会自动加 1。为了能够计算往返时间 RTT,它会在报文的数据部分插入发送时间。
由 ICMP 协议将这个数据包连同对方的IP地址 一起交给 IP 层。IP 层将以对方的IP地址作为目的地址,本机 IP 地址作为源地址,加上一些其他控制信息,构建一个 IP 数据包。
接下来,需要加入 MAC 头。如果在本节 ARP 映射表中查找出 对方的IP 地址 所对应的 MAC 地址,则可以直接使用;如果没有,则需要发送 ARP 协议查询 MAC 地址,获得 MAC 地址后,由数据链路层构建一个数据帧,目的地址是 IP 层传过来的 MAC 地址,源地址则是本机的 MAC 地址;还要附加上一些控制信息,依据以太网的介质访问规则,将它们传送出去。
对方主机收到这个数据帧后,先检查它的目的 MAC 地址,并和本机的 MAC 地址对比,如符合,则接收,否则就丢弃。接收后检查该数据帧,将 IP 数据包从帧中提取出来,交给本机的 IP 层。同样,IP 层检查后,将有用的信息提取后交给 ICMP 协议。
对方主机会构建一个 ICMP 应答包,应答数据包的类型字段为 0,顺序号为接收到的请求数据包中的顺序号,然后再发送出去给源主机。
在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明目标主机不可达;如果接收到了 ICMP 应答包,则说明目标主机可达。此时,源主机会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。
如果跨网段的话,还会涉及网关的转发、路由器的转发等等。但是对于 ICMP 的头来讲,是没什么影响的。会影响的是根据目标 IP 地址,选择路由的下一跳,还有每经过一个路由器到达一个新的局域网,需要换 MAC 头里面的 MAC 地址。
经常会遇到一个问题,如果不在我们的控制范围内,很多中间设备都是禁止 ping 的,但是 ping 不通不代表网络不通。这个时候就要使用 telnet,通过其他协议来测试网络是否通。
3.3 Traceroute:差错报文类型的使用
Traceroute,会使用 ICMP 的规则,故意制造一些能够产生错误的场景。
1. Traceroute 的第一个作用就是故意设置特殊的 TTL,来追踪去往目的地时沿途经过的路由器。
Traceroute 的参数指向某个目的 IP 地址,它会发送一个 UDP 的数据包。将 TTL 设置成 1,也就是说一旦遇到一个路由器或者一个关卡。
如果他“牺牲”了,就返回一个 ICMP 包,也就是网络差错包,类型是时间超时。这时候就知道达到目标IP的路径不值隔了一个路由,然后把TTL 设置成 2,如此反复,直到到达目的主机。这样,Traceroute 就拿到了所有的路由器 IP。当然,有的路由器压根不会回这个 ICMP。这也是 Traceroute 一个公网的地址,看不到中间路由的原因。
怎么知道 UDP 有没有到达目的主机呢?Traceroute 程序会发送一份 UDP 数据报给目的主机,但它会选择一个不可能的值作为 UDP 端口号(大于 30000)。当该数据报到达时,将使目的主机的 UDP 模块产生一份“端口不可达”错误 ICMP 报文。如果数据报没有到达,则可能是超时。
2. Traceroute 还有一个作用是故意设置不分片,从而确定路径的 MTU。
要做的工作首先是发送分组,并设置“不分片”标志。发送的第一个分组的长度正好与出口 MTU 相等。如果中间遇到窄的关口会被卡住,会发送 ICMP 网络差错包,类型为“需要进行分片但设置了不分片位”。其实,这是人家故意的好吧,每次收到 ICMP“不能分片”差错时就减小分组的长度,直到到达目标主机。
3.4 总结
- ICMP 相当于网络世界的侦察兵。
- 两种类型的 ICMP 报文,一种是主动探查的查询报文,一种异常报告的差错报文;
- ping 使用查询报文,Traceroute 使用差错报文。
不应发送ICMP差错报文的几种情况:
- 对ICMP差错报文,不再发送ICMP差错报告报文。
- 对第一个分片的数据报片的所有后续数据报片,都不发送ICMP差错报告报文
- 对具有多播地址的数据报,都不发送ICMP差错报告报文
- 对具有特殊地址(如127.0.0.0或0.0.0.0)的数据报,不发送ICMP差错报告报文
tracerouter发udp,为啥出错回icmp?
ICMP一般认为属于网络层的,和IP同一层,是管理和控制IP的一种协议,而UDP和TCP是传输层,所以UDP出错可以返回ICMP差错报文。正常情况下,协议栈能正常走到udp,当然正常返回udp。
但是,你主机不可达,是ip层的(还没到udp)。ip层,当然只知道回icmp。报文分片错误也是同理。