1

六、ICMP与ping

ICMP协议的格式

ping 是基于 ICMP 协议工作的。ICMP全称Internet Control Message Protocol,就是互联网控制报文协议。
ICMP 报文是封装在 IP 包里面的。因为传输指令的时候,肯定需要源地址和目标地址。它本身非常简单。
image.png
ICMP 报文有很多的类型,不同的类型有不同的代码。最常用的类型是主动请求为 8,主动请求的应答为 0。

查询报文类型

常用的ping 就是查询报文,是一种主动请求,并且获得主动应答的 ICMP 协议。所以,ping 发的包也是符合 ICMP 协议格式的,只不过它在后面增加了自己的格式。
对 ping 的主动请求,进行网络抓包,称为ICMP ECHO REQUEST。同理主动请求的回复,称为ICMP ECHO REPLY。比起原生的 ICMP,这里面多了两个字段,一个是标识符(标识是请求还是回复),另一个是序号(每个发出的报文都有序号)。

在选项数据中,ping 还会存放发送请求的时间值,来计算往返时间,说明路程的长短。

差错报文类型

终点不可达为 3,源抑制为 4,超时为 11,重定向为 5。
差错报文的结构相对复杂一些。除了前面还是 IP,ICMP 的前 8 字节不变,后面则跟上出错的那个 IP 包的 IP 头和 IP 正文的前 8 个字节。

ping:查询报文类型的使用

image.png
ping 命令执行的时候,源主机首先会构建一个 ICMP 请求数据包,ICMP 数据包内包含多个字段。最重要的是两个,第一个是类型字段,对于请求数据包而言该字段为 8;另外一个是顺序号,主要用于区分连续 ping 的时候发出的多个数据包。每发出一个请求数据包,顺序号会自动加 1。为了能够计算往返时间 RTT,它会在报文的数据部分插入发送时间。

主机 B 会构建一个 ICMP 应答包,应答数据包的类型字段为 0,顺序号为接收到的请求数据包中的顺序号,然后再发送出去给主机 A。

在规定的时候间内,源主机如果没有接到 ICMP 的应答包,则说明目标主机不可达;如果接收到了 ICMP 应答包,则说明目标主机可达。此时,源主机会检查,用当前时刻减去该数据包最初从源主机上发出的时刻,就是 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 报文。如果数据报没有到达,则可能是超时。

Traceroute 还有一个作用是故意设置不分片,从而确定路径的 MTU。要做的工作首先是发送分组,并设置“不分片”标志。发送的第一个分组的长度正好与出口 MTU 相等。如果中间遇到窄的关口会被卡住,会发送 ICMP 网络差错包,类型为“需要进行分片但设置了不分片位”。其实,这是人家故意的好吧,每次收到 ICMP“不能分片”差错时就减小分组的长度,直到到达目标主机。

ping 使用查询报文,Traceroute 使用差错报文

七、网关

怎么上网?

二层网络只能让两个局域网的计算机互联,并不能真正的和Internet 互联。 假如学校给每个宿舍的网口分配了一个 IP 地址。这个 IP 是校园网的 IP,完全由网管部门控制。宿舍网的 IP 地址多为 192.168.1.x。校园网的 IP 地址,假设是 10.10.x.x。这个时候,你要在宿舍上网,有两个办法:

  1. 让你们宿舍长再买一个网卡。这个时候,你们宿舍长的电脑里就有两张网卡。一张网卡的线插到你们宿舍的交换机上,另一张网卡的线插到校园网的网口。而且,这张新的网卡的 IP 地址要按照学校网管部门分配的配置,不然上不了网。这种情况下,如果你们宿舍的人要上网,就需要一直开着宿舍长的电脑。
  2. 你们共同出钱买个家庭路由器。家庭路由器会有内网网口和外网网口。把外网网口的线插到校园网的网口上,将这个外网网口配置成和网管部的一样。内网网口连上你们宿舍的所有的电脑。这种情况下,如果你们宿舍的人要上网,就需要一直开着路由器。

这两种方法其实是一样的。只不过第一种方式,让你的宿舍长的电脑,变成一个有多个口的路由器而已。而你买的家庭路由器,里面也跑着程序,和你宿舍长电脑里的功能一样,只不过是一个嵌入式的系统。
当你的宿舍长能够上网之后,接下来,就是其他人的电脑怎么上网的问题。这就需要配置你们的网卡。当然 DHCP 是可以默认配置的。在进行网卡配置的时候,除了 IP 地址,还需要配置一个Gateway的东西,这个就是网关。

MAC 头和 IP 头

一旦配置了 IP 地址和网关,往往就能够指定目标地址进行访问了。在跨网关访问的时候,MAC 地址和 IP 地址会变化。
image.png
在 MAC 头里面,先是目标 MAC 地址,然后是源 MAC 地址,然后有一个协议类型,用来说明里面是 IP 协议。IP 头里面的版本号,目前主流的还是 IPv4,8 位标识协议。这里到了下一层的协议,也就是,是 TCP 还是 UDP。最重要的就是源 IP 和目标IP。先是源 IP 地址,然后是目标 IP 地址。在任何一台机器上,当要访问另一个 IP 地址的时候,都会先判断,这个目标 IP 地址,和当前机器的 IP 地址,是否在同一个网段。怎么判断同一个网段呢?需要 CIDR 和子网掩码。

如果是同一个网段, 例如,你访问你旁边的兄弟的电脑,那就没网关什么事情,直接将源地址和目标地址放入 IP 头中,然后通过 ARP 获得 MAC 地址,将源 MAC 和目的 MAC 放入MAC 头中,发出去就可以了。

如果不是同一网段, 这就需要发往默认网关 Gateway。Gateway 的地址一定是和源 IP 地址是一个网段的。往往不是第一个,就是第二个。例如 192.168.1.0/24 这个网段,Gateway 往往会是 192.168.1.1/24 或者192.168.1.2/24。

如何发往默认网关呢?这个过程就和发往同一个网段的其他机器是一样的:将源地址和目标 IP 地址放入 IP 头中,通过 ARP 获得网关的MAC 地址,将源 MAC 和网关的 MAC 放入 MAC 头中,发送出去。网关所在的端口,例如 192.168.1.1/24 将网络包收进来,然后接下来怎么做,就完全看网关的了。

网关往往是一个路由器,是一个三层转发的设备。就是把MAC 头和 IP 头都取下来,然后根据里面的内容,看看接下来把包往哪里转发的设备。路由器是一台设备,它有五个网口或者网卡,相当于有五只手,分别连着五个局域网。每只手的IP 地址都和局域网的 IP 地址相同的网段,每只手都是它握住的那个局域网的网关。任何一个想发往其他局域网的包,都会到达其中一只手,被拿进来,拿下 MAC 头和 IP头,看看,根据自己的路由算法,选择另一只手,加上 IP 头和 MAC 头,然后扔出去。

静态路由

静态路由,其实就是在路由器上,配置一条一条规则。这些规则包括:想访问 BBS 站(它肯定有个网段),从 2 号口出去,下一跳是 IP2;想访问教学视频站(它也有个自己的网段),从 3 号口出去,下一跳是 IP3,然后保存在路由器里。

IP头和MAC头哪些变、哪些不变?

MAC 地址是一个局域网内才有效的地址。因而,MAC 地址只要过网关,就必定会改变,因为已经换了局域网。两者主要的区别在于 IP 地址是否改变。不改变 IP 地址的网关,我们称为转发网关;改变 IP 地址的网关,我们称为NAT 网关。

转发网关

image.png
服务器 A 要访问服务器 B。首先,服务器 A 会思考,192.168.4.101 和我不是一个网段的,因而需要先发给网关。那网关是谁呢?已经静态配置好了,网关是 192.168.1.1。网关
的 MAC 地址是多少呢?发送 ARP 获取网关的 MAC 地址,然后发送包。包的内容是这样的:

源 MAC:服务器 A 的 MAC
目标 MAC:192.168.1.1 这个网口的 MAC
源 IP:192.168.1.101
目标 IP:192.168.4.101

包到达 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 地址,然后发送包。包的内容是这样的:

源 MAC:192.168.56.1 的 MAC 地址
目标 MAC:192.168.56.2 的 MAC 地址
源 IP:192.168.1.101
目标 IP:192.168.4.101

包到达 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 地址,然后发送包。包的内容是这样的:

源 MAC:192.168.4.1 的 MAC 地址
目标 MAC:192.168.4.101 的 MAC 地址
源 IP:192.168.1.101
目标 IP:192.168.4.101

通过这个过程可以看出,每到一个新的局域网,MAC 都是要变的,但是 IP 地址都不变。 在 IP 头里面,不会保存任何网关的 IP 地址。所谓的下一跳是,某个 IP 要将这个 IP 地址转换为 MAC 放入 MAC 头。

NAT 网关

image.png
这里遇见的第一个问题是,局域网之间没有商量过,各定各的网段,因而 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 地址,然后发送包。包的内容是这样的:

源 MAC:服务器 A 的 MAC
目标 MAC:192.168.1.1 这个网口的 MAC
源 IP:192.168.1.101
目标 IP:192.168.56.2

包到达 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。发送包的内容是这样的:

源 MAC:192.168.1.1 的 MAC 地址
目标 MAC:192.168.1.101 的 MAC 地址
源 IP:192.168.56.1
目标 IP:192.168.1.101

从服务器 B 接收的包可以看出,源 IP 为服务器 A 的国际身份,因而发送返回包的时候,也发给这个国际身份,由路由器 A 做 NAT,转换为国内身份。现在大家每家都有家用路由器,家里的网段都是192.168.1.x,所以你肯定访问不了你邻居家的这个私网的 IP 地址的。所以,当我们家里的包发出去的时候,都被家用路由器 NAT 成为了运营商的地址了

八、路由协议

如何配置路由?

路由器就是一台网络设备,它有多张网卡。当一个入口的网络包送到路由器时,它会根据一个本地的转发信息库,来决定如何正确地转发流量。这个转发信息库通常被称为路由表。一张路由表中会有多条路由规则。每一条规则至少包含这三项信息。

目的网络:这个包想去哪儿?
出口设备:将包从哪个口扔出去?
下一跳网关:下一个路由器的地址。

通过 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 地址、入口设备、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。
image.png

动态路由算法

解决如何在途中找到最短路径

1.距离矢量路由算法

这种算法的基本思路是,每个路由器都保存一个路由表,包含多行,每行对应网络中的一个路由器,每一行包含两部分信息,一个是要到目标路由器,从那条线出去,另一个是到目标路由器的距离。由此可以看出,每个路由器都是知道全局信息的。那这个信息如何更新呢?每个路由器都知道自己和邻居之间的距离,每过几秒,每个路由器都将自己所知的到达所有的路由器的距离告知邻居,每个路由器也能从邻居那里得到相似的信息。每个路由器根据新收集的信息,计算和其他路由器的距离,比如自己的一个邻居距离目标路由器的距离是 M,而自己距离邻居是 x,则自己距离目标路由器是 x+M。

第一个问题就是好消息传得快,坏消息传得慢。如果有个路由器加入了这个网络,它的邻居就能很快发现它,然后将消息广播出去。要不了多久,整个网络就都知道了。但是一旦一个路由器挂了,挂的消息是没有广播的。当每个路由器发现原来的道路到不了这个路由器的时候,感觉不到它已经挂了,而是试图通过其他的路径访问,直到试过了所有的路径,才发现这个路由器是真的挂了。

这种算法的第二个问题是,每次发送的时候,要发送整个全局路由表。网络大了,谁也受不了,所以最早的路由协议 RIP 就是这个算法。它适用于小型网络(小于 15 跳)。当网络规模都小的时候,没有问题。现在一个数据中心内部路由器数目就很多,因而不适用了。

2.链路状态路由算法

第二大类算法是链路状态路由(link state routing),基于 Dijkstra 算法。
这种算法的基本思路是:当一个路由器启动的时候,首先是发现邻居,向邻居 say hello,邻居都回复。然后计算和邻居的距离,发送一个 echo,要求马上返回,除以二就是距离。然后将自己和邻居之间的链路状态包广播出去,发送到整个网络的每个路由器。这样每个路由器都能够收到它和邻居之间的关系的信息。因而,每个路由器都能在自己本地构建一个完整的图,然后针对这个图使用 Dijkstra 算法,找到两点之间的最短路径。不像距离距离矢量路由协议那样,更新时发送整个路由表。链路状态路由协议只广播更新的或改变的网络拓扑,这使得更新信息更小,节省了带宽和 CPU 利用率。而且一旦一个路由器挂了,它的邻居都会广播这个消息,可以使得坏消息迅速收敛。

动态路由协议

1.基于链路状态路由算法的OSPF

OSPF(Open Shortest Path First,开放式最短路径优先)就是这样一个基于链路状态路由协议,广泛应用在数据中心中的协议。由于主要用在数据中心内部,用于路由决策,因而称为内部网关协议(Interior Gateway Protocol,简称IGP)。

内部网关协议的重点就是找到最短的路径。在一个组织内部,路径最短往往最优。当然有时候 OSPF 可以发现多个最短的路径,可以在这多个路径中进行负载均衡,这常常被称为等价路由。

这一点非常重要。有了等价路由,到一个地方去可以有相同的两个路线,可以分摊流量,还可以当一条路不通的时候,走另外一条路。

2.基于距离矢量路由算法的BGP

但是外网的路由协议,又有所不同。我们称为外网路由协议(BorderGateway Protocol,简称BGP)。在一个国家内部,有路当然选近的走。但是国家之间,不光远近的问题,还有政策的问题。
每个数据中心都设置自己的 Policy。例如,哪些外部的 IP 可以让内部知晓,哪些内部的 IP 可以让外部知晓,哪些可以通过,哪些不能通过。
在网络世界,形成了一个个自治系统 AS(Autonomous System)。自治系统分几种类型。

  1. Stub AS:对外只有一个连接。这类 AS 不会传输其他 AS 的包。例如,个人或者小公司的网络。
  2. Multihomed AS:可能有多个连接连到其他的 AS,但是大多拒绝帮其他的 AS 传输包。例如一些大公司的网络。
  3. Transit AS:有多个连接连到其他的 AS,并且可以帮助其他的 AS 传输包。例如主干网。

每个自治系统都有边界路由器,通过它和外面的世界建立联系。
image.png
BGP 又分为两类,eBGP 和 iBGP。 自治系统间,边界路由器之间使用 eBGP 广播路由。内部网络也需要访问其他的自治系统。边界路由器如何将 BGP 学习到的路由导入到内部网络呢?就是通过运行 iBGP,使得内部的路由器能够找到到达外网目的地的最好的边界路由器。

BGP 协议使用的算法是路径矢量路由协议(path-vector protocol)。它是距离矢量路由协议的升级版。
距离矢量路由协议的缺点。其中一个是收敛慢。在 BGP 里面,除了下一跳 hop之外,还包括了自治系统 AS 的路径,从而可以避免坏消息传的慢的问题,也即上面所描述的,B 知道 C 原来能够到达 A,是因为通过自己,一旦自己都到达不了 A 了,就不用假设C 还能到达 A 了。


拿骚的莫里斯
25 声望4 粉丝