MAC协议原理

数据链路层

Quicker_20231030_204532_result

现在我们知道主机B的报文经过路径选择后,可以将报文交给主机C!

我们上面说过IP提供的能力是将B主机报文跨网络送到C主机的能力!——现在我们知道跨网络将报文送到的能力是通过==目的IP+子网划分+路由(路径选择)==来达成的!

但是我们想要将数据从主机B到主机C的前提是——我们要能将数据交付给和我们直接相连我们下一跳路由器!而路由器也要将数据交付给和路由器直接相连的下一跳的设备!循环往复这个过程!——==所以我们将数据从主机B到主机C,我们要先解决的是如何将数据交给直接相连的下一个节点!(从主机B到路由器F)==

而这就要保证主机B和路由器F是同一个网段(局域网内)的!而路由器F到路由器G也是要处于同一个网段!

==所以跨网络传输的本质是由无数个局域网(子网)转发的结果!==

==我们想要彻底理解跨网络转发!首先就要理解,局域网中报文跨网络转发的原理!==

IP协议只是告诉我们去哪里!但是具体怎么走是由底层决定的!

所以我们就需要数据链路层——用于两个设备(同一种数据链路节点)之间进行传递

==而数据链路层中的协议就是以太网协议!==

什么是以太网

"以太网" 不是一种具体的网络, 而是一种技术标准;

既包含了数据链路层的内容, 也包含了一些物理层的 内容. 例如: 规定了网络拓扑结构, 访问控制方式, 传输速率等;

例如以太网中的网线必须使用双绞线; 传输速率有10M, 100M, 1000M等;

以太网是当前应用最广泛的局域网技术; 和以太网并列的还有令牌环网, 无线LAN等;

==那么局域网转发原理是什么呢?==

首先我们要有一个常识——在同一个局域网的主机,能不能直接通信呢?可以的!

我们可以用一个例子来说明

image-20230912114305748

==从上面的例子中我们可以提炼出一个核心信息——每一台主机都要有唯一的标识符!==

以太网帧格式(协议格式)

在局域网通信的时候,数据报到了IP层,IP经过路由转发,发现他要去的路由主机要转发到局域网中的入口/出口路由器当中!所以就要重新封装MAC帧

要封装MAC帧就要将IP重新交付给它的下一层协议以太网!遵守的协议就是MAC帧

所以就要进行IP报文封装MAC——所以我们接下来就要了解一下MAC帧的报头格式!

Quicker_20231106_095518_result

image-20231106100440282

==这个数据就是上层交付下来的IP报文!——包含了IP报头和有效载荷!==

==然后前面的目的地址和源地址,类型,以及后面的CRC都是属于以太网报头!==

==那么如何进行报头和有效载荷分离呢?==

以太协议的分离方式特别的简单粗暴!——使用的是定长分离!

当收到报文的时候!就直接对前面的14个字节和后面额4字节报头进行分离!剩下的就是有效载荷!

==那么得到有效载荷后如何将数据分用呢(如何交付给上一层!)?==

MAC帧报头里面就有一个字段——是==类型!==

这个类型是0800——说明这个报文是属于IP数据报!那么这个有效载荷就是IP报文!

如果是0806说明这个报文是ARP

如果是8035说明这个报文是RARP

image-20231106102600186

==所以通过类型我们就可以如何交付了!==

==而目的地址和源地址——其实就是说该报文从哪来到哪去!==

==最后的CRC字段是一个CRC校验——用于保证MAC帧二进制数据的正确性!==

上面我们说过每一台主机都要有唯一的标识符!——这个唯一的标识符我们该如何理解呢?

这里我们不考虑虚拟机!——只说真实的主机!

真实的裸的物理机 每一台机器都只要要配备一个网卡!而每张网卡都有一个序号号(sn)

==这个序列号我们就称之为该网卡的mac地址!——这个mac地址在全球范围内具有唯一性!通常是48位的数值!==

image-20231106101754193

在linux下我们可以使用ifconfig来查看这个mac地址!

**里面每一位都是占4个字节! 所以是4 * 2 * 6 = 48字节! **

ether——也就是以太的意思!

==无论如何我们只要保证他是在局域网唯一就可以了!所以不用太关心这个数字!==

基于协议的局域网转发的原理

上面我们用一个生活例子来说明了局域网的转发原理!

那么实际上局域网的转发流程是怎么样的呢?两个主机是如何通信的呢?

image-20231106105219128

==所以以太网的通信原则是非常简单的!——它的信息是会被所有主机都接收到的!但是主机会将不是自己的报文丢弃!是自己的才会向上交付!==

==总结——局域网中所有的主机其实都能收到对应的mac报文,只不过大部分主机在自己的数据链路层通过对比数据帧中的目标mac地址和自己的mac地址是否相等,来决策要不要在进行后续处理!==

所以在局域网中,网卡有一种模式:混杂模式,不放弃任何数据帧,直接向上交付,这也是绝大部分局域网抓包工具的原理!——就是修改网卡的工作模式为混杂模式!因为本质我们都是能收到的!(所以我们说http协议是不安全的!因为在任意的一个节点中只要设置为混杂模式就能抓到使用http协议发出来的数据包)

==刚刚的情况是m1和m8独自的在网络中发送!——那么在m1发送的时候么m2,m3,m4...可以一起发送吗?==

就好比在一间教师里面,小明和小红在对话,那么小刘和小张能不能同时对话呢?——当然可以!因为教师就是一个共享的环境!但是这样子教师肯定是乱糟糟的!十分的吵闹,什么声音都有!

==上面的情况在网络通信也是会出现的!——但是这样子会出现很严重的数据干扰!在计算机里面也叫做数据碰撞!==

换句话说m1发消息的时候,m2,m3m4也可以同时向局域网里面发消息啊!而我们发送的消息,在计算机里面都是光电信号!就是一些数字和模拟信号

或者也可以理解是一些波形图!当多个波同时在一起的时候,就会互相干扰了!分不清楚谁是谁了!

==所以为了避免这样的问题——任何时刻只能有一个主机发送消息!==

但是每个主机都是独立的!又应该如何管得住这些主机呢?

管不住的!——但是因为彼此都是使用的是同一个数据链路层协议!虽然主机间无法阻止,当我在发消息的时候,你也在发消息这件事的发送!==但是可以进行检测==

==如果多个消息被同时发送,会导致局域网中的数据发送碰撞!那么这个数据就变成了无效数据!==

那么如何知道发送碰撞呢?——很简单因为一台主机发送的数据,主机本身也是能收到的!(就像是你自己说话,你也能听到),当发现收到的数据是不一样的时候,那不就是发送碰撞了吗?

==所以一个局域网,也叫做一个碰撞域==

那么如何保证任何时候,只能有一个主机发送消息呢?

不同的局域网有不同的解决方案!——其中有个叫做==令牌环!==

就是在局域网中流转一份令牌数据,只有持有令牌的人,才能发消息!而发消息的人也要将令牌一起发送出去,转给下一台主机!

还有一个是基于碰撞域的==以太网==

那么以太网是如何做大的呢?

很简单,如果检测到发送碰撞!数据链路层的协议就是触发策略暂时不发送数据!等一会!然后过一会再尝试发送!等的时间可以根据情况随机等待!

例如:A主机和B主机同时发送数据,触发了碰撞!那么A主机和B主机会同时暂停发送!

那么其他主机就可以发送数据了!而等待时间是随机的,所以等待时间相同的概率也很低!A,B主机大概率是不会发生上面的情况(但是也有可能但是概率很低)

==这些就是主机的碰撞检查和碰撞避免算法!==

虽然这些算法很简单粗暴!——但是首先不要高估人们在局域网中传输数据的量!其次不要低估光电信号的传递速度!

我们或许会认为时间很短!很容易发送碰撞——但是局域网本身就不大!而光电信号传输速度就是光速!对于光电信号来说时间不仅够还可能会有剩下的,==所以发送碰撞的概率并不高!==

那么我们不断的向局域网发送垃圾数据,且==不执行碰撞检测和碰撞避免==,来尝试和各种主机的数据进行碰撞!那么局域网所有人的消息是不是发布出去了呢?——是可以的!这种策略也有对应的工具的

保护策略就是——碰撞检测和碰撞避免

==我们重新看待局域网!——主机A和主机B在通信背后其实是两个进程在通信,而我们局域网本质要被所有的主机共享,也就是被主机背后的进程共享,但是为了保证正常通信我们要保证局域网中只有一个主机发消息——也就是只有一个进程能访问!==

==那么局域网可以看做是什么东西呢?——临界资源!——而碰撞检查+碰撞避免就是这个临界资源的保护策略,保证任何一个时刻只有一个主机(进程)能够网临界资源里面写入数据!(这就是临界区)==

使用这样的角度来看待——所谓的令牌环,其实就是一个互斥锁!

==那么局域网能不能很大呢?==

肯定不能!因为局域网很大就意味着主机很多!那么任意时刻发生碰撞的概率就增加了!——就像是一个wife用的人多了就卡了!

==为了解决这个问题——所以我们要引入一个新的概念——交换机!==

交换机这个设备的作用是什么呢?

image-20231106210930830

==所以交换机的核心工作就是分割作用域!==

==所以对于大的局域网,我们一般要加上交换机,用来减少数据碰撞!==

==那么因为有碰撞域的存在,一台主机发送数据的时候,发送的数据量是长好,还是短好?为什么?==

肯定是的短的好!我们可以做一个极端的假设,有一个非常长的数据!这就意味着在局域网中转发时间的长度就会变得更长了!这样子在传输期间就会发生较大概率的碰撞!

==所以数据帧一般不要太大!太大会增加局域网中碰撞的概率!——因此数据帧应该最好有一个传输范围的大小!——这就和我们上面说的MAC帧有效载荷的大小不能超过1500字节对上了!这个最大的大小就是MTU,最小的大小就是46字节——这也是为什说IP协议有一个分片和组装的原因==

对比MAC地址和IP地址

==IP地址描述的是路途总体的 起点 和 终点==;

==MAC地址描述的是路途上的每一个区间的起点和终点;==

主机将数据交付给下一跳(无论是主机还是路由器等其他节点),前提一定是该数据帧被路由过!因为网络层在数据链路层的上层!

MTU介绍

MTU相当于发快递时对包裹尺寸的限制. 这个限制是不同的数据链路对应的物理层, 产生的限制

1.以太网帧中的数据长度规定最小46字节,最大1500字节,ARP数据包的长度不够46字节,要在后面补填充 位

2.最大值1500称为以太网的最大传输单元(MTU),不同的网络类型有不同的MTU;

3.如果一个数据包从以太网路由到拨号链路上,数据包长度大于拨号链路的MTU了,则需要对数据包进行分 片(fragmentation);

4.不同的数据链路层标准的MTU是不同的

MTU对IP协议的影响

由于数据链路层MTU的限制, 对于较大的IP数据包要进行分包.

1.将较大的IP包分成多个小包, 并给每个小包打上标签;

2.每个小包IP协议头的 16位标识(id) 都是相同的;

3.每个小包的IP协议头的3位标志字段中, 第2位置为0, 表示允许分片, 第3位来表示结束标记(当前是否是最 后一个小包, 是的话置为1, 否则置为0);

4.到达对端时再将这些小包, 会按顺序重组, 拼装到一起返回给传输层;

5.一旦这些小包中任意一个小包丢失, 接收端的重组就会失败. 但是IP层不会负责重新传输数据;

image-20231107105508066

==现在有一个问题——分片问题是不是只会由发送端主机来分片?路上的其他节点也会不会对数据进行分片呢?有可能!路上的路由器也可能发生分片!因为大家都用的是TCP/IP协议!所以都是具有分片的能力的!==

为什么会发生这种情况呢?——因为有可能主机的MTU是1500,而路由器的MTU是500,每个设备的MTU不一定是一致的!每个设备都会有自己MTU的规定

如下图

image-20231107112021109

那么我们上面的说的16位标识符,3位表示和3位片偏移能不能继续支撑分片的分片呢?——==肯定可以!==

IP分片后本身就是一个IP报文!我们只要按照正常报文那样进行分片即可!

image-20231107111721177

==然后我们可以发现!——在分片后的报文依旧可以和原来的分片保持偏移量+保温大小 == 下一个分片的偏移量!例如2480+500 == 2980!就找到了最后一个分片!==

我们IP协议里面还有一个不可分片标志位!——这个标志位有什么作用呢?

我们举个例子:我们发送数据在发送之前就分片好了,然后将后续不可以继续分片的报文里面的不可分片标志位设置为1,MTU为1500,那么这也就意味着,一旦路上的路由器,想要将分片进一步分片后,我们就禁止不让它分片!那么该路由器就会将该报文丢弃!那么我们发送方就要超时重传!重新进行路径选择!——==而重新进行路径选择就有可能找到一条允许我用1500字节,从头发到尾的路径!——所以我们就能找到一个最大吞吐量的网络路径!==

==所以不可分片标志位的作用就是帮组我们可以找到那些带宽更大的路由器!==

但是这也不是说,带宽更大的路由器更好!这要看场景!假如我们都是使用的是小数据传输!那么那些带宽小的说不定会更快!

MTU对UDP协议的影响

1.一旦UDP携带的数据超过1472(1500 - 20(IP首部) - 8(UDP首部)), 那么就会在网络层分成多个IP数据报.

2.这多个IP数据报有任意一个丢失, 都会引起接收端网络层重组失败. 那么这就意味着, 如果UDP数据报在 网络层被分片, 整个数据被丢失的概率就大大增加了.

例如:直播的时候,数据量很大!那么影响就很大了!因为会增加丢包的概率!

但是数据量小的时候MTU其实影响就不算很大了!

MTU对于TCP协议的影响

1.TCP的一个数据报也不能无限大, 还是受制于MTU.

2.TCP的单个数据报的最大消息长度, 称为MSS(Max Segment Size);

3.TCP在建立连接的过程中, 通信双方会进行MSS协商. 最理想的情况下, MSS的值正好是在IP不会被分片处理的最大长度(这个长度仍然是受制于数据链路层的 MTU).

4.双方在发送SYN的时候会在TCP头部写入自己能支持的MSS值.

5.然后双方得知对方的MSS值之后, 选择较小的作为最终MSS.

6.MSS的值就是==在TCP首部的40字节变长选项中(kind=2)==

为了尽可能的减少分片!所以就必须让TCP层来控制传输数据的大小!——因为TCP是传输控制协议!

image-20231107165933472

使用指令查看MTU

使用ifconfig命令,即可查看ip地址,mac地址,和MTU;

image-20231107105142248

ARP协议

xXFCwzOQqASE5cI

==为了完成这个认识的过程!——所以我们就必须要有一个新的协议!就是ARP协议!==

否则路由器只知道目标主机的IP地址但是不知道目标主机的MAC地址也是无法传输!

虽然我们在这里介绍ARP协议, 但是需要强调, ARP不是一个单纯的数据链路层的协议, 而是一个介于数据链路层和网络层之间的协议(因为ARP都认识IP了!所以就不仅仅是单纯的是数据链路层了!);

ARP协议的作用

1.在网络通讯时,源主机的应用程序知道目的主机的IP地址和端口号,却不知道目的主机的硬件地址;

2.数据包首先是被网卡接收到再去处理上层协议的,如果接收到的数据包的硬件地址与本机不符,则直接丢弃;

3.因此在通讯前必须获得目的主机的硬件地址;

简单的说就是根据IP来获取,目标主机的MAC地址!

然后用这个MAC地址来封装MAC帧!

ARP协议的原理

我们用一个例子来说明

一个新来的老师,他刚刚接手班级!完全不认识任何一个学生!学校也只给了一张学号纸上面也没有名字,那么他该如何认识这个班级的学生呢?——所以老师就说:同学们,我喊对应的学号,你们把名字告诉我!

所以老师就开始喊了一个学号!老师喊了虽然班级里面的学生都听见了!但是只有对应的学号的学生会对老师进行回应,然后老师在学号的旁边写上同学的名字!

==这样子就建立了一个学号和学生姓名的映射关系!==

有一天,校长来到了教室,拿了一个奖状,跟新老师说:张老师,你们班级10号的同学在竞赛上得了奖了!请转交给他!新老师可能还不认识这个学号的同学,于是先喊了一声10号是谁!张三回答到:10号是张三!然后老师说:张三,你有一张奖状!过来拿,于是10号同学张三里面回应,就跑过来了!然后老师就将奖状给张三!

==在上面的情况中我们假设了一种情况,在学校层面是使用学号进行管理的!但是在上课的时候是使用姓名进行管理的!==

这奖状就是数据报文!但是数据报文上面只有目标同学的学号!但是老师要将奖状给同学就必须知道它的名字!如果老师不认识就现在班级里面喊一声,知道学号对应的同学的名字后,再将数据报文交付给它

image-20231107212103350

==这就是一个宏观的过程!==

ARP数据报的格式

image-20231107172631948

==ARP协议是在MAC帧的上层的!==

image-20231107212942694

==所以我们可以看到,MAC帧协议的有效载荷里面也可以存放ARP的请求和应答!对应的类型是0806==

Quicker_20231107_213400_result

==我们可以从这个图中也可以看出来!进入以太网后既可以走IP协议,也可以走ARP协议== image-20231107215405903

==硬件类型——这个字段是一般是一个固定字段!如果网卡连接的是以太网!那么这个硬件类型永远都是1==

也可能有无线网,令牌环网或者其他类型的网络)其他类型的网络,也有P地址转MAC地址的需求但是无论是什么网络都是用IP地址和MAC地址的!所以才会有硬件类型这个字段!

==硬件地址长度——指的是数据链路层地址(通常是MAC地址)的字节长度。以太网中,MAC地址通常是6个字节长(即48位)==

==协议地址长度——指的是协议地址的长度是4字节,也就是16位的pi地址,这两个都是固定用法!==

==发送端以太网地址,发送端P地址一这两个就是指谁发起的ARP请求!MAC地址是多少!IP地址是多少!==

==目的以太网地址,目的IP地址——是要请求谁的MAC地址,谁的IP地址一用来发送ARP响应==

一般ARP请求是填目的以太网地址的,是全F表示不知道!——我们就是因为不知道所以才需要发起ARP请求的

但是会填目的IP地址!所以就可以通过目的IP地址来找局域网主机!

==op字段一为1表示ARP请求,为2表示ARP应答。==

==再了ARP请求的结构后我们可以实际演示一下==

image-20231108214340105

ARP请求和响应,不止会发生在进入目标主机的子网的入口路由器里面!==但凡是一个路由器从一个子网传输数据到另一个子网的时候,都有可能会发送ARP请求来请求另一个子网的下的某个主机的MAC地址!==路由器和路由器之间也可以发起ARP请求!

一个局域网本身是不大的!——只要有子网掩码!那么我们就可以将子网内的所有IP地址构建出来!例如(255.255.255.0,ip是196.168.3——那么局域网内的范围就是192.168.3.1——192.168.3.254),那么路由器就可以简单粗暴对所有主机发起ARP请求!那么路由器就可以获取这局域网内的所有主机MAC地址和IP地址!——这样就可以在路由器中获取所有主机的情况!

因为有ARP的存在!所有路由器之间可以互相发彼此!就可以通过结合IP地址,来构建出一个更详细的,网络转发的路由表结构!

难道每一次我们就要发起ARP请求么?——刚刚结束,发送给主机C的数据!现在又来了一个新的数据要发送给主机C,路由器是不是又要发送一个ARP请求呢?==不是!ARP的结果是会暂时缓存起来的!第一次不认识!第二次如果很快就来了!就可以直接查缓存表!找到MAC地址发送就行了!==

为什么要清理掉呢?——因为在局域网中IP是会变的!有可能机器上一次接入的IP是192.168.3.1

下一次接入就是192.168.3.111——那么MAC地址和IP的映射关系就发生改变了!所以ARP的缓存是会失效的!

而且如果有点设备想要换网卡!那么MAC地址就发生改变了!

如果是一个永久的表!映射关系永久不变!一个IP就对应了一个MAC那么这就会导致换了网卡后就永远上不了网了!

Quicker_20231107_212156_result

arp缓存是会定期更新的!那么当==收到来自同一个主机的多个arp报文响应==的时候!arp收到应答的时候,会以最新的为主!只记录最新的!

==那么假如出现了如下的情况==

总结

源主机发出ARP请求,询问“IP地址是192.168.0.1的主机的硬件地址是多少”, 并将这个请求广播到本地网 段(以太网帧首部的硬件地址填FF:FF:FF:FF:FF:FF表示广播);

目的主机接收到广播的ARP请求,发现其中的IP地址与本机相符,则发送一个ARP应答数据包给源主机,将自 己的硬件地址填写在应答包中;

每台主机都维护一个ARP缓存表,可以用arp -a命令查看。缓存表中的表项有过期时间(一般为20分钟),如 果20分钟内没有再次使用某个表项,则该表项失效,下次还要发ARP请求来获得目的主机的硬件地址

image-20231107212756059

RARP

如果有一种情况就是我们知道MAC地址,但是不知道IP地址的时候,这种情况存在但是这种情况很少见!

比如:我是一个管理员,内网就是我搭建的!我知道路由器的MAC地址!但是发现数据报转发不出去!想要调试一下!但是我们此时不知道路由器的IP地址!那么此时我们就可以使用RARP(Reverse ARP——逆地址解析),来获取这个IP地址!

==这个过程比ARP过程更加简单!因为ARP我们是不知道MAC地址,所以才需要广播!但是此时我们知道MAC地址只需要,直接封装MAC帧然后请求获取!然后接收方在RARP层里面解包分用,然后将IP地址填入RARP响应发出去即可!==

ARP欺骗

image-20231109111813870

==所以我们有了各种的加密和证书,保证哪怕你拿到了也无法解密!修改了就会被发现!==

==而且如果我们主机3不对报文进行转发!还会导致主机1无法上网!因为主机1找不到路由器了!==

==那么我们如何知道一个局域网下面的设备的MAC地址呢?==

当我们明白了arp是可以被缓存之后,我们可以尝试的ping一下这个服务,因为ping的时候是要找到主机的!所以肯定也会进行arp请求,这个时候——ping是用来检测网络连通性的一条命令!(后文会详细解释)是向目标主机发送DNS报文,让对方进行响应!一旦要连通对方,对方也要给予应答!应答也要知道对方的MAC地址,所以ping的底层就会触发ARP

如果我们的某个地方的地址192.168.3.4子网掩码就是255.255.255.0,我们可以用代码(例如C++),封装一下ping命令,遍历一下局域网内1-254号的所有主机!把每一个局域网主机ping一下!我们就能获取我们局域网下的所有人的所有设备的MAC地址和IP地址!然后对比一下哪一个设备是谁的!我们从此往后就能知道特定主机的MAC地址了!然后如果想要特定的抓取某个主机的数据报!我们只要何其连接同一个局域网即可!——这种抓包前的所有动作我们称之为踩点!