This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,120 @@
<audio id="audio" title="第5讲 | 从物理层到MAC层如何在宿舍里自己组网玩联机游戏" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/c0/4e/c01745571018a2a0dd62c5fa269d644e.mp3"></audio>
上一节我们见证了IP地址的诞生或者说是整个操作系统的诞生。一旦机器有了IP就可以在网络的环境里和其他的机器展开沟通了。
故事就从我的大学宿舍开始讲起吧。作为一个八零后,我要暴露年龄了。
我们宿舍四个人,大一的时候学校不让上网,不给开通网络。但是,宿舍有一个人比较有钱,率先买了一台电脑。那买了电脑干什么呢?
首先,有单机游戏可以打,比如说《拳皇》。两个人用一个键盘,照样打得火热。后来有第二个人买了电脑,那两台电脑能不能连接起来呢?你会说,当然能啊,买个路由器不就行了。
现在一台家用路由器非常便宜,一百多块的事情。那时候路由器绝对是奢侈品。一直到大四,我们宿舍都没有买路由器。可能是因为那时候技术没有现在这么发达,导致我对网络技术的认知是逐渐深入的,而且每一层都是实实在在接触到的。
## 第一层(物理层)
使用路由器,是在第三层上。我们先从第一层物理层开始说。
物理层能折腾啥?现在的同学可能想不到,我们当时去学校配电脑的地方买网线,卖网线的师傅都会问,你的网线是要电脑连电脑啊,还是电脑连网口啊?
我们要的是电脑连电脑。这种方式就是一根网线,有两个头。一头插在一台电脑的网卡上,另一头插在另一台电脑的网卡上。但是在当时,普通的网线这样是通不了的,所以水晶头要做交叉线,用的就是所谓的**13**、**26交叉接法**。
水晶头的第1、2和第3、6脚它们分别起着收、发信号的作用。将一端的1号和3号线、2号和6号线互换一下位置就能够在物理层实现一端发送的信号另一端能收到。
当然电脑连电脑除了网线要交叉还需要配置这两台电脑的IP地址、子网掩码和默认网关。这三个概念上一节详细描述过了。要想两台电脑能够通信这三项必须配置成为一个网络可以一个是192.168.0.1/24另一个是192.168.0.2/24否则是不通的。
这里我想问你一个问题两台电脑之间的网络包包含MAC层吗当然包含要完整。IP层要封装了MAC层才能将包放入物理层。
到此为止,两台电脑已经构成了一个最小的**局域网**,也即**LAN。**可以玩联机局域网游戏啦!
等到第三个哥们也买了一台电脑,怎么把三台电脑连在一起呢?
先别说交换机,当时交换机也贵。有一个叫做**Hub**的东西,也就是**集线器**。这种设备有多个口,可以将宿舍里的多台电脑连接起来。但是,和交换机不同,集线器没有大脑,它完全在物理层工作。它会将自己收到的每一个字节,都复制到其他端口上去。这是第一层物理层联通的方案。
## 第二层(数据链路层)
你可能已经发现问题了。Hub采取的是广播的模式如果每一台电脑发出的包宿舍的每个电脑都能收到那就麻烦了。这就需要解决几个问题
1. 这个包是发给谁的?谁应该接收?
1. 大家都在发,会不会产生混乱?有没有谁先发、谁后发的规则?
1. 如果发送的时候出现了错误,怎么办?
这几个问题都是第二层数据链路层也即MAC层要解决的问题。**MAC**的全称是**Medium Access Control**,即**媒体访问控制。<strong>控制什么呢?其实就是控制在往媒体上发数据的时候,谁先发、谁后发的问题。防止发生混乱。这解决的是第二个问题。这个问题中的规则,学名叫**多路访问</strong>。有很多算法可以解决这个问题。就像车管所管束马路上跑的车,能想的办法都想过了。
比如接下来这三种方式:
<li>
方式一:分多个车道。每个车一个车道,你走你的,我走我的。这在计算机网络里叫作**信道划分;**
</li>
<li>
方式二:今天单号出行,明天双号出行,轮着来。这在计算机网络里叫作**轮流协议;**
</li>
<li>
方式三:不管三七二十一,有事儿先出门,发现特堵,就回去。错过高峰再出。我们叫作**随机接入协议。**著名的以太网,用的就是这个方式。
</li>
解决了第二个问题就是解决了媒体接入控制的问题MAC的问题也就解决好了。这和MAC地址没什么关系。
接下来要解决第一个问题:发给谁,谁接收?这里用到一个物理地址,叫作**链路层地址。<strong>但是因为第二层主要解决媒体接入控制的问题,所以它常被称为**MAC地址</strong>
解决第一个问题就牵扯到第二层的网络包**格式**。对于以太网第二层的最开始就是目标的MAC地址和源的MAC地址。
<img src="https://static001.geekbang.org/resource/image/80/41/8072e4885b0cbc6cb5384ea84d487e41.jpg" alt="">
接下来是**类型**大部分的类型是IP数据包然后IP里面包含TCP、UDP以及HTTP等这都是里层封装的事情。
有了这个目标MAC地址数据包在链路上广播MAC的网卡才能发现这个包是给它的。MAC的网卡把包收进来然后打开IP包发现IP地址也是自己的再打开TCP包发现端口是自己也就是80而nginx就是监听80。
于是将请求提交给nginxnginx返回一个网页。然后将网页需要发回请求的机器。然后层层封装最后到MAC层。因为来的时候有源MAC地址返回的时候源MAC就变成了目标MAC再返给请求的机器。
对于以太网,第二层的最后面是**CRC**,也就是**循环冗余检测**。通过XOR异或的算法来计算整个包是否在发送的过程中出现了错误主要解决第三个问题。
这里还有一个没有解决的问题当源机器知道目标机器的时候可以将目标地址放入包里面如果不知道呢一个广播的网络里面接入了N台机器我怎么知道每个MAC地址是谁呢这就是**ARP协议**也就是已知IP地址求MAC地址的协议。
<img src="https://static001.geekbang.org/resource/image/56/37/561324a275460a4abbc15e73a476e037.jpg" alt="">
在一个局域网里面当知道了IP地址不知道MAC怎么办呢靠“吼”。
<img src="https://static001.geekbang.org/resource/image/48/ad/485b5902066131de547acbcf3579c4ad.jpg" alt="">
广而告之发送一个广播包谁是这个IP谁来回答。具体询问和回答的报文就像下面这样
<img src="https://static001.geekbang.org/resource/image/1f/9b/1f7cfe6046c5df606cfbb6bb6c7f899b.jpg" alt="">
为了避免每次都用ARP请求机器本地也会进行ARP缓存。当然机器会不断地上线下线IP也可能会变所以ARP的MAC地址缓存过一段时间就会过期。
## 局域网
好了至此我们宿舍四个电脑就组成了一个局域网。用Hub连接起来就可以玩局域网版的《魔兽争霸》了。
<img src="https://static001.geekbang.org/resource/image/33/ac/33d180e376439ca10e3f126eb2e36bac.jpg" alt="">
打开游戏,进入“局域网选项”,选择一张地图,点击“创建游戏”,就可以进入这张地图的房间中。等同一个局域网里的其他小伙伴加入后,游戏就可以开始了。
这种组网的方法对一个宿舍来说没有问题但是一旦机器数目增多问题就出现了。因为Hub是广播的不管某个接口是否需要所有的Bit都会被发送出去然后让主机来判断是不是需要。这种方式路上的车少就没问题车一多产生冲突的概率就提高了。而且把不需要的包转发过去纯属浪费。看来Hub这种不管三七二十一都转发的设备是不行了需要点儿智能的。因为每个口都只连接一台电脑这台电脑又不怎么换IP和MAC地址只要记住这台电脑的MAC地址如果目标MAC地址不是这台电脑的这个口就不用转发了。
谁能知道目标MAC地址是否就是连接某个口的电脑的MAC地址呢这就需要一个能把MAC头拿下来检查一下目标MAC地址然后根据策略转发的设备按第二节课中讲过的这个设备显然是个二层设备我们称为**交换机**。
交换机怎么知道每个口的电脑的MAC地址呢这需要交换机会学习。
一台MAC1电脑将一个包发送给另一台MAC2电脑当这个包到达交换机的时候一开始交换机也不知道MAC2的电脑在哪个口所以没办法它只能将包转发给除了来的那个口之外的其他所有的口。但是这个时候交换机会干一件非常聪明的事情就是交换机会记住MAC1是来自一个明确的口。以后有包的目的地址是MAC1的直接发送到这个口就可以了。
当交换机作为一个关卡一样过了一段时间之后就有了整个网络的一个结构了这个时候基本上不用广播了全部可以准确转发。当然每个机器的IP地址会变所在的口也会变因而交换机上的学习的结果我们称为**转发表**,是有一个过期时间的。
有了交换机,一般来说,你接个几十台、上百台机器打游戏,应该没啥问题。你可以组个战队了。能上网了,就可以玩网游了。
## 小结
好了,今天的内容差不多了,我们来总结一下,有三个重点需要你记住:
第一MAC层是用来解决多路访问的堵车问题的
第二ARP是通过吼的方式来寻找目标MAC地址的吼完之后记住一段时间这个叫作缓存
第三交换机是有MAC地址学习能力的学完了它就知道谁在哪儿了不用广播了。
最后,给你留两个思考题吧。
1. 在二层中我们讲了ARP协议即已知IP地址求MAC还有一种RARP协议即已知MAC求IP的你知道它可以用来干什么吗
1. 如果一个局域网里面有多个交换机ARP广播的模式会出现什么问题呢
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,155 @@
<audio id="audio" title="第6讲 | 交换机与VLAN办公室太复杂我要回学校" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/23/0c/2312a98fcc46cea1d9f5e3f3ed16df0c.mp3"></audio>
上一次我们在宿舍里组建了一个本地的局域网LAN可以愉快地玩游戏了。这是一个非常简单的场景因为只有一台交换机电脑数目很少。今天让我们切换到一个稍微复杂一点的场景办公室。
## 拓扑结构是怎么形成的?
我们常见到的办公室大多是一排排的桌子,每个桌子都有网口,一排十几个座位就有十几个网口,一个楼层就会有几十个甚至上百个网口。如果算上所有楼层,这个场景自然比你宿舍里的复杂多了。具体哪里复杂呢?我来给你具体讲解。
首先,这个时候,一个交换机肯定不够用,需要多台交换机,交换机之间连接起来,就形成一个稍微复杂的**拓扑结构**。
我们先来看**两台交换机**的情形。两台交换机连接着三个局域网每个局域网上都有多台机器。如果机器1只知道机器4的IP地址当它想要访问机器4把包发出去的时候它必须要知道机器4的MAC地址。
<img src="https://static001.geekbang.org/resource/image/08/29/0867321c36cc52bd3dd4d7622583fa29.jpg" alt="">
于是机器1发起广播机器2收到这个广播但是这不是找它的所以没它什么事。交换机A一开始是不知道任何拓扑信息的在它收到这个广播后采取的策略是除了广播包来的方向外它还要转发给其他所有的网口。于是机器3也收到广播信息了但是这和它也没什么关系。
当然交换机B也是能够收到广播信息的但是这时候它也是不知道任何拓扑信息的因而也是进行广播的策略将包转发到局域网三。这个时候机器4和机器5都收到了广播信息。机器4主动响应说这是找我的这是我的MAC地址。于是一个ARP请求就成功完成了。
在上面的过程中交换机A和交换机B都是能够学习到这样的信息机器1是在左边这个网口的。当了解到这些拓扑信息之后情况就好转起来。当机器2要访问机器1的时候机器2并不知道机器1的MAC地址所以机器2会发起一个ARP请求。这个广播消息会到达机器1也同时会到达交换机A。这个时候交换机A已经知道机器1是不可能在右边的网口的所以这个广播信息就不会广播到局域网二和局域网三。
当机器3要访问机器1的时候也需要发起一个广播的ARP请求。这个时候交换机A和交换机B都能够收到这个广播请求。交换机A当然知道主机A是在左边这个网口的所以会把广播消息转发到局域网一。同时交换机B收到这个广播消息之后由于它知道机器1是不在右边这个网口的所以不会将消息广播到局域网三。
## 如何解决常见的环路问题?
这样看起来,两台交换机工作得非常好。随着办公室越来越大,交换机数目肯定越来越多。当整个拓扑结构复杂了,这么多网线,绕过来绕过去,不可避免地会出现一些意料不到的情况。其中常见的问题就是**环路问题**。
例如这个图,当两个交换机将两个局域网同时连接起来的时候。你可能会觉得,这样反而有了高可用性。但是却不幸地出现了环路。出现了环路会有什么结果呢?
<img src="https://static001.geekbang.org/resource/image/1f/ea/1f909508a8253d4842ffe962883421ea.jpg" alt="">
我们来想象一下机器1访问机器2的过程。一开始机器1并不知道机器2的MAC地址所以它需要发起一个ARP的广播。广播到达机器2机器2会把MAC地址返回来看起来没有这两个交换机什么事情。
但是问题来了这两个交换机还是都能够收到广播包的。交换机A一开始是不知道机器2在哪个局域网的所以它会把广播消息放到局域网二在局域网二广播的时候交换机B右边这个网口也是能够收到广播消息的。交换机B会将这个广播信息发送到局域网一。局域网一的这个广播消息又会到达交换机A左边的这个接口。交换机A这个时候还是不知道机器2在哪个局域网于是将广播包又转发到局域网二。左转左转左转好像是个圈哦。
可能有人会说,当两台交换机都能够逐渐学习到拓扑结构之后,是不是就可以了?
别想了压根儿学不会的。机器1的广播包到达交换机A和交换机B的时候本来两个交换机都学会了机器1是在局域网一的但是当交换机A将包广播到局域网二之后交换机B右边的网口收到了来自交换机A的广播包。根据学习机制这彻底损坏了交换机B的三观刚才机器1还在左边的网口呢怎么又出现在右边的网口呢那肯定是机器1换位置了于是就误会了交换机B就学会了机器1是从右边这个网口来的把刚才学习的那一条清理掉。同理交换机A右边的网口也能收到交换机B转发过来的广播包同样也误会了于是也学会了机器1从右边的网口来不是从左边的网口来。
然而当广播包从左边的局域网一广播的时候两个交换机再次刷新三观原来机器1是在左边的过一会儿又发现不对是在右边的过一会又发现不对是在左边的。
这还是一个包转来转去,每台机器都会发广播包,交换机转发也会复制广播包,当广播包越来越多的时候,按照上一节讲过一个共享道路的算法,也就是路会越来越堵,最后谁也别想走。所以,必须有一个方法解决环路的问题,怎么破除环路呢?
## STP协议中那些难以理解的概念
在数据结构中,有一个方法叫做**最小生成树**。有环的我们常称为**图**。将图中的环破了,就生成了**树**。在计算机网络中,生成树的算法叫作**STP**,全称**Spanning Tree Protocol**。
STP协议比较复杂一开始很难看懂但是其实这是一场血雨腥风的武林比武或者华山论剑最终决出五岳盟主的方式。
<img src="https://static001.geekbang.org/resource/image/47/23/47baa69073b38357e0ae3f88ff74dd23.jpg" alt="">
在STP协议里面有很多概念译名就非常拗口但是我一作比喻你很容易就明白了。
<li>
**Root Bridge**,也就是**根交换机**。这个比较容易理解,可以比喻为“掌门”交换机,是某棵树的老大,是掌门,最大的大哥。
</li>
<li>
**Designated Bridges**,有的翻译为**指定交换机**。这个比较难理解,可以想像成一个“小弟”,对于树来说,就是一棵树的树枝。所谓“指定”的意思是,我拜谁做大哥,其他交换机通过这个交换机到达根交换机,也就相当于拜他做了大哥。这里注意是树枝,不是叶子,因为叶子往往是主机。
</li>
<li>
**Bridge Protocol Data Units BPDU** **网桥协议数据单元**。可以比喻为“相互比较实力”的协议。行走江湖比的就是武功拼的就是实力。当两个交换机碰见的时候也就是相连的时候就需要互相比一比内力了。BPDU只有掌门能发已经隶属于某个掌门的交换机只能传达掌门的指示。
</li>
<li>
**Priority Vector****优先级向量**。可以比喻为实力 值越小越牛。实力是啥就是一组ID数目[Root Bridge ID, Root Path Cost, Bridge ID, and Port ID]。为什么这样设计呢这是因为要看怎么来比实力。先看Root Bridge ID。拿出老大的ID看看发现掌门一样那就是师兄弟再比Root Path Cost也即我距离我的老大的距离也就是拿和掌门关系比看同一个门派内谁和老大关系铁最后比Bridge ID比我自己的ID拿自己的本事比。
</li>
## STP的工作过程是怎样的
接下来我们来看STP的工作过程。
一开始江湖纷争异常混乱。大家都觉得自己是掌门谁也不服谁。于是所有的交换机都认为自己是掌门每个网桥都被分配了一个ID。这个ID里有管理员分配的优先级当然网络管理员知道哪些交换机贵哪些交换机好就会给它们分配高的优先级。这种交换机生下来武功就很高起步就是乔峰。
<img src="https://static001.geekbang.org/resource/image/66/2b/66237be156bea81a801dca8d507c1e2b.jpg" alt="">
既然都是掌门互相都连着网线就互相发送BPDU来比功夫呗。这一比就发现有人是岳不群有人是封不平赢的接着当掌门输的就只好做小弟了。当掌门的还会继续发BPDU而输的人就没有机会了。它们只有在收到掌门发的BPDU的时候转发一下表示服从命令。
<img src="https://static001.geekbang.org/resource/image/5d/47/5da50b7e328ea3cf8f90430f1deb3f47.jpg" alt="">
数字表示优先级。就像这个图5和6碰见了6的优先级低所以乖乖做小弟。于是一个小门派形成5是掌门6是小弟。其他诸如1-7、2-8、3-4这样的小门派也诞生了。于是江湖出现了很多小的门派小的门派接着合并。
合并的过程会出现以下四种情形,我分别来介绍。
### 情形一:掌门遇到掌门
当5碰到了1掌门碰见掌门1觉得自己是掌门5也刚刚跟别人PK完成为掌门。这俩掌门比较功夫最终1胜出。于是输掉的掌门5就会率领所有的小弟归顺。结果就是1成为大掌门。
<img src="https://static001.geekbang.org/resource/image/fb/56/fb0e19a14e00b5825dac11d359ffe056.jpg" alt="">
### 情形二:同门相遇
同门相遇可以是掌门与自己的小弟相遇这说明存在“环”了。这个小弟已经通过其他门路拜在你门下结果你还不认识就PK了一把。结果掌门发现这个小弟功夫不错不应该级别这么低就把它招到门下亲自带那这个小弟就相当于升职了。
我们再来看假如1和6相遇。6原来就拜在1的门下只不过6的上司是55的上司是1。1发现6距离我才只有2比从5这里过来的5=4+1近多了那6就直接汇报给我吧。于是5和6分别汇报给1。
<img src="https://static001.geekbang.org/resource/image/1e/d8/1ef3c9fb5b7d386c519402202233a8d8.jpg" alt="">
同门相遇还可以是小弟相遇。这个时候就要比较谁和掌门的关系近当然近的当大哥。刚才5和6同时汇报给1了后来5和6在比较功夫的时候发现5你直接汇报给1距离是4如果5汇报给6再汇报给1距离只有2+1=3所以5干脆拜6为上司。
### 情形三:掌门与其他帮派小弟相遇
小弟拿本帮掌门和这个掌门比较,赢了,这个掌门拜入门来。输了,会拜入新掌门,并且逐渐拉拢和自己连接的兄弟,一起弃暗投明。
<img src="https://static001.geekbang.org/resource/image/8e/da/8e852604ac81ab453115470edb9e70da.jpg" alt="">
例如2和7相遇虽然7是小弟2是掌门。就个人武功而言2比7强但是7的掌门是1比2牛所以没办法2要拜入7的门派并且连同自己的小弟都一起拜入。
### 情形四:不同门小弟相遇
各自拿掌门比较,输了的拜入赢的门派,并且逐渐将与自己连接的兄弟弃暗投明。<br>
<img src="https://static001.geekbang.org/resource/image/fd/bf/fdab777fb2f69666e1fd5d838278b1bf.jpg" alt="">
例如5和4相遇。虽然4的武功好于5但是5的掌门是1比4牛于是4拜入5的门派。后来当3和4相遇的时候3发现4已经叛变了4说我现在老大是1比你牛要不你也来吧于是3也拜入1。
最终,生成一棵树,武林一统,天下太平。但是天下大势,分久必合,合久必分,天下统一久了,也会有相应的问题。
### 如何解决广播问题和安全问题?
毕竟机器多了交换机也多了就算交换机比Hub智能一些但是还是难免有广播的问题一大波机器相关的部门、不相关的部门广播一大堆性能就下来了。就像一家公司创业的时候一二十个人坐在一个会议室有事情大家讨论一下非常方便。但是如果变成了50个人全在一个会议室里面吵吵就会乱得不得了。
你们公司有不同的部门有的部门需要保密的比如人事部门肯定要讨论升职加薪的事儿。由于在同一个广播域里面很多包都会在一个局域网里面飘啊飘碰到了一个会抓包的程序员就能抓到这些包如果没有加密就能看到这些敏感信息了。还是上面的例子50个人在一个会议室里面七嘴八舌地讨论其中有两个HR那他们讨论的问题肯定被其他人偷偷听走了。
那咋办,分部门,分会议室呗。那我们就来看看怎么分。
有两种分的方法,一个是**物理隔离**。每个部门设一个单独的会议室,对应到网络方面,就是每个部门有单独的交换机,配置单独的子网,这样部门之间的沟通就需要路由器了。路由器咱们还没讲到,以后再说。这样的问题在于,有的部门人多,有的部门人少。人少的部门慢慢人会变多,人多的部门也可能人越变越少。如果每个部门有单独的交换机,口多了浪费,少了又不够用。
另外一种方式是**虚拟隔离**,就是用我们常说的**VLAN**,或者叫**虚拟局域网**。使用VLAN一个交换机上会连属于多个局域网的机器那交换机怎么区分哪个机器属于哪个局域网呢<br>
<img src="https://static001.geekbang.org/resource/image/ba/60/ba720f6988558f95c381f4deaab11660.jpg" alt="">
我们只需要在原来的二层的头上加一个TAG里面有一个VLAN ID一共12位。为什么是12位呢因为12位可以划分4096个VLAN。这样是不是还不够啊。现在的情况证明目前云计算厂商里面绝对不止4096个用户。当然每个用户需要一个VLAN了啊怎么办呢这个我们在后面的章节再说。
如果我们买的交换机是支持VLAN的当这个交换机把二层的头取下来的时候就能够识别这个VLAN ID。这样只有相同VLAN的包才会互相转发不同VLAN的包是看不到的。这样广播问题和安全问题就都能够解决了。<br>
<img src="https://static001.geekbang.org/resource/image/5c/4a/5c207a6e2c1c9881823b04e648f4ba4a.jpg" alt="">
我们可以设置交换机每个口所属的VLAN。如果某个口坐的是程序员他们属于VLAN 10如果某个口坐的是人事他们属于VLAN 20如果某个口坐的是财务他们属于VLAN 30。这样财务发的包交换机只会转发到VLAN 30的口上。程序员啊你就监听VLAN 10吧里面除了代码啥都没有。
而且对于交换机来讲每个VLAN的口都是可以重新设置的。一个财务走了把他所在座位的口从VLAN 30移除掉来了一个程序员坐在财务的位置上就把这个口设置为VLAN 10十分灵活。
有人会问交换机之间怎么连接呢将两个交换机连接起来的口应该设置成什么VLAN呢对于支持VLAN的交换机有一种口叫作**Trunk口**。它可以转发属于任何VLAN的口。交换机之间可以通过这种口相互连接。
好了,解决这么多交换机连接在一起的问题,办公室的问题似乎搞定了。然而这只是一般复杂的场景,因为你能接触到的网络,到目前为止,不管是你的台式机,还是笔记本所连接的网络,对于带宽、高可用等都要求不高。就算出了问题,一会儿上不了网,也不会有什么大事。
我们在宿舍、学校或者办公室,经常会访问一些网站,这些网站似乎永远不会“挂掉”。那是因为这些网站都生活在一个叫做数据中心的地方,那里的网络世界更加复杂。在后面的章节,我会为你详细讲解。
## 小结
好了,这节就到这里,我们这里来总结一下:
- 当交换机的数目越来越多的时候会遭遇环路问题让网络包迷路这就需要使用STP协议通过华山论剑比武的方式将有环路的图变成没有环路的树从而解决环路问题。
- 交换机数目多会面临隔离问题可以通过VLAN形成虚拟局域网从而解决广播问题和安全问题。
最后,给你留两个思考题。
1. STP协议能够很好地解决环路问题但是也有它的缺点你能举几个例子吗
1. 在一个比较大的网络中,如果两台机器不通,你知道应该用什么方式调试吗?
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,118 @@
<audio id="audio" title="第7讲 | ICMP与ping投石问路的侦察兵" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/24/ad/2486b041bd60d50f2c45a19ce827e8ad.mp3"></audio>
无论是在宿舍,还是在办公室,或者运维一个数据中心,我们常常会遇到网络不通的问题。那台机器明明就在那里,你甚至都可以通过机器的终端连上去看。它看着好好的,可是就是连不上去,究竟是哪里出了问题呢?
## ICMP协议的格式
一般情况下你会想到ping一下。那你知道ping是如何工作的吗
ping是基于ICMP协议工作的。**ICMP**全称**Internet Control Message Protocol**,就是**互联网控制报文协议**。这里面的关键词是“控制”,那具体是怎么控制的呢?
网络包在异常复杂的网络环境中传输时,常常会遇到各种各样的问题。当遇到问题的时候,总不能“死个不明不白”,要传出消息来,报告情况,这样才可以调整传输策略。这就相当于我们经常看到的电视剧里,古代行军的时候,为将为帅者需要通过侦察兵、哨探或传令兵等人肉的方式来掌握情况,控制整个战局。
ICMP报文是封装在IP包里面的。因为传输指令的时候肯定需要源地址和目标地址。它本身非常简单。因为作为侦查兵要轻装上阵不能携带大量的包袱。
<img src="https://static001.geekbang.org/resource/image/20/e2/201589bb205c5b00ad42e0081aa46fe2.jpg" alt="">
ICMP报文有很多的类型不同的类型有不同的代码。**最常用的类型是主动请求为8主动请求的应答为0**。
## 查询报文类型
我们经常在电视剧里听到这样的话:主帅说,来人哪!前方战事如何,快去派人打探,一有情况,立即通报!
这种是主帅发起的主动查看敌情对应ICMP的**查询报文类型**。例如,常用的**ping就是查询报文是一种主动请求并且获得主动应答的ICMP协议。**所以ping发的包也是符合ICMP协议格式的只不过它在后面增加了自己的格式。
对ping的主动请求进行网络抓包称为**ICMP ECHO REQUEST。<strong>同理主动请求的回复,称为**ICMP ECHO REPLY</strong>。比起原生的ICMP这里面多了两个字段一个是**标识符**。这个很好理解,你派出去两队侦查兵,一队是侦查战况的,一队是去查找水源的,要有个标识才能区分。另一个是**序号**你派出去的侦查兵都要编个号。如果派出去10个回来10个就说明前方战况不错如果派出去10个回来2个说明情况可能不妙。
在选项数据中ping还会存放发送请求的时间值来计算往返时间说明路程的长短。
## 差错报文类型
当然也有另外一种方式,就是差错报文。
主帅骑马走着走着突然来了一匹快马上面的小兵气喘吁吁的报告主公不好啦张将军遭遇埋伏全军覆没啦这种是异常情况发起的来报告发生了不好的事情对应ICMP的**差错报文类型**。
我举几个ICMP差错报文的例子**终点不可达为3源抑制为4超时为11重定向为5**。这些都是什么意思呢?我给你具体解释一下。
**第一种是终点不可达**。小兵:报告主公,您让把粮草送到张将军那里,结果没有送到。
如果你是主公你肯定会问为啥送不到具体的原因在代码中表示就是网络不可达代码为0主机不可达代码为1协议不可达代码为2端口不可达代码为3需要进行分片但设置了不分片位代码为4。
具体的场景就像这样:
- 网络不可达:主公,找不到地方呀?
- 主机不可达:主公,找到地方没这个人呀?
- 协议不可达主公找到地方找到人口号没对上人家天王盖地虎我说12345
- 端口不可达:主公,找到地方,找到人,对了口号,事儿没对上,我去送粮草,人家说他们在等救兵。
- 需要进行分片但设置了不分片位:主公,走到一半,山路狭窄,想换小车,但是您的将令,严禁换小车,就没办法送到了。
**第二种是源站抑制**,也就是让源站放慢发送速度。小兵:报告主公,您粮草送的太多了吃不完。
**第三种是时间超时**,也就是超过网络包的生存时间还是没到。小兵:报告主公,送粮草的人,自己把粮草吃完了,还没找到地方,已经饿死啦。
**第四种是路由重定向**,也就是让下次发给另一个路由器。小兵:报告主公,上次送粮草的人本来只要走一站地铁,非得从五环绕,下次别这样了啊。
差错报文的结构相对复杂一些。除了前面还是IPICMP的前8字节不变后面则跟上出错的那个IP包的IP头和IP正文的前8个字节。
而且这类侦查兵特别恪尽职守,不但自己返回来报信,还把一部分遗物也带回来。
- 侦察兵:报告主公,张将军已经战死沙场,这是张将军的印信和佩剑。
- 主公神马张将军是怎么死的可以查看ICMP的前8字节没错这是张将军的剑是他的剑IP数据包的头及正文前8字节
## ping查询报文类型的使用
接下来我们重点来看ping的发送和接收过程。
<img src="https://static001.geekbang.org/resource/image/57/21/57a77fb89bc4a5653842276c70c0d621.jpg" alt="">
假定主机A的IP地址是192.168.1.1主机B的IP地址是192.168.1.2它们都在同一个子网。那当你在主机A上运行“ping 192.168.1.2”后,会发生什么呢?
ping命令执行的时候源主机首先会构建一个ICMP请求数据包ICMP数据包内包含多个字段。最重要的是两个第一个是**类型字段**,对于请求数据包而言该字段为 8另外一个是**顺序号**主要用于区分连续ping的时候发出的多个数据包。每发出一个请求数据包顺序号会自动加1。为了能够计算往返时间RTT它会在报文的数据部分插入发送时间。
然后由ICMP协议将这个数据包连同地址192.168.1.2一起交给IP层。IP层将以192.168.1.2作为目的地址本机IP地址作为源地址加上一些其他控制信息构建一个IP数据包。
接下来需要加入MAC头。如果在本节ARP映射表中查找出IP地址192.168.1.2所对应的MAC地址则可以直接使用如果没有则需要发送ARP协议查询MAC地址获得MAC地址后由数据链路层构建一个数据帧目的地址是IP层传过来的MAC地址源地址则是本机的MAC地址还要附加上一些控制信息依据以太网的介质访问规则将它们传送出去。
主机B收到这个数据帧后先检查它的目的MAC地址并和本机的MAC地址对比如符合则接收否则就丢弃。接收后检查该数据帧将IP数据包从帧中提取出来交给本机的IP层。同样IP层检查后将有用的信息提取后交给ICMP协议。
主机B会构建一个 ICMP 应答包,应答数据包的类型字段为 0顺序号为接收到的请求数据包中的顺序号然后再发送出去给主机A。
在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明目标主机不可达;如果接收到了 ICMP 应答包,则说明目标主机可达。此时,源主机会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是 ICMP 数据包的时间延迟。
当然这只是最简单的同一个局域网里面的情况。如果跨网段的话还会涉及网关的转发、路由器的转发等等。但是对于ICMP的头来讲是没什么影响的。会影响的是根据目标IP地址选择路由的下一跳还有每经过一个路由器到达一个新的局域网需要换MAC头里面的MAC地址。这个过程后面几节会详细描述这里暂时不多说。
如果在自己的可控范围之内当遇到网络不通的问题的时候除了直接ping目标的IP地址之外还应该有一个清晰的网络拓扑图。并且从理论上来讲应该要清楚地知道一个网络包从源地址到目标地址都需要经过哪些设备然后逐个ping中间的这些设备或者机器。如果可能的话在这些关键点通过tcpdump -i eth0 icmp查看包有没有到达某个点回复的包到达了哪个点可以更加容易推断出错的位置。
经常会遇到一个问题如果不在我们的控制范围内很多中间设备都是禁止ping的但是ping不通不代表网络不通。这个时候就要使用telnet通过其他协议来测试网络是否通这个就不在本篇的讲述范围了。
说了这么多你应该可以看出ping这个程序是使用了ICMP里面的ECHO REQUEST和ECHO REPLY类型的。
## Traceroute差错报文类型的使用
那其他的类型呢是不是只有真正遇到错误的时候才能收到呢那也不是有一个程序Traceroute是个“大骗子”。它会使用ICMP的规则故意制造一些能够产生错误的场景。
所以,**Traceroute的第一个作用就是故意设置特殊的TTL来追踪去往目的地时沿途经过的路由器**。Traceroute的参数指向某个目的IP地址它会发送一个UDP的数据包。将TTL设置成1也就是说一旦遇到一个路由器或者一个关卡就表示它“牺牲”了。
如果中间的路由器不止一个当然碰到第一个就“牺牲”。于是返回一个ICMP包也就是网络差错包类型是时间超时。那大军前行就带一顿饭试一试走多远会被饿死然后找个哨探回来报告那我就知道大军只带一顿饭能走多远了。
接下来将TTL设置为2。第一关过了第二关就“牺牲”了那我就知道第二关有多远。如此反复直到到达目的主机。这样Traceroute就拿到了所有的路由器IP。当然有的路由器压根不会回这个ICMP。这也是Traceroute一个公网的地址看不到中间路由的原因。
怎么知道UDP有没有到达目的主机呢Traceroute程序会发送一份UDP数据报给目的主机但它会选择一个不可能的值作为UDP端口号大于30000。当该数据报到达时将使目的主机的 UDP模块产生一份“端口不可达”错误ICMP报文。如果数据报没有到达则可能是超时。
这就相当于故意派人去西天如来那里去请一本《道德经》结果人家信佛不信道消息就会被打出来。被打的消息传回来你就知道西天是能够到达的。为什么不去取《心经》呢因为UDP是无连接的。也就是说这人一派出去你就得不到任何音信。你无法区别到底是半路走丢了还是真的信佛遁入空门了只有让人家打出来你才会得到消息。
**Traceroute还有一个作用是故意设置不分片从而确定路径的MTU。**要做的工作首先是发送分组并设置“不分片”标志。发送的第一个分组的长度正好与出口MTU相等。如果中间遇到窄的关口会被卡住会发送ICMP网络差错包类型为“需要进行分片但设置了不分片位”。其实这是人家故意的好吧每次收到ICMP“不能分片”差错时就减小分组的长度直到到达目标主机。
## 小结
好了,这一节内容差不多了,我来总结一下:
- ICMP相当于网络世界的侦察兵。我讲了两种类型的ICMP报文一种是主动探查的查询报文一种异常报告的差错报文
- ping使用查询报文Traceroute使用差错报文。
最后,给你留两个思考题吧。
1. 当发送的报文出问题的时候会发送一个ICMP的差错报文来报告错误但是如果ICMP的差错报文也出问题了呢
1. 这一节只说了一个局域网互相ping的情况。如果跨路由器、跨网关的过程会是什么样的呢
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,222 @@
<audio id="audio" title="第8讲 | 世界这么大,我想出网关:欧洲十国游与玄奘西行" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/fb/b1/fb36e0987432e257d1226e874a77bab1.mp3"></audio>
前几节,我主要跟你讲了宿舍里和办公室里用到的网络协议。你已经有了一些基础,是时候去外网逛逛了!
## 怎么在宿舍上网?
还记得咱们在宿舍的时候买了台交换机几台机器组了一个局域网打游戏吗可惜啊只能打局域网的游戏不能上网啊盼啊盼啊终于盼到大二允许宿舍开通网络了。学校给每个宿舍的网口分配了一个IP地址。这个IP是校园网的IP完全由网管部门控制。宿舍网的IP地址多为192.168.1.x。校园网的IP地址假设是10.10.x.x。
这个时候,你要在宿舍上网,有两个办法:
第一个办法让你们宿舍长再买一个网卡。这个时候你们宿舍长的电脑里就有两张网卡。一张网卡的线插到你们宿舍的交换机上另一张网卡的线插到校园网的网口。而且这张新的网卡的IP地址要按照学校网管部门分配的配置不然上不了网。**这种情况下,如果你们宿舍的人要上网,就需要一直开着宿舍长的电脑。**
第二个办法,你们共同出钱买个家庭路由器(反正当时我们买不起)。家庭路由器会有内网网口和外网网口。把外网网口的线插到校园网的网口上,将这个外网网口配置成和网管部的一样。内网网口连上你们宿舍的所有的电脑。**这种情况下,如果你们宿舍的人要上网,就需要一直开着路由器。**
这两种方法其实是一样的。只不过第一种方式,让你的宿舍长的电脑,变成一个有多个口的路由器而已。而你买的家庭路由器,里面也跑着程序,和你宿舍长电脑里的功能一样,只不过是一个嵌入式的系统。
当你的宿舍长能够上网之后,接下来,就是其他人的电脑怎么上网的问题。这就需要配置你们的**网卡。<strong>当然DHCP是可以默认配置的。在进行网卡配置的时候除了IP地址还需要配置一个**Gateway</strong>的东西,这个就是**网关**。
## 你了解MAC头和IP头的细节吗
一旦配置了IP地址和网关往往就能够指定目标地址进行访问了。由于在跨网关访问的时候牵扯到MAC地址和IP地址的变化这里有必要详细描述一下MAC头和IP头的细节。
<img src="https://static001.geekbang.org/resource/image/82/65/825e54560a6de08a32e4cab4e0f59f65.jpg" alt="">
在MAC头里面先是目标MAC地址然后是源MAC地址然后有一个协议类型用来说明里面是IP协议。IP头里面的版本号目前主流的还是IPv4服务类型TOS在第三节讲ip addr命令的时候讲过TTL在第7节讲ICMP协议的时候讲过。另外还有8位标识协议。这里到了下一层的协议也就是是TCP还是UDP。最重要的就是源IP和目标IP。先是源IP地址然后是目标IP地址。
在任何一台机器上当要访问另一个IP地址的时候都会先判断这个目标IP地址和当前机器的IP地址是否在同一个网段。怎么判断同一个网段呢需要CIDR和子网掩码这个在第三节的时候也讲过了。
**如果是同一个网段**例如你访问你旁边的兄弟的电脑那就没网关什么事情直接将源地址和目标地址放入IP头中然后通过ARP获得MAC地址将源MAC和目的MAC放入MAC头中发出去就可以了。
**如果不是同一网段**例如你要访问你们校园网里面的BBS该怎么办这就需要发往默认网关Gateway。Gateway的地址一定是和源IP地址是一个网段的。往往不是第一个就是第二个。例如192.168.1.0/24这个网段Gateway往往会是192.168.1.1/24或者192.168.1.2/24。
如何发往默认网关呢网关不是和源IP地址是一个网段的么这个过程就和发往同一个网段的其他机器是一样的将源地址和目标IP地址放入IP头中通过ARP获得网关的MAC地址将源MAC和网关的MAC放入MAC头中发送出去。网关所在的端口例如192.168.1.1/24将网络包收进来然后接下来怎么做就完全看网关的了。
**网关往往是一个路由器,是一个三层转发的设备。**啥叫三层设备前面也说过了就是把MAC头和IP头都取下来然后根据里面的内容看看接下来把包往哪里转发的设备。
在你的宿舍里面网关就是你宿舍长的电脑。一个路由器往往有多个网口如果是一台服务器做这个事情则就有多个网卡其中一个网卡是和源IP同网段的。
很多情况下,人们把网关就叫做路由器。其实不完全准确,而另一种比喻更加恰当:**路由器是一台设备它有五个网口或者网卡相当于有五只手分别连着五个局域网。每只手的IP地址都和局域网的IP地址相同的网段每只手都是它握住的那个局域网的网关。**
任何一个想发往其他局域网的包都会到达其中一只手被拿进来拿下MAC头和IP头看看根据自己的路由算法选择另一只手加上IP头和MAC头然后扔出去。
## 静态路由是什么?
这个时候问题来了该选择哪一只手IP头和MAC头加什么内容哪些变、哪些不变呢这个问题比较复杂大致可以分为两类一个是**静态路由**,一个是**动态路由**。动态路由下一节我们详细地讲。这一节我们先说静态路由。
**静态路由,其实就是在路由器上,配置一条一条规则。**这些规则包括想访问BBS站它肯定有个网段从2号口出去下一跳是IP2想访问教学视频站它也有个自己的网段从3号口出去下一跳是IP3然后保存在路由器里。
每当要选择从哪只手抛出去的时候就一条一条的匹配规则找到符合的规则就按规则中设置的那样从某个口抛出去找下一跳IPX。
## IP头和MAC头哪些变、哪些不变
对于IP头和MAC头哪些变、哪些不变的问题可以分两种类型。我把它们称为“**欧洲十国游”型**和“**玄奘西行”型**。
之前我说过MAC地址是一个局域网内才有效的地址。因而MAC地址只要过网关就必定会改变因为已经换了局域网。两者主要的区别在于IP地址是否改变。不改变IP地址的网关我们称为**转发网关;<strong>改变IP地址的网关我们称为**NAT网关</strong>
### “欧洲十国游”型
结合这个图,我们先来看“欧洲十国游”型。
<img src="https://static001.geekbang.org/resource/image/1d/8c/1d604f88456096a73e40437d8f9e458c.jpg" alt="">
服务器A要访问服务器B。首先服务器A会思考192.168.4.101和我不是一个网段的因而需要先发给网关。那网关是谁呢已经静态配置好了网关是192.168.1.1。网关的MAC地址是多少呢发送ARP获取网关的MAC地址然后发送包。包的内容是这样的
<li>
源MAC服务器A的MAC
</li>
<li>
目标MAC192.168.1.1这个网口的MAC
</li>
<li>
源IP192.168.1.101
</li>
<li>
目标IP192.168.4.101
</li>
包到达192.168.1.1这个网口发现MAC一致将包收进来开始思考往哪里转发。
在路由器A中配置了静态路由之后要想访问192.168.4.0/24要从192.168.56.1这个口出去下一跳为192.168.56.2。
于是路由器A思考的时候匹配上了这条路由要从192.168.56.1这个口发出去发给192.168.56.2那192.168.56.2的MAC地址是多少呢路由器A发送ARP获取192.168.56.2的MAC地址然后发送包。包的内容是这样的
<li>
源MAC192.168.56.1的MAC地址
</li>
<li>
目标MAC192.168.56.2的MAC地址
</li>
<li>
源IP192.168.1.101
</li>
<li>
目标IP192.168.4.101
</li>
包到达192.168.56.2这个网口发现MAC一致将包收进来开始思考往哪里转发。
在路由器B中配置了静态路由要想访问192.168.4.0/24要从192.168.4.1这个口出去,没有下一跳了。因为我右手这个网卡,就是这个网段的,我是最后一跳了。
于是路由器B思考的时候匹配上了这条路由要从192.168.4.1这个口发出去发给192.168.4.101。那192.168.4.101的MAC地址是多少呢路由器B发送ARP获取192.168.4.101的MAC地址然后发送包。包的内容是这样的
<li>
源MAC192.168.4.1的MAC地址
</li>
<li>
目标MAC192.168.4.101的MAC地址
</li>
<li>
源IP192.168.1.101
</li>
<li>
目标IP192.168.4.101
</li>
包到达服务器BMAC地址匹配将包收进来。
通过这个过程可以看出每到一个新的局域网MAC都是要变的但是IP地址都不变。在IP头里面不会保存任何网关的IP地址。**所谓的下一跳是某个IP要将这个IP地址转换为MAC放入MAC头。**
之所以将这种模式比喻称为欧洲十国游是因为在整个过程中IP头里面的地址都是不变的。IP地址在三个局域网都可见在三个局域网之间的网段都不会冲突。在三个网段之间传输包IP头不改变。这就像在欧洲各国之间旅游一个签证就能搞定。
<img src="https://static001.geekbang.org/resource/image/35/3b/35fb548bbaa7d77012ab46151bfbe63b.jpg" alt="">
### “玄奘西行”型
我们再来看“玄奘西行”型。
这里遇见的第一个问题是局域网之间没有商量过各定各的网段因而IP段冲突了。最左面大唐的地址是192.168.1.101最右面印度的地址也是192.168.1.101如果单从IP地址上看简直是自己访问自己其实是大唐的192.168.1.101要访问印度的192.168.1.101。
怎么解决这个问题呢?既然局域网之间没有商量过,你们各管各的,那到国际上,也即中间的局域网里面,就需要使用另外的地址。就像出国,不能用咱们自己的身份证,而要改用护照一样,玄奘西游也要拿着专门取经的通关文牒,而不能用自己国家的身份证。
首先目标服务器B在国际上要有一个国际的身份我们给它一个192.168.56.2。在网关B上我们记下来国际身份192.168.56.2对应国内身份192.168.1.101。凡是要访问192.168.56.2都转成192.168.1.101。
于是源服务器A要访问目标服务器B要指定的目标地址为192.168.56.2。这是它的国际身份。服务器A想192.168.56.2和我不是一个网段的因而需要发给网关网关是谁已经静态配置好了网关是192.168.1.1网关的MAC地址是多少发送ARP获取网关的MAC地址然后发送包。包的内容是这样的
<li>
源MAC服务器A的MAC
</li>
<li>
目标MAC192.168.1.1这个网口的MAC
</li>
<li>
源IP192.168.1.101
</li>
<li>
目标IP192.168.56.2
</li>
包到达192.168.1.1这个网口发现MAC一致将包收进来开始思考往哪里转发。
在路由器A中配置了静态路由要想访问192.168.56.2/24要从192.168.56.1这个口出去,没有下一跳了,因为我右手这个网卡,就是这个网段的,我是最后一跳了。
于是路由器A思考的时候匹配上了这条路由要从192.168.56.1这个口发出去发给192.168.56.2。那192.168.56.2的MAC地址是多少呢路由器A发送ARP获取192.168.56.2的MAC地址。
当网络包发送到中间的局域网的时候服务器A也需要有个国际身份因而在国际上源IP地址也不能用192.168.1.101需要改成192.168.56.1。发送包的内容是这样的:
<li>
源MAC192.168.56.1的MAC地址
</li>
<li>
目标MAC192.168.56.2的MAC地址
</li>
<li>
源IP192.168.56.1
</li>
<li>
目标IP192.168.56.2
</li>
包到达192.168.56.2这个网口发现MAC一致将包收进来开始思考往哪里转发。
路由器B是一个NAT网关它上面配置了要访问国际身份192.168.56.2对应国内身份192.168.1.101于是改为访问192.168.1.101。
在路由器B中配置了静态路由要想访问192.168.1.0/24要从192.168.1.1这个口出去,没有下一跳了,因为我右手这个网卡,就是这个网段的,我是最后一跳了。
于是路由器B思考的时候匹配上了这条路由要从192.168.1.1这个口发出去发给192.168.1.101。
那192.168.1.101的MAC地址是多少呢路由器B发送ARP获取192.168.1.101的MAC地址然后发送包。内容是这样的
<li>
源MAC192.168.1.1的MAC地址
</li>
<li>
目标MAC192.168.1.101的MAC地址
</li>
<li>
源IP192.168.56.1
</li>
<li>
目标IP192.168.1.101
</li>
包到达服务器BMAC地址匹配将包收进来。
从服务器B接收的包可以看出源IP为服务器A的国际身份因而发送返回包的时候也发给这个国际身份由路由器A做NAT转换为国内身份。
从这个过程可以看出IP地址也会变。这个过程用英文说就是**Network Address Translation**,简称**NAT**。
其实这第二种方式我们经常见现在大家每家都有家用路由器家里的网段都是192.168.1.x所以你肯定访问不了你邻居家的这个私网的IP地址的。所以当我们家里的包发出去的时候都被家用路由器NAT成为了运营商的地址了。
很多办公室访问外网的时候也是被NAT过的因为不可能办公室里面的IP也是公网可见的公网地址实在是太贵了所以一般就是整个办公室共用一个到两个出口IP地址。你可以通过 [https://www.whatismyip.com/](https://www.whatismyip.com/) 查看自己的出口IP地址。
## 小结
好了,这一节内容差不多了,我来总结一下:
<li>
如果离开本局域网,就需要经过网关,网关是路由器的一个网口;
</li>
<li>
路由器是一个三层设备,里面有如何寻找下一跳的规则;
</li>
<li>
经过路由器之后MAC头要变如果IP不变相当于不换护照的欧洲旅游如果IP变相当于换护照的玄奘西行。
</li>
最后,给你留两个思考题吧。
1. 当在你家里要访问163网站的时候你的包需要NAT成为公网IP返回的包又要NAT成你的私有IP返回包怎么知道这是你的请求呢它怎么就这么智能的NAT成了你的IP而非别人的IP呢
1. 对于路由规则,这一节讲述了静态路由,需要手动配置,如果要自动配置,你觉得应该怎么办呢?
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,244 @@
<audio id="audio" title="第9讲 | 路由协议:西出网关无故人,敢问路在何方" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/ad/a3/add1ddabb65aaa752e68e1c4c13704a3.mp3"></audio>
俗话说得好,在家千日好,出门一日难。网络包一旦出了网关,就像玄奘西行一样踏上了江湖漂泊的路。
上一节我们描述的是一个相对简单的情形。出了网关之后,只有一条路可以走。但是,网络世界复杂得多,一旦出了网关,会面临着很多路由器,有很多条道路可以选。如何选择一个更快速的道路求取真经呢?这里面还有很多门道可以讲。
## 如何配置路由?
通过上一节的内容,你应该已经知道,路由器就是一台网络设备,它有多张网卡。当一个入口的网络包送到路由器时,它会根据一个本地的转发信息库,来决定如何正确地转发流量。这个转发信息库通常被称为**路由表**。
一张路由表中会有多条路由规则。每一条规则至少包含这三项信息。
<li>
目的网络:这个包想去哪儿?
</li>
<li>
出口设备:将包从哪个口扔出去?
</li>
<li>
下一跳网关:下一个路由器的地址。
</li>
通过route命令和ip route命令都可以进行查询或者配置。
例如我们设置ip route add 10.176.48.0/20 via 10.173.32.1 dev eth0就说明要去10.176.48.0/20这个目标网络要从eth0端口出去经过10.173.32.1。
上一节的例子中,网关上的路由策略就是按照这三项配置信息进行配置的。这种配置方式的一个核心思想是:**根据目的IP地址来配置路由**。
## 如何配置策略路由?
当然在真实的复杂的网络环境中除了可以根据目的ip地址配置路由外还可以根据多个参数来配置路由这就称为**策略路由**。
可以配置多个路由表可以根据源IP地址、入口设备、TOS等选择路由表然后在路由表中查找路由。这样可以使得来自不同来源的包走不同的路由。
例如,我们设置:
```
ip rule add from 192.168.1.0/24 table 10
ip rule add from 192.168.2.0/24 table 20
```
表示从192.168.1.10/24这个网段来的使用table 10中的路由表而从192.168.2.0/24网段来的使用table20的路由表。
在一条路由规则中,也可以走多条路径。例如,在下面的路由规则中:
```
ip route add default scope global nexthop via 100.100.100.1 weight 1 nexthop via 200.200.200.1 weight 2
```
下一跳有两个地方分别是100.100.100.1和200.200.200.1权重分别为1比2。
在什么情况下会用到如此复杂的配置呢?我来举一个现实中的例子。
我是房东,家里从运营商那儿拉了两根网线。这两根网线分别属于两个运行商。一个带宽大一些,一个带宽小一些。这个时候,我就不能买普通的家用路由器了,得买个高级点的,可以接两个外网的。
家里的网络呢就是普通的家用网段192.168.1.x/24。家里有两个租户分别把线连到路由器上。IP地址为192.168.1.101/24和192.168.1.102/24网关都是192.168.1.1/24网关在路由器上。
就像上一节说的一样家里的网段是私有网段出去的包需要NAT成公网的IP地址因而路由器是一个NAT路由器。
两个运营商都要为这个网关配置一个公网的IP地址。如果你去查看你们家路由器里的网段基本就是我图中画的样子。
<img src="https://static001.geekbang.org/resource/image/c3/db/c3f476eb7ce8f185befb6c7a2b1752db.jpg" alt="">
运行商里面也有一个IP地址在运营商网络里面的网关。不同的运营商方法不一样有的是/32的也即一个一对一连接。
例如运营商1给路由器分配的地址是183.134.189.34/32而运营商网络里面的网关是183.134.188.1/32。有的是/30的也就是分了一个特别小的网段。运营商2给路由器分配的地址是60.190.27.190/30运营商网络里面的网关是60.190.27.189/30。
根据这个网络拓扑图,可以将路由配置成这样:
```
$ ip route list table main
60.190.27.189/30 dev eth3 proto kernel scope link src 60.190.27.190
183.134.188.1 dev eth2 proto kernel scope link src 183.134.189.34
192.168.1.0/24 dev eth1 proto kernel scope link src 192.168.1.1
127.0.0.0/8 dev lo scope link
default via 183.134.188.1 dev eth2
```
当路由这样配置的时候,就告诉这个路由器如下的规则:
<li>
如果去运营商二就走eth3
</li>
<li>
如果去运营商一呢就走eth2
</li>
<li>
如果访问内网就走eth1
</li>
<li>
如果所有的规则都匹配不上,默认走运营商一,也即走快的网络。
</li>
但是问题来了租户A不想多付钱他说我就上上网页从不看电影凭什么收我同样贵的网费啊没关系咱有技术可以解决。
下面我添加一个Table名字叫**chao**。
```
# echo 200 chao &gt;&gt; /etc/iproute2/rt_tables
```
添加一条规则:
```
# ip rule add from 192.168.1.101 table chao
# ip rule ls
0: from all lookup local
32765: from 10.0.0.10 lookup chao
32766: from all lookup main
32767: from all lookup default
```
设定规则为从192.168.1.101来的包都查看个chao这个新的路由表。
在chao路由表中添加规则
```
# ip route add default via 60.190.27.189 dev eth3 table chao
# ip route flush cache
```
默认的路由走慢的,谁让你不付钱。
上面说的都是静态的路由,一般来说网络环境简单的时候,在自己的可控范围之内,自己捣鼓还是可以的。但是有时候网络环境复杂并且多变,如果总是用静态路由,一旦网络结构发生变化,让网络管理员手工修改路由太复杂了,因而需要动态路由算法。
## 动态路由算法
使用动态路由路由器,可以根据路由协议算法生成动态路由表,随网络运行状况的变化而变化。那路由算法是什么样的呢?
我们可以想象唐僧西天取经,需要解决两大问题,一个是在每个国家如何找到正确的路,去换通关文牒、吃饭、休息;一个是在国家之间,野外行走的时候,如何找到正确的路、水源的问题。
<img src="https://static001.geekbang.org/resource/image/85/65/85b3314e56cb5870a5cf9a0597ffa965.jpg" alt="">
无论是一个国家内部,还是国家之间,我们都可以将复杂的路径,抽象为一种叫作图的数据结构。至于唐僧西行取经,肯定想走的路越少越好,道路越短越好,因而这就转化成为**如何在途中找到最短路径**的问题。
咱们在大学里面学习计算机网络与数据结构的时候知道求最短路径常用的有两种方法一种是Bellman-Ford算法一种是Dijkstra算法。在计算机网络中基本也是用这两种方法计算的。
### 1.距离矢量路由算法
第一大类的算法称为**距离矢量路由****distance vector routing**。它是基于Bellman-Ford算法的。
这种算法的基本思路是,每个路由器都保存一个路由表,包含多行,每行对应网络中的一个路由器,每一行包含两部分信息,一个是要到目标路由器,从那条线出去,另一个是到目标路由器的距离。
由此可以看出,每个路由器都是知道全局信息的。那这个信息如何更新呢?每个路由器都知道自己和邻居之间的距离,每过几秒,每个路由器都将自己所知的到达所有的路由器的距离告知邻居,每个路由器也能从邻居那里得到相似的信息。
每个路由器根据新收集的信息计算和其他路由器的距离比如自己的一个邻居距离目标路由器的距离是M而自己距离邻居是x则自己距离目标路由器是x+M。
这个算法比较简单,但是还是有问题。
**第一个问题就是好消息传得快,坏消息传得慢。** 如果有个路由器加入了这个网络,它的邻居就能很快发现它,然后将消息广播出去。要不了多久,整个网络就都知道了。但是一旦一个路由器挂了,挂的消息是没有广播的。当每个路由器发现原来的道路到不了这个路由器的时候,感觉不到它已经挂了,而是试图通过其他的路径访问,直到试过了所有的路径,才发现这个路由器是真的挂了。
我再举个例子。
<img src="https://static001.geekbang.org/resource/image/e9/79/e9642f901c1d9c470c539ccc395e7879.jpg" alt="">
原来的网络包括两个节点B和C。A加入了网络它的邻居B很快就发现A启动起来了。于是它将自己和A的距离设为1同样C也发现A起来了将自己和A的距离设置为2。但是如果A挂掉情况就不妙了。B本来和A是邻居发现连不上A了但是C还是能够连上只不过距离远了点是2于是将自己的距离设置为3。殊不知C的距离2其实是基于原来自己的距离为1计算出来的。C发现自己也连不上A并且发现B设置为3于是自己改成距离4。依次类推数越来越大直到超过一个阈值我们才能判定A真的挂了。
这个道理有点像有人走丢了。当你突然发现找不到这个人了。于是你去学校问,是不是在他姨家呀?找到他姨家,他姨说,是不是在他舅舅家呀?他舅舅说,是不是在他姥姥家呀?他姥姥说,是不是在学校呀?总归要问一圈,或者是超过一定的时间,大家才会认为这个人的确走丢了。如果这个人其实只是去见了一个谁都不认识的网友去了,当这个人回来的时候,只要他随便见到其中的一个亲戚,这个亲戚就会拉着他到他的家长那里,说你赶紧回家,你妈都找你一天了。
**这种算法的第二个问题是,每次发送的时候,要发送整个全局路由表。**网络大了谁也受不了所以最早的路由协议RIP就是这个算法。它适用于小型网络小于15跳。当网络规模都小的时候没有问题。现在一个数据中心内部路由器数目就很多因而不适用了。
所以上面的两个问题,限制了距离矢量路由的网络规模。
### 2.链路状态路由算法
第二大类算法是**链路状态路由****link state routing**基于Dijkstra算法。
这种算法的基本思路是当一个路由器启动的时候首先是发现邻居向邻居say hello邻居都回复。然后计算和邻居的距离发送一个echo要求马上返回除以二就是距离。然后将自己和邻居之间的链路状态包广播出去发送到整个网络的每个路由器。这样每个路由器都能够收到它和邻居之间的关系的信息。因而每个路由器都能在自己本地构建一个完整的图然后针对这个图使用Dijkstra算法找到两点之间的最短路径。
不像距离距离矢量路由协议那样更新时发送整个路由表。链路状态路由协议只广播更新的或改变的网络拓扑这使得更新信息更小节省了带宽和CPU利用率。而且一旦一个路由器挂了它的邻居都会广播这个消息可以使得坏消息迅速收敛。
## 动态路由协议
### 1.基于链路状态路由算法的OSPF
**OSPF****Open Shortest Path First****开放式最短路径优先**)就是这样一个基于链路状态路由协议,广泛应用在数据中心中的协议。由于主要用在数据中心内部,用于路由决策,因而称为**内部网关协议****Interior Gateway Protocol**,简称**IGP**)。
内部网关协议的重点就是找到最短的路径。在一个组织内部路径最短往往最优。当然有时候OSPF可以发现多个最短的路径可以在这多个路径中进行负载均衡这常常被称为**等价路由**。
<img src="https://static001.geekbang.org/resource/image/2e/db/2eb5f4722689adf9926fded5005e02db.jpg" alt="">
这一点非常重要。有了等价路由到一个地方去可以有相同的两个路线可以分摊流量还可以当一条路不通的时候走另外一条路。这个在后面我们讲数据中心的网络的时候一般应用的接入层会有负载均衡LVS。它可以和OSPF一起实现高吞吐量的接入层设计。
有了内网的路由协议,在一个国家内,唐僧可以想怎么走怎么走了,两条路选一条也行。
### 2.基于距离矢量路由算法的BGP
但是外网的路由协议,也即国家之间的,又有所不同。我们称为**外网路由协议****Border Gateway Protocol**,简称**BGP**)。
在一个国家内部,有路当然选近的走。但是国家之间,不光远近的问题,还有政策的问题。例如,唐僧去西天取经,有的路近。但是路过的国家看不惯僧人,见了僧人就抓。例如灭法国,连光头都要抓。这样的情况即便路近,也最好绕远点走。
对于网络包同样每个数据中心都设置自己的Policy。例如哪些外部的IP可以让内部知晓哪些内部的IP可以让外部知晓哪些可以通过哪些不能通过。这就好比虽然从我家里到目的地最近但是不能谁都能从我家走啊
在网络世界,这一个个国家成为自治系统**AS**Autonomous System。自治系统分几种类型。
<li>
Stub AS对外只有一个连接。这类AS不会传输其他AS的包。例如个人或者小公司的网络。
</li>
<li>
Multihomed AS可能有多个连接连到其他的AS但是大多拒绝帮其他的AS传输包。例如一些大公司的网络。
</li>
<li>
Transit AS有多个连接连到其他的AS并且可以帮助其他的AS传输包。例如主干网。
</li>
每个自治系统都有边界路由器,通过它和外面的世界建立联系。
<img src="https://static001.geekbang.org/resource/image/69/3d/698e368848fdbf1eb8e270983e18143d.jpg" alt="">
**BGP又分为两类eBGP和iBGP。**自治系统间边界路由器之间使用eBGP广播路由。内部网络也需要访问其他的自治系统。边界路由器如何将BGP学习到的路由导入到内部网络呢就是通过运行iBGP使得内部的路由器能够找到到达外网目的地的最好的边界路由器。
BGP协议使用的算法是**路径矢量路由协议**path-vector protocol。它是距离矢量路由协议的升级版。
前面说了距离矢量路由协议的缺点。其中一个是收敛慢。在BGP里面除了下一跳hop之外还包括了自治系统AS的路径从而可以避免坏消息传得慢的问题也即上面所描述的B知道C原来能够到达A是因为通过自己一旦自己都到达不了A了就不用假设C还能到达A了。
另外,在路径中将一个自治系统看成一个整体,不区分自治系统内部的路由器,这样自治系统的数目是非常有限的。就像大家都能记住出去玩,从中国出发先到韩国然后到日本,只要不计算细到具体哪一站,就算是发送全局信息,也是没有问题的。
## 小结
好了,这一节就到这里了,我来做个总结:
<li>
路由分静态路由和动态路由,静态路由可以配置复杂的策略路由,控制转发策略;
</li>
<li>
动态路由主流算法有两种距离矢量算法和链路状态算法。基于两种算法产生两种协议BGP协议和OSPF协议。
</li>
最后,再给你留两个思考题:
<li>
路由协议要在路由器之间交换信息,这些信息的交换还需要走路由吗?不是死锁了吗?
</li>
<li>
路由器之间信息的交换使用什么协议呢?报文格式是什么样呢?
</li>
欢迎你留言和我讨论。趣谈网络协议,我们下期见!