网络实验:Linux静态路由器配置

穷则独善其身,达则兼善天下。

—— 战国·孟子·《孟子》

本实验演示 静态路由 配置方法,迫于没有真实的路由设备,我们拿 Linux 主机来顶。

Linux 是一个非常流行的服务器操作系统,不仅可以用来部署软件服务,网络功能也非常强大。经过简单的配置,就可以让 Linux 摇身一变,成为一台路由器,非常有趣!

接下来,我们以网络规划一节中的提到的某公司网络拓扑为例,讲解 Linux 静态路由配置步骤:

拓扑图中的所有路由器,均由 Linux 主机提供。我们将根据拓扑图中标注的网段、地址进行配置,以打通所有部门主机互访为目标。

实验环境同样由 Docker 容器提供,只需执行以下 docker 命令即可一键打开:

1
docker run --name static-router-lab --rm -it --privileged --cap-add=NET_ADMIN --cap-add=SYS_ADMIN -v /data -h static-router-lab fasionchan/netbox:0.5 bash /script/static-router-lab.sh

如果打开成功,屏幕将输出 Success 字样:

1
2
[Success]
press Ctrl-C to exit

实验完毕后,只需按下 Ctrl-C 组合键,即可退出实验环境。

实验环境成功启动后,可以执行 docker 命令登录拓扑中的任意节点。以登录主机 bruce 为例:

1
docker exec -it static-router-lab bash /script/nsvm-util.sh enter-nsvm bruce

将这行命令最后的 bruce 换成其他节点名,即可登录其他节点。例如登录研发部路由器 dev :

1
docker exec -it static-router-lab bash /script/nsvm-util.sh enter-nsvm dev

主机 bruce 已经预先配置好 IP 地址,可以 ping 通研发部网络内的主机。我们 ping 一下 bruce 的网关,也就是研发部路由器 192.168.171.1 ,看到网络是通的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
root@bruce [ ~ ]  ➜ ping 192.168.171.1
PING 192.168.171.1 (192.168.171.1) 56(84) bytes of data.
64 bytes from 192.168.171.1: icmp_seq=1 ttl=64 time=0.090 ms
64 bytes from 192.168.171.1: icmp_seq=2 ttl=64 time=0.391 ms
64 bytes from 192.168.171.1: icmp_seq=3 ttl=64 time=0.139 ms
64 bytes from 192.168.171.1: icmp_seq=4 ttl=64 time=0.191 ms
^C
--- 192.168.171.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3112ms
rtt min/avg/max/mdev = 0.090/0.202/0.391/0.114 ms

研发部路由器有两块网卡,分别接入研发部网络以及核心路由网络。我们 ping 该路由在核心路由网络中的地址 192.168.170.5 ,发现网络还不通:

1
2
root@bruce [ ~ ]  ➜ ping 192.168.170.5
ping: connect: Network is unreachable

ping 命令提示的错误是网络不可达 ,应该是 bruce 主机路由表中缺少去往 192.168.170.5 的规则导致的。我们先查一下主机的路由规则:

1
2
root@bruce [ ~ ]  ➜ ip route
192.168.171.0/25 dev eth0 proto kernel scope link src 192.168.171.3

果然,主机 bruce 当前只有到本地研发部网络的路由规则。

bruce 去往其他网络的数据包,应该由研发部路由器来转发。因此,我们可以为它配置一条默认路由,以 192.168.171.1 为下一跳,这样就可以 ping 通了:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
root@bruce [ ~ ]  ➜ ip route add default via 192.168.171.1
root@bruce [ ~ ]  ➜ ping 192.168.170.5
PING 192.168.170.5 (192.168.170.5) 56(84) bytes of data.
64 bytes from 192.168.170.5: icmp_seq=1 ttl=64 time=0.092 ms
64 bytes from 192.168.170.5: icmp_seq=2 ttl=64 time=0.198 ms
64 bytes from 192.168.170.5: icmp_seq=3 ttl=64 time=0.099 ms
64 bytes from 192.168.170.5: icmp_seq=4 ttl=64 time=0.193 ms
^C
--- 192.168.170.5 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3083ms
rtt min/avg/max/mdev = 0.092/0.145/0.198/0.050 ms

我们 ping 一下其他路由器,例如法务部路由器 192.168.170.2 ,看是否能通:

1
2
3
4
5
root@bruce [ ~ ]  ➜ ping 192.168.170.2
PING 192.168.170.2 (192.168.170.2) 56(84) bytes of data.
^C
--- 192.168.170.2 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3077ms

ping 命令显示,它发出了 4 个包,但没有收到任何响应,网络似乎不通。这是为什么呢?

我们重新在 bruce 上执行 ping 命令,并进入法务部路由器 law ,执行 tcpdump 命令抓包分析:

1
2
3
root@law [ ~ ]  ➜ tcpdump -ni eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

tcpdump 命令并没有任何输出,这说明数据包并没有到达路由器 law 。

我们进入研发部路由器 dev ,同样执行 tcpdump 进行抓包:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
root@dev [ ~ ]  ➜ tcpdump -ni eth1
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
15:56:18.684348 IP 192.168.171.3 > 192.168.170.2: ICMP echo request, id 583, seq 81, length 64
15:56:19.703137 IP 192.168.171.3 > 192.168.170.2: ICMP echo request, id 583, seq 82, length 64
15:56:20.729008 IP 192.168.171.3 > 192.168.170.2: ICMP echo request, id 583, seq 83, length 64
15:56:21.751004 IP 192.168.171.3 > 192.168.170.2: ICMP echo request, id 583, seq 84, length 64
^C
4 packets captured
4 packets received by filter
0 packets dropped by kernel
root@dev [ ~ ]  ➜ tcpdump -ni eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes

我们看到,数据包从 eth1 网卡进来,但没有按照预期转发出去,eth0 网卡没有任何流量。

为什么研发部路由器没有帮我转发数据包呢?原因通常有二:

  1. 缺少相关路由规则,但这种情况路由器一般会报告目的不可达差错;
  2. 内核没有开启 IP 包转发功能;

研发部路由器并没有报告目的不可达差错,因此应该是它没有开启流量转发开关。我们很快就确认了这一点:

1
2
root@dev [ ~ ]  ➜ cat /proc/sys/net/ipv4/ip_forward
0

Linux 路由转发功能是否开启,由一个内核参数控制。该参数可以通过 procfs 访问,路径是 /proc/sys/net/ipv4/ip_forward 。它有两个不同的取值:

  • 0 ,关闭路由转发功能
  • 1 ,开启路由转发功能

我们将 dev 的路由转发功能打开:

1
2
3
root@dev [ ~ ]  ➜ echo 1 > /proc/sys/net/ipv4/ip_forward
root@dev [ ~ ]  ➜ cat /proc/sys/net/ipv4/ip_forward
1

很快我们在路由 law 上面,观察到 bruce 发来的 ping 包:

1
2
3
4
5
6
7
8
9
root@law [ ~ ]  ➜ tcpdump -ni eth0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
15:59:07.485919 ARP, Request who-has 192.168.170.2 tell 192.168.170.5, length 28
15:59:07.486259 ARP, Reply 192.168.170.2 is-at 16:59:71:cf:83:b6, length 28
15:59:07.486370 IP 192.168.171.3 > 192.168.170.2: ICMP echo request, id 583, seq 246, length 64
15:59:08.511588 IP 192.168.171.3 > 192.168.170.2: ICMP echo request, id 583, seq 247, length 64
15:59:09.536063 IP 192.168.171.3 > 192.168.170.2: ICMP echo request, id 583, seq 248, length 64
15:59:10.558338 IP 192.168.171.3 > 192.168.170.2: ICMP echo request, id 583, seq 249, length 64

但 bruce 还是没有收到如何应答,这又是为什么呢?

问题出在回程上:按道理 law 收到 bruce 的 ping 包后,需要向 bruce 回复应答包。但由于它的路由表还缺少 bruce 所在网段的规则,回程包不知道怎么走:

1
2
3
root@law [ ~ ]  ➜ ip route
192.168.170.0/26 dev eth0 proto kernel scope link src 192.168.170.2
192.168.170.192/26 dev eth1 proto kernel scope link src 192.168.170.193

我们为 law 配上研发部网段的路由规则,以研发部路由器 192.168.170.5 为下一跳:

1
2
3
4
5
root@law [ ~ ]  ➜ ip route add 192.168.171.0/25 via 192.168.170.5
root@law [ ~ ]  ➜ ip route
192.168.170.0/26 dev eth0 proto kernel scope link src 192.168.170.2
192.168.170.192/26 dev eth1 proto kernel scope link src 192.168.170.193
192.168.171.0/25 via 192.168.170.5 dev eth0

很快,我们就看到主机 bruce 已经可以 ping 通路由 law 了:

1
2
3
4
5
6
root@bruce [ ~ ]  ➜ ping 192.168.170.2
PING 192.168.170.2 (192.168.170.2) 56(84) bytes of data.
64 bytes from 192.168.170.2: icmp_seq=404 ttl=63 time=0.236 ms
64 bytes from 192.168.170.2: icmp_seq=405 ttl=63 time=0.231 ms
64 bytes from 192.168.170.2: icmp_seq=406 ttl=63 time=0.314 ms
64 bytes from 192.168.170.2: icmp_seq=407 ttl=63 time=0.207 ms

现在我们改 ping 路由器 law 另一个地址 192.168.170.193 ,发现研发部路由器报目的网络不可达差错:

1
2
3
4
5
6
7
8
9
root@bruce [ ~ ]  ➜ ping 192.168.170.193
PING 192.168.170.193 (192.168.170.193) 56(84) bytes of data.
From 192.168.171.1 icmp_seq=1 Destination Net Unreachable
From 192.168.171.1 icmp_seq=2 Destination Net Unreachable
From 192.168.171.1 icmp_seq=3 Destination Net Unreachable
From 192.168.171.1 icmp_seq=4 Destination Net Unreachable
^C
--- 192.168.170.193 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3080ms

这是因为研发部路由还没配置去往 192.168.170.193 所在网段的路由规则:

1
2
3
root@dev [ ~ ]  ➜ ip route
192.168.170.0/26 dev eth0 proto kernel scope link src 192.168.170.5
192.168.171.0/25 dev eth1 proto kernel scope link src 192.168.171.1

我们为它加上 192.168.170.192/26 网段的路由规则,以法务部路由器 192.168.170.2 为下一跳:

1
2
3
4
5
root@dev [ ~ ]  ➜ ip route add 192.168.170.192/26 via 192.168.170.2
root@dev [ ~ ]  ➜ ip route
192.168.170.0/26 dev eth0 proto kernel scope link src 192.168.170.5
192.168.170.192/26 via 192.168.170.2 dev eth0
192.168.171.0/25 dev eth1 proto kernel scope link src 192.168.171.1

很快我们发现,bruce 可以 ping 通 192.168.170.193 了:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
root@bruce [ ~ ]  ➜ ping 192.168.170.193
PING 192.168.170.193 (192.168.170.193) 56(84) bytes of data.
64 bytes from 192.168.170.193: icmp_seq=1 ttl=63 time=0.106 ms
64 bytes from 192.168.170.193: icmp_seq=2 ttl=63 time=0.164 ms
64 bytes from 192.168.170.193: icmp_seq=3 ttl=63 time=0.156 ms
64 bytes from 192.168.170.193: icmp_seq=4 ttl=63 time=0.523 ms
^C
--- 192.168.170.193 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3037ms
rtt min/avg/max/mdev = 0.106/0.237/0.523/0.166 ms

至此,alice 的主机 192.168.170.194 应该也能 ping 通了吧?但我们很惊讶,结果不通:

1
2
3
4
5
root@bruce [ ~ ]  ➜ ping 192.168.170.194
PING 192.168.170.194 (192.168.170.194) 56(84) bytes of data.
^C
--- 192.168.170.194 ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 3112ms

由前面配置路由器 dev 的经验,我们很快意识到,路由器 law 的转发开关还没有打开:

1
2
root@law [ ~ ]  ➜ cat /proc/sys/net/ipv4/ip_forward
0

我们需要打开这个开关,law 才会帮我们转发 IP 数据包:

1
root@law [ ~ ]  ➜ echo 1 > /proc/sys/net/ipv4/ip_forward

开关打开后,192.168.170.194 还是 ping 不通,我们进一步分析:

  1. 同网段的 192.168.170.193 可以 ping 通,说明去往 192.168.170.194 的数据包应该可以正常送达路由器 law ;
  2. law 已打开转发开关,讲道理数据包应该可以正常送达主机 alice ;
  3. 如果主机 alice 正确回复应答,law 上的路由规则应该可以将回程应答正确送回;
  4. 因此,问题很可能出在主机 alice 上,因路由规则缺失而无法应答;

我们进入主机 alice ,并查看路由表,发现它只有本地网络的路由规则:

1
2
root@alice [ ~ ]  ➜ ip route
192.168.170.192/26 dev eth0 proto kernel scope link src 192.168.170.194

由于缺少主机 bruce 所在网段的路由规则,因此 alice 无法向它恢复应答包。与 bruce 一样,我们给 alice 加上一条默认路由规则,以法务部路由器 192.168.170.193 为下一跳:

1
2
3
4
5
6
root@alice [ ~ ]  ➜ ip route add default via 192.168.170.193
root@alice [ ~ ]  ➜ route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.170.193 0.0.0.0         UG    0      0        0 eth0
192.168.170.192 0.0.0.0         255.255.255.192 U     0      0        0 eth0

配置完毕后,我们很快发现,bruce 已经可以 ping 通 alice 了!

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
root@bruce [ ~ ]  ➜ ping 192.168.170.194
PING 192.168.170.194 (192.168.170.194) 56(84) bytes of data.
64 bytes from 192.168.170.194: icmp_seq=122 ttl=62 time=0.327 ms
64 bytes from 192.168.170.194: icmp_seq=123 ttl=62 time=0.270 ms
64 bytes from 192.168.170.194: icmp_seq=124 ttl=62 time=0.430 ms
64 bytes from 192.168.170.194: icmp_seq=125 ttl=62 time=0.425 ms
^C
--- 192.168.170.194 ping statistics ---
125 packets transmitted, 4 received, 96.8% packet loss, time 126840ms
rtt min/avg/max/mdev = 0.270/0.363/0.430/0.067 ms

在分析 alice 的问题时,我们通过逻辑推理,一步步接近问题的根因。如果简单逻辑分析无法解决问题,则需要在 law 和 alice 上进行抓包,再根据具体情况具体分析。

通过本次实验,我们成功完成了两台路由器的配置工作,掌握了将 Linux 主机配置成静态路由器的技巧:

  1. 打开转发开关:向 /proc/sys/net/ipv4/ip_forward 文件写入 1
  2. 为相关网段配置必要的路由规则;

最后,留一个练习,在本实验的基础上,进一步配置路由 dev 和 market ,让研发部 bruce 可以 ping 通市场部 tom 。

小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注:

【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注: