28_路由(八),完成路由 ## 网络协议那些事儿

50 阅读15分钟

28_路由(八),完成路由

网络协议那些事儿

内容简介


  1. 前言

上一课我们用虚拟机软件 VirtualBox 创建了三个虚拟机,也学习了 VirtualBox 提供的强大的克隆功能,我们创建的三个虚拟机分别叫作 Ubuntu01, Ubuntu02 和 Ubuntu03。如下图:

当然了,你也可以用 VMware 这样的虚拟机软件。

这一课我们就来配置这三个虚拟机里面的 Linux 的网络,以完成下图所示的网络架构:

  1. 完成路由的实践

现在,我们只需要配置虚拟机的网络即可。首先,我们要创建一个 NAT 网络(我们之后的课程会详细学习 NAT(Network Address Translation 的缩写,表示 “网络地址转换”))。

在 VirtualBox 的菜单栏中,打开 “偏好设置”(Preferences,也可能叫作 “首选项” 或“属性”):

在打开的 “偏好设置” 窗口,点击 “ 网络” 选项,如下图所示:

可以看到这里是 NAT 网络的管理区域。可以添加、删除、编辑 NAT 网络。目前暂时没有任何 NAT 网络,我们添加一个,点击带加号的网卡图标(用红框标识出来的):

点击之后,会添加如上图所示的名叫 NatNetwork 的 NAT 网络。然后我们可以编辑此网络,点击带齿轮符号的网卡图标(用红框标识出来的),会打开如下图所示的小窗口:

你可以修改此 NAT 网络的名称,网络的 CIDR 的值(就跟我们学习过的网络的表示法一样)。我们可以不修改,就用这里默认的值,网络是 10.0.2.0/24(当然,你也可以设置为其他值,例如 10.0.0.0/24)。记得保证 “支持 DHCP” 这个选项是被选中的,以便我们的虚拟机能够在需要时自动被分配 IP 地址。点击 “OK” 或者“Cancel”,关闭此窗口即可。

好的,我们创建了一个 NAT 网络,现在需要让虚拟机连接到该网络。

首先,我们配置第一个虚拟机(也就是 Ubuntu01)的网络。进入 Ubuntu01 这个虚拟机的 “设置”->“网络”:

可以看到,有四张虚拟网卡,网卡 1 是默认配置为 “启用网络连接” 的,网卡 2、网卡 3 和 网卡 4 默认都没有启用。默认网卡 1 的连接方式是“网络地址转换(NAT)”,我们将其改为“NAT 网络”:

“界面名称” 就设置为我们刚才配置的 NatNetwork 这个 NAT 网络,我们这里因为只创建了一个 NAT 网络,所以它自动为我们配置了 NatNetwork 这个网络。

高级选项里面,暂时不需要修改什么。不过保险起见,建议你单击 MAC 地址右侧的圆形箭头图标,用于 “生成一个新的随机 MAC 地址”,以确保虚拟机上没有两次使用相同的 MAC 地址:

点击了圆形箭头图标后,MAC 地址就变成了新的随机的 MAC 地址:

点击 “OK” 来保存、退出。在 VirtualBox 的管理器界面中,可以看到 Ubuntu01 这个虚拟机的信息一栏里面的网络信息显示如下:

接着,我们对另外两个虚拟机(Ubuntu02 和 Ubuntu03)也执行相同的配置,以使这三个虚拟机都连接到 NatNetwork 这个网络。

现在,我们启动这三台虚拟机。

三台虚拟机启动后,用创建 Ubuntu01 这台虚拟机时创建的用户名和密码来登录(我自己创建的用户名是 oscar,密码是 123456):

因为 Ubuntu02 和 Ubuntu03 这两台虚拟机都是克隆自 Ubuntu01,登录之后可以发现这三台虚拟机的主机名都是 ubuntu01,如下图所示:

目前,在三台虚拟机上,我们都是以普通用户的身份登录的(比如我是以 oscar 这个普通用户的身份登录的),我们可以切换为 root 用户,就是系统的大管家,拥有所有权限,这样运行很多命令的时候比较方便,不需要每次都在命令前加 sudo 这个提权命令。

切换为 root 用户,可以运行如下命令:

然后输入你的普通用户的密码(比如我的 oscar 这个用户的密码是 123456),就能切换为 root 用户了:

可以看到,切换为 root 用户之后,命令行提示符就从例如 oscar@ubuntu01:~$ 变为了 root@ubuntu01:/home/oscar#,表示目前我们已经是 root 用户的身份。

对 Ubuntu02 和 Ubuntu03 这两个虚拟机也做同样的操作,都从普通用户切换为 root 用户。

之前我们说目前这三台虚拟机的主机名都是 ubuntu01,我们来修改一下 Ubuntu02 和 Ubuntu03 这两台虚拟机中的 Linux 系统的 /etc/hostname 这个文件,来重命名主机名(host 是 “主机” 的意思,name 是 “名字” 的意思),分别将其修改为 ubuntu02 和 ubuntu03。你可以用 Vim 等文本编辑器来修改 /etc/hostname 这个文件,也可以用以下命令来修改主机名:


hostnamectl set-hostname ubuntu02

  
  



hostnamectl set-hostname ubuntu03

  
  


以上命令的运行需要 root 权限。修改完之后,使用 reboot 命令重新启动 Ubuntu02 和 Ubuntu03 这两个虚拟机,以使修改生效。

重新启动之后,可以看到命令行提示符中的主机名已经变成了对应的 ubuntu02 和 ubuntu03。

现在,我们为这三台虚拟机配置以下 IP 地址:

  • 在 Ubuntu01 这台虚拟机上,设置 IP 地址为 192.168.10.1/24;

  • 在 Ubuntu02 这台虚拟机上,设置 IP 地址为 192.168.10.254/24;

  • 在 Ubuntu03 这台虚拟机上,设置 IP 地址为 192.168.11.1/24。

在 Ubuntu01 这台虚拟机上,运行以下命令:

ifconfig enp0s3 192.168.10.1 netmask 255.255.255.0

在 Ubuntu02 这台虚拟机上,运行以下命令:

ifconfig enp0s3 192.168.10.254 netmask 255.255.255.0

在 Ubuntu03 这台虚拟机上,运行以下命令:

ifconfig enp0s3 192.168.11.1 netmask 255.255.255.0

现在,我们尝试在 Ubuntu01 这台虚拟机上测试一下到 Ubuntu02 这台虚拟机的网络连接,用 ping 192.168.10.254 命令:

要停止 ping 命令,可以使用 Ctrl + c 组合键。

可以看到 ping 命令成功了,从 Ubuntu01 可以连接到 Ubuntu02。

现在,我们在 Ubuntu01 这台虚拟机上测试一下到 Ubuntu03 这台虚拟机的网络连接,用 ping 192.168.11.1 命令:

这次 ping 命令没有成功。这是很正常的,因为 Ubuntu01 和 Ubuntu03 不在同一个网络中。没有路由器连接这两个网络,所以无法彼此通信。

因此,我们需要在 Ubuntu03 所属的网络(192.168.11.0/24)中为 Ubuntu02 这台虚拟机添加一个接口,以连接这两个网络。此接口就充当一个网关的作用,地址是 192.168.11.254,如之前的网络图所示。

路由器配置

我们让 Ubuntu02 这个虚拟机扮演路由器的角色,首先要做的是在 192.168.11.0/24 这个网络中为它添加一个额外的 IP 地址。

但是你会说:“目前 Ubuntu02 这台虚拟机只有一张网卡呀!”

没关系,因为在 Linux 中,我们可以向一个网络接口添加任意数量的 IP 地址。我们将创建一个名为 enp0s3:0 的虚拟网络接口。

ifconfig enp0s3:0 192.168.11.254 netmask 255.255.255.0

可以看到,现在我们有两个网络接口,每个接口在两个网络里各有一个 IP 地址。在 192.168.10.0/24 这个网络中,接口的 IP 地址是 192.168.10.254。在 192.168.11.0/24 这个网络中,接口的 IP 地址是 192.168.11.254。

好的,我们已经差不多准备好进行路由了。为什么说差不多呢?

因为目前 Ubuntu02 还只是一台普通的机器,会拒绝不是发给自己的 IP 地址的数据包。为了使其表现得像路由器,必须激活路由功能。要激活路由功能非常简单,只要将 /proc/sys/net/ipv4/ip_forward 这个文件的值从 0 改为 1,运行以下命令即可:


echo 1 > /proc/sys/net/ipv4/ip_forward

  
  


很好,我们的 Ubuntu02 现在已经是一台路由器了!

我们可以在 Ubuntu01 上测试一下到 Ubuntu03 的网络连接,用 ping 192.168.11.1 命令:

为什么 ping 命令还是不成功呢?

这是正常的,因为目前 Ubuntu01 还不知道为了将数据包发给 Ubuntu03,需要先发给 Ubuntu02,经由 Ubuntu02 这个路由器中转。

为此,我们须要在 Ubuntu01 的路由表中设置一条路由。由于我们的网络非常简单,因此可以将其设置为默认路由。

我们运行 route -n 命令来看一下 Ubuntu01 的路由表:

可以看到,目前 Ubuntu01 的默认路由的网关的 IP 地址是 10.0.2.1。我们运行 route add default gw 192.168.10.254 命令,为 Ubuntu01 添加一个默认路由,默认路由的网关的 IP 地址是 192.168.10.254。

我们再来试一下,在 Ubuntu01 上测试一下到 Ubuntu03 的网络连接,用 ping 192.168.11.1 命令:

还是不能连接到 Ubuntu03。不过,可以看到 Ubuntu01 上显示的信息和以前不一样了,上图显示 From 192.168.10.254,表示 Ubuntu01 已经知道为了连接 Ubuntu03,需要发送数据包到 Ubuntu02 这个路由器的 192.168.10.254 接口。

Ubuntu01 的路由表告诉它要加入 192.168.11.0/24 这个网络,需要经过默认路由。因此,它将数据包发送到 Ubuntu02 这个路由器,在 192.168.10.254 这个接口。

Ubuntu02 接收到该数据包,在 OSI 第 2 层中看到其 MAC 地址,在 OSI 第 3 层中读取目标 IP 地址(192.168.11.1),发现该数据包不是发给自己的。由于路由已激活,它将在路由表中查看,看看应将数据包发送给谁。我们在 Ubuntu02 中运行 route -n 命令看看:

Ubuntu02 看到 192.168.11.1 是在它自己所属的网络(192.168.11.0/24)中,因此可以将数据包直接发送给 192.168.11.1。

到此为止,一切都是顺利的。192.168.11.1 这个 IP 地址对应的 Ubuntu03 这台虚拟机接收到了 ping 命令发送的数据包。

但另一方面,Ubuntu03 的默认路由还没有被正确配置,它不知道应该把对于 ping 命令的响应发送给谁。因此 Ubuntu01 就接收不到从 Ubuntu03 发来的对 ping 命令的响应。

我们可以使用强大的 tcpdump 命令来验证一下。

我们将在使用 ping 命令进行数据包的发送时,依次在 Ubuntu01 的 enp0s3 接口,Ubuntu02 的 enp0s3 和 enp0s3:0 接口,Ubuntu03 的 enp0s3 接口上使用 tcpdump 命令来嗅探。

我们可以通过打开多个虚拟终端(或虚拟控制台,被称为 tty)在 Linux 下并行启动多个命令,在 Ubuntu 中我们可以使用 6 个虚拟终端。

现在,我们在第一个虚拟终端(tty1)中,可以用 w 命令来验证一下:

要进入这些虚拟终端,须要用 Ctrl + Alt + Fx(x 可以从 1 到 6)的组合按键。例如,要进入第二个虚拟终端,须要按下 Ctrl + Alt + F2。要回到登录时的虚拟终端,也就是我们目前所在的 tty1,就用 Ctrl + Alt + F1。

在苹果的 macOS 中,如果按下 F1 - F12 的按键,默认对应的不是 F1 - F12 的效果,而是印在上面的例如调节屏幕亮度,调节声音大小,等等的效果。

当然你可以在 MacBook 的键盘上用左下角的 fn 键 + F1 - F12 来起到实际 F1 - F12 的效果。

你也可以进入 “系统偏好设置” -> “键盘”,把“将 F1、F2 等键用作标准功能键” 这个选项勾上。这样你在虚拟机中的 Ubuntu 里用 Cmd + Alt + [F1 - F6] 组合键时就不需要加上 fn 键了。如下图红框所示:

Ubuntu 18.04 及以上版本中,进入 tty 的这些终端的快捷键:

  • Ctrl + Alt + F1 : 回到登录时的虚拟终端,就是 tty1;

  • Ctrl + Alt + F2 : 进入 tty2;

  • Ctrl + Alt + F3 : 进入 tty3;

  • Ctrl + Alt + F4 : 进入 tty4;

  • Ctrl + Alt + F5 : 进入 tty5;

  • Ctrl + Alt + F6 : 进入 tty6。

进入 tty2 - tty6 这些虚拟终端后,和登录 tty1 一样,你需要输入你的用户名和密码(例如我输入用户名 oscar 和密码 123456),才能真正登录上去。

这样,你可以在第一个虚拟终端(tty1)中运行 ping 命令,然后在第二个虚拟终端(tty2)中运行 tcpdump 命令。

首先,我们在 Ubuntu01 的 tty1 虚拟终端(也就是当前登录的终端)中运行 ping 192.168.11.1 命令:

然后用 Ctrl + Alt + F2 组合按键进入 tty2 这第二个虚拟终端,使用你的用户名和密码登录 tty2。

因为 tcpdump 命令需要 root 权限,所以先用 sudo su 命令切换为 root 用户,再运行 tcpdump -i enp0s3 icmp 命令(tcpdump 命令参数里的 icmp 表示 ICMP 协议,因为 ping 命令就是通过发送 ICMP 数据包来进行网络连接测试的)来嗅探:

上图中,我们看到 Ubuntu01(IP 地址是 192.168.10.1)将 ICMP 请求发送到 Ubuntu03(IP 地址是 192.168.11.1)。

request 表示 “请求”;之后我们会看到的 reply 表示 “响应,回复”。

接着,我们在 Ubuntu02 上面运行 tcpdump -i enp0s3 icmp 命令:

在 Ubuntu02 上,我们看到 ICMP 请求到达 enp0s3 接口(IP 地址是 192.168.10.254)。

我们在 Ubuntu02 上用 Ctrl + Alt + F2 来登录第二个虚拟终端 tty2,然后在其中运行 tcpdump -i enp0s3:0 icmp 命令:

可以看到有请求从 Ubuntu02 的 enp0s3:0 接口(IP 地址是 192.168.11.254)出来。

在 Ubuntu03 上,我们也运行 tcpdump -i enp0s3 icmp 命令:

可以看到,有 ICMP 请求(request)到达 Ubuntu03 的 enp0s3 接口,但是没有响应(reply)从它的 enp0s3 接口出来。

这个问题通常被称为 “路由的返回问题”。我们通常会记得配置信息如何发送,却忘记配置信息如何返回。

因此,我们须要用 route add default gw 192.168.11.254 命令为 Ubuntu03 添加一个默认路由,默认路由的网关的 IP 地址是 192.168.11.254。

这次,我们的 ping 命令终于成功了!可以用 tcpdump 命令来查看:

在 Ubuntu01 的 tty2 虚拟终端中,可以看到 Ubuntu01 的请求(request,从 192.168.10.1 到 192.168.11.1)和 Ubuntu03 的响应(reply,从 192.168.11.1 到 192.168.10.1。经由 Ubuntu02 这个路由器中转)。

在 Ubuntu03 中也能看到类似的信息:

在 Ubuntu01 的 tty1 虚拟终端中,可以看到 ping 命令终于成功了:

那么,我们应该记住什么呢?

  1. 只有配置路由在两个方向都成功运行的情况下,我们才能连接到一个机器。

  2. 在搭建网络架构之前,我们通常先将路由表写在纸上,这样可以让思路更清晰。

很好,我们终于搭建好了第一个简单的路由网络架构!

  1. 更进一步

我们之前研究过一个较大型的网络(请参见下图)。这个网络的架构的搭建太耗费时间和篇幅,我们就不演示了,你有兴趣的话可以尝试搭建一下。

创建虚拟机

要实现此架构,需要不少虚拟机。可以使用 VirtualBox 的克隆功能来创建多个虚拟机。

编写路由表

将所有机器的路由表写在纸上。

配置

根据你在纸上写的路由表,配置所有虚拟机的 IP 地址和路由表。

要创建不是默认路由的一条路由,使用类似下面的命令:


route add -net 192.168.10.0 netmask 255.255.255.0 gw 192.168.11.254

  
  


要删除一条特定的路由,使用类似下面的命令:


route del -net 192.168.10.0 netmask 255.255.255.0

  
  


测试

要测试你的网络,你可以用 ping 命令,还可以用 traceroutetcpdump 命令。使用这些命令来了解问题到底出在哪里。

  1. 总结

好的,我们路由的实践终于完成了。这几课还是颇具难度的,因为涉及到不少操作系统和命令行的知识。

如果你顺利地完成了实践,那么请把掌声给自己!

现在:

  • 你已经掌握了 IP 协议(至少是 IP 协议的一部分);

  • 你知道了什么是路由;

  • 你知道了如何将网络互连起来;

  • 你可以在 Windows 和 Linux 中配置机器的 IP 地址;

  • 你知道如何在 Linux 下配置路由。

你现在已经非常了解 IP 协议了,但我们将看到 OSI 第 3 层其实还有其他协议。

一起加油吧~

}如果您想了解更多技术资源,欢迎加入点击这里钉钉群交流IT技术资源查看“IT技术交流群一”群的钉钉群号: 129605002953