本实验演示 静态路由 配置方法,迫于没有真实的路由设备,我们拿 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.11 launch-netenv static-router-lab
|
如果打开成功,屏幕将输出 Success 字样:
1
2
|
[Success]
press Ctrl-C to exit
|
实验完毕后,只需按下 Ctrl-C
组合键,即可退出实验环境。
实验环境成功启动后,可以执行 docker 命令登录拓扑中的任意节点。以登录主机 bruce 为例:
1
|
docker exec -it static-router-lab netbox-main launch-netenv nsvm-util enter-nsvm bruce
|
将这行命令最后的 bruce 换成其他节点名,即可登录其他节点。例如登录研发部路由器 dev :
1
|
docker exec -it static-router-lab netbox-main launch-netenv nsvm-util 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 网卡没有任何流量。
为什么研发部路由器没有帮我转发数据包呢?原因通常有二:
- 缺少相关路由规则,但这种情况路由器一般会报告目的不可达差错;
- 内核没有开启 IP 包转发功能;
研发部路由器并没有报告目的不可达差错,因此应该是它没有开启流量转发开关。我们很快就确认了这一点:
1
2
|
root@dev [ ~ ] ➜ cat /proc/sys/net/ipv4/ip_forward
0
|
Linux 路由转发功能是否开启,由一个内核参数控制。该参数可以通过 procfs 访问,路径是 /proc/sys/net/ipv4/ip_forward
。它有两个不同的取值:
我们将 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 不通,我们进一步分析:
- 同网段的 192.168.170.193 可以 ping 通,说明去往 192.168.170.194 的数据包应该可以正常送达路由器 law ;
- law 已打开转发开关,讲道理数据包应该可以正常送达主机 alice ;
- 如果主机 alice 正确回复应答,law 上的路由规则应该可以将回程应答正确送回;
- 因此,问题很可能出在主机 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 主机配置成静态路由器的技巧:
- 打开转发开关:向 /proc/sys/net/ipv4/ip_forward 文件写入
1
;
- 为相关网段配置必要的路由规则;
最后,留一个练习,在本实验的基础上,进一步配置路由 dev 和 market ,让研发部 bruce 可以 ping 通市场部 tom 。
【小菜学网络】系列文章首发于公众号【小菜学编程】,敬请关注: