Linux 高级路由教程
多年来,我们在办公室一直使用普通的 ADSL——快速下载速度,慢速上传,高延迟——所有这些都以 1 美元/GB 的价格为代价。我们在性能和可靠性方面遇到了很多问题,经过几年的挣扎,我们决定获得第二条上行链路——SHDSL 5M/5M 对称链路——低延迟,白天速度稳定。这简直太棒了。

图 1. 网络概览
然而,SHDSL 很昂贵!虽然国内流量是免费的,但国际流量是 5 美元/GB。相比之下,ADSL 国内和国际流量均为 1 美元/GB(表 1)。
表 1. ADSL 与 SHDSLADSL | SHDSL | |
---|---|---|
速度 | 7M 下载/1M 上传 | 5M 下载/5M 上传 |
国内价格 | 1 美元/GB | 免费 |
国际价格 | 1 美元/GB | 5 美元/GB |
公共 IP 地址 | 1 | 1 + /28 |
两者都有明显的优点和缺点。这让我思考(而且我不常这样做),如果我们保留 ADSL 用于对我们来说不太重要的国际流量,而主要使用 SHDSL 用于国内流量——快速且便宜,会怎么样?

图 2. 在国际和国内之间拆分流量
我们还通过 SHDSL 获得了一个 /28 子网用于 DMZ,显然,我们希望所有进出 DMZ 的流量都通过 SHDSL 链路,无论它是国内流量还是国际流量。

图 3. 进出 DMZ 的流量
路由 101为了使我的计划奏效,公司核心路由器需要某种方式来判断从办公室工作站到开放互联网上的 IP.AD.DR.ES 的数据包是国内的还是国际的,并相应地通过 ADSL 或 SHDSL 发送。路由器使用其路由表来决定它们转发的数据包的命运和路径。一个地址为 192.168.130.100 的办公室工作站的简单路由表可能如下所示
[workstation] ~ # ip route show
192.168.130.0/24 dev eth0 proto kernel scope link
↪src 192.168.130.100
default via 192.168.130.1 dev eth0
这表示所有到 192.168.130.0/24 范围内其他地址的流量都应直接发送到连接到接口 eth0 的本地网段。所有其他流量都遵循“默认”路由,并被移交给 IP 为 192.168.130.1 的路由器进行处理。假设我们要发送一个数据包到 8.8.4.4,Google 的公共 DNS 服务器。首先,我们尝试“ping 8.8.4.4”,并在工作站的 eth0 接口上使用 tcpdump 观察流量
[workstation] ~ # tcpdump -i eth0 -n -s0 -e
listening on eth0, link-type EN10MB (Ethernet),
↪capture size 65535 bytes
[1] 17:53:59.615650 00:16:17:ec:5c:6c > ff:ff:ff:ff:ff:ff,
↪ethertype ARP (0x0806), length 42:
Request who-has 192.168.130.1 tell 192.168.130.100,
↪length 28
[2] 17:53:59.615775 00:14:c2:5b:4f:2c > 00:16:17:ec:5c:6c,
↪ethertype ARP (0x0806), length 60:
Reply 192.168.130.1 is-at 00:14:c2:5b:4f:2c, length 46
[3] 17:53:59.615796 00:16:17:ec:5c:6c > 00:14:c2:5b:4f:2c,
↪ethertype IPv4 (0x0800), length 98:
192.168.130.100 > 8.8.4.4: ICMP echo request,
↪id 3082, seq 1, length 64
我的工作站查询了目标 IP 8.8.4.4 的路由表,并意识到它应该将数据包发送到默认路由器 192.168.130.1。为此,它需要路由器的低级以太网地址(也称为 MAC 地址),上面 tcpdump 输出中的第一个数据包,标记为 [1],正是这样做的——通过向网络段上的所有节点“广播”请求来请求 IP 192.168.130.1 的 MAC 地址。第二个数据包,标记为 [2],是一个回复——IP 192.168.130.1 的 MAC 地址是 00:14:c2:5b:4f:2c。最后,PING 数据包可以被发送,目标 IP 为 8.8.4.4,路由器的 MAC 地址为 00:14:c2:5b:4f:2c(参见标记为 [3] 的行)。
一切都很好,所以现在我们可以假设我们的路由器收到了数据包,并将进一步将其转发到目的地。让我们看看路由器上会发生什么。
我们配置了 ADSL 和 SHDSL 链路,但默认情况下,所有流量都通过 ADSL 发送。ADSL 调制解调器的地址为 192.168.128.254。目前,SHDSL 链路 203.0.113.36/30 处于空闲状态。这是路由表
[router] ~ # ip route show
[1] 203.0.113.36/30 dev vlan-shdsl proto kernel
↪scope link src 203.0.113.38
[2] 192.168.128.0/24 dev vlan-adsl proto kernel
↪scope link src 192.168.128.1
[3] 192.168.130.0/24 dev vlan-office proto kernel
↪scope link src 192.168.130.1
[4] default via 192.168.128.254 dev vlan-adsl
第一行 [1] 是 SHDSL 链路——我们在该链路上的路由器 IP 是 203.0.113.38。第二行是到 ADSL 调制解调器的链路;第三行 [3] 是包含我的工作站的网络段,最后,第四行 [4] 是默认路由。所有与第 1、2 或 3 行上的任何本地子网都不匹配的数据包都将发送到 ADSL 调制解调器 192.168.128.254,然后由它将它们转发给 ISP 2。这也是我们发送到 8.8.4.4 的数据包的命运。让我们通过调用 ip route get
快速验证一下会发生什么
[router] ~ # ip route get 8.8.4.4 from 192.168.130.100
↪iif vlan-office
8.8.4.4 from 192.168.130.100 via 192.168.128.254 dev vlan-adsl
如您所见,它将“通过 192.168.128.254”发送,这是 ADSL 调制解调器。检查从我的工作站到任何给定目标地址的完整网络路径的简单方法是 traceroute 命令。它显示了到达目的地的路径上的所有路由器(“跃点”)
[workstation] ~ $ /usr/sbin/traceroute 8.8.4.4
traceroute to 8.8.4.4 (8.8.4.4), 30 hops max,
↪40 byte packets using UDP
1 gw-vlan-office.e-it.co.nz (192.168.130.1)
↪0.156 ms 0.126 ms 0.124 ms
2 gw-vlan-adsl.e-it.co.nz (192.168.128.254)
↪0.853 ms 0.831 ms 0.830 ms
3 core-adsl.isp2 (218.101.x.y)
↪11.765 ms 19.173 ms 19.066 ms
4 core-xyz.isp2 (203.98.x.y)
↪16.052 ms 15.515 ms 17.153 ms
[... some more hops ...]
13 64.233.x.y (64.233.x.y) 193.826 ms 194.230 ms 194.412 ms
14 * * *
15 google-public-dns-b.google.com (8.8.4.4)
↪196.086 ms 195.909 ms 195.816 ms
如您所见,第一个跃点是我们的路由器 192.168.130.1。第二个跃点是 ADSL 调制解调器 192.168.128.254。第三个跃点是 ISP2 的核心路由器之一,依此类推,经过 11 个以上的路由器,数据包最终到达目的地 8.8.4.4,又名 google-public-dns-b.google.com。
国内与国际流量Google 的公共 DNS 服务器 B 显然是一个离岸国际目的地。然而,根 DNS 服务器之一,即 IP 为 192.5.5.241 的 f.root-servers.net,就在新西兰本地。目前,到 f.root-servers.net 的 traceroute 仍然显示 ADSL 路径
[workstation] ~ $ /usr/sbin/traceroute f.root-servers.net
traceroute to f.root-servers.net (192.5.5.241), 30 hops max,
↪40 byte packets using UDP
1 gw-vlan-office.e-it.co.nz (192.168.130.1)
↪0.175 ms 0.126 ms 0.125 ms
2 gw-vlan-adsl.e-it.co.nz (192.168.128.254)
↪0.861 ms 0.840 ms 0.825 ms
3 core-adsl.isp2 (218.101.x.y) 22.456 ms 22.298 ms 23.501 ms
4 isp2.ape.net.nz (192.203.154.x) 21.035 ms 20.928 ms 21.268 ms
5 isc2.ape.net.nz (192.203.154.y) 20.689 ms 21.724 ms 24.187 ms
6 f.root-servers.net (192.5.5.241) 26.680 ms 26.059 ms 25.427 ms
这显然是国内流量,根据我们的计划,它应该通过 SHDSL 链路输出。我们可以手动执行此操作,并在我们的核心路由器上设置适当的路由
[router] ~ # ip route add 192.5.5.241 via 203.0.113.37
↪dev vlan-shdsl
关于 NAT 的旁注:我们还需要将办公室地址范围 192.168.130.0/24 转换为我们的 SHDSL 公共 IP 203.0.113.38(或“伪装”或 NAT)。如果我们不这样做,数据包的源 IP 将为 192.168.130.100,并且回复将永远无法返回到我的工作站,因为此地址范围在公共互联网中不可路由。讨论防火墙和 NAT 超出了本文的范围,但为了让您入门,这里是最简单的魔法命令
[router] ~ # iptables -t nat -A POSTROUTING -s 192.168.128.0/20
↪-o vlan-shdsl -j DNAT --to 203.0.113.38
所有源地址来自 192.168.128.0/20 范围并通过接口 vlan-shdsl 离开的数据包的源地址都将被重写为 203.0.113.38。我们不需要为 ADSL 路径设置任何伪装,因为 ADSL 路由器在那里 NAT 了我们所有的出站流量。
现在,让我们检查一下新的网络路径
[workstation] ~ $ /usr/sbin/traceroute f.root-servers.net
traceroute to f.root-servers.net (192.5.5.241), 30 hops max,
↪40 byte packets using UDP
1 gw-vlan-office.e-it.co.nz (192.168.130.1)
↪0.190 ms 0.129 ms 0.125 ms
2 rt-shdsl.isp1 (203.0.113.37) 2.676 ms 2.599 ms 2.632 ms
3 rt3.isp1 (121.98.ab.cd) 2.715 ms 2.680 ms 2.591 ms
4 isc2.ape.net.nz (192.203.154.z) 2.919 ms 3.033 ms 3.088 ms
5 f.root-servers.net (192.5.5.241) 3.007 ms 2.670 ms 2.864 ms
这好多了。第一个跃点保持不变,那是我的工作站路由器,但第二个跃点不再是 ADSL 调制解调器。相反,它是 SHDSL ISP1 的核心路由器。它还清楚地显示了延迟的改善——从 ADSL 的 26 毫秒到 SHDSL 的 3 毫秒。
让我们再次删除手动路由,以避免将来出现任何混淆,并查询路由表
[router] ~ # ip route get 192.5.5.241 from
↪192.168.130.100 iif vlan-office
192.5.5.241 from 192.168.130.100 via 203.0.113.37
↪dev vlan-shdsl # SHDSL
[router] ~ # ip route delete 192.5.5.241 via 203.0.113.37
↪dev vlan-shdsl
[router] ~ # ip route get 192.5.5.241 from
↪192.168.130.100 iif vlan-office
192.5.5.241 from 192.168.130.100 via 192.168.128.254
↪dev vlan-adsl # ADSL
所以我们现在需要做的就是列出所有国内 IP 地址,将它们放入路由表中,我们就完成了。但是如何做呢?手动吗?即使在新西兰这样的小国,也有数百个本地 IP 地址和前缀,而且列表是动态的,每天都在变化。这种列表不可能手动管理。我们需要一个更好的工具。
喂养 BirdBGP 是当今互联网的路由协议。地球上的每个 ISP 都告诉地球上所有其他 ISP,它在其网络中拥有哪些 IP 地址,以及可以通过该 ISP 的网络访问哪些其他 IP 地址。交换此类信息的协议称为 BGP(边界网关协议)。
我不会深入探讨 BGP 的细节。我们只需要知道我们的 ISP1 可以使用 BGP 向我们发送所有国内前缀的列表。我们将监听“BGP feed”并从中更新我们的路由表,而不是手动输入它们。这部分需要与互联网提供商协调,所以我要求我们的 ISP1“请为我们分配一个私有 ASN,并向我们发送包含国内前缀的 BGP feed”。BGP 通常在由 ASN(自治系统号)标识的自治系统之间运行。任何足够大的组织都可以申请并支付其自己的官方 ASN,但对于我们的目的而言,使用 ISP 分配的私有范围内的 ASN 就足够了。表 2 显示了我从他们那里收到的信息。
表 2. 来自 ISP1 的信息ISP | 公司 | |
---|---|---|
ASN | 177XY | 6452X |
路由器 IP | 203.0.113.37 | 203.0.113.38 |
通告的前缀 | 所有国内前缀 | 无 |
现在我们有了链路两侧的路由器 IP,两个 ASN 以及他们将发送给我们的前缀的确认(“所有国内前缀”)。这就是我们需要的所有信息。
许多 BGP 守护程序可用于 Linux。我选择了 Bird(当时,最新版本是 1.3.4),并从 RPM 安装了它。
Bird 的配置非常简单。配置文件位于 /etc/bird/bird.conf,可能如下所示
log syslog all;
protocol kernel {
import none;
export all;
}
protocol device {
scan time 10;
}
protocol bgp {
description "ISP1 National Routes";
local as 64526;
neighbor 203.0.113.37 as 17746;
source address 203.0.113.38;
import all; # Accept all prefixes from our neighbor
export none; # Don't send the neighbor any prefixes
}
本质上,Bird 进程与 BGP 邻居对话,并将所有通告的前缀导入其内部路由列表。它还与内核对话,并将它知道的所有路由“导出到内核”——即所有通过 BGP 学习到的路由。这样,它就可以通过 BGP feed 填充内核路由表。
导入 BGP 路由后,内核路由表现在有 4,000 多个记录
[router] ~ # ip route show
[1] 203.0.113.36/30 dev vlan-shdsl proto kernel
↪scope link src 203.0.113.38
[2] 192.168.128.0/24 dev vlan-adsl proto kernel
↪scope link src 192.168.128.1
[3] 192.168.130.0/24 dev vlan-office proto kernel
↪scope link src 192.168.130.1
[4] default via 192.168.128.254 dev vlan-adsl
[5] 14.1.32.0/19 via 203.0.113.37 dev vlan-shdsl proto bird
[6] 27.252.0.0/16 via 203.0.113.37 dev vlan-shdsl proto bird
[7] 58.28.0.0/16 via 203.0.113.37 dev vlan-shdsl proto bird
....
[4509] 203.97.0.0/17 via 203.0.113.37 dev vlan-shdsl proto bird
[4510] 222.153.128.0/18 via 203.0.113.37 dev vlan-shdsl proto bird
[4511] 222.155.96.0/19 via 203.0.113.37 dev vlan-shdsl proto bird
第 [1] 到 [4] 行与您之前看到的相同——所有直接连接的子网和默认路由。第 [5] 到 [4511] 行是通过 BGP 接收的路由。
现在,让我们查询新填充的路由,以查找通往我们最喜欢的 f.root-servers.net 的路径
[router] ~ # ip route get 192.5.5.241 from
↪192.168.130.100 iif vlan-office
192.5.5.241 from 192.168.130.100 via
↪203.0.113.37 dev vlan-shdsl # SHDSL
太棒了,这就是我们想要的!从工作站到国内和国际目的地的几次 traceroute 运行验证了新路径按预期使用。
DMZ 挑战我们的第二条互联网链路的要求之一是能够为我们的 DMZ(隔离区)获取一块公共 IP 地址,我们计划在 DMZ 中托管一些外部可访问的服务。从 ISP 那里,我们获得了 203.0.113.208/28 区块,我们希望所有进出 DMZ 的流量都使用 SHDSL 链路,无论它是国内流量还是国际流量。入站流量的路由是 ISP 的责任,但出站流量是我们的工作。
让我们看看我们当前的设置会发生什么。在测试 DMZ 框 203.0.113.222 上,路由表如下所示
[dmz-box] ~ # ip route show
203.0.113.208/28 dev eth0 proto kernel
↪scope link src 203.0.113.222
default via 203.0.113.209 dev eth0
所有流量都流向路由器 IP 203.0.113.209,然后路由器决定做什么。让我们再次 traceroute 到 Google 的公共 DNS 服务器,看看会发生什么
[dmz-box] ~ # traceroute 8.8.4.4
traceroute to 8.8.4.4 (8.8.4.4), 30 hops max, 60 byte packets
1 gw-dmz.e-it.co.nz (203.0.113.209) 0.175 ms 0.110 ms 0.110 ms
2 gw-vlan-adsl.e-it.co.nz (192.168.128.254)
↪8.707 ms 9.080 ms 9.522 ms
3 core-adsl.isp2 (218.101.x.y) 11.899 ms 13.555 ms 15.585 ms
4 core-xyz.isp2 (203.98.x.y) 15.114 ms 16.332 ms 17.142 ms
[... some more hops ...]
13 64.233.x.y (64.233.x.y) 195.061 ms 198.098 ms 197.589 ms
14 * * *
15 google-public-dns-b.google.com (8.8.4.4)
↪203.621 ms 204.588 ms 205.792 ms
那不是我们想要的。流量通过 ADSL 链路而不是 SHDSL 链路。但是,这是可以理解的。我们的路由器仅根据目标 IP 选择网络路径,而忽略源 IP。一旦它看到一个发往 8.8.4.4 的数据包,它就会将其发送到 ADSL 路径,无论它来自我在 192.168.130.100 的工作站还是来自 DMZ 框 203.0.113.222。
幸运的是,Linux 内核最多可以有 255 个独立的路由表和最多 32,768 条不同的规则,用于指定为每个数据包查找哪个路由表。最新 Linux 机器上的标准规则集如下所示
[router] ~ # ip rule show
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
规则没有约束。对于“来自所有”地址的数据包,可以查询所有三个规则,直到找到匹配的路由。根据规则,“local”表首先被查找。“local”表由内核维护,包含广播地址和类似的特殊目的地的规则。您可以列出其内容,但除非您确切知道自己在做什么,否则最好不要更改它
[router] ~ # ip route show table local
broadcast 192.168.130.0 dev vlan-office proto kernel
↪scope link src 192.168.130.1
local 192.168.130.1 dev vlan-office proto kernel
↪scope host src 192.168.130.1
local 203.0.113.38 dev vlan-shdsl proto kernel
↪scope host src 203.0.113.38
broadcast 203.0.113.39 dev vlan-shdsl proto kernel
↪scope link src 203.0.113.38
broadcast 127.0.0.0 dev lo proto kernel
↪scope link src 127.0.0.1
local 127.0.0.1 dev lo proto kernel scope host src 127.0.0.1
[... a lot more routes ...]
如果在“local”表中未找到匹配项,则内核将继续执行下一条规则,即“lookup main”。“main”表是标准表,所有“正常”路由都最终到达那里——所有直接连接的子网的路由、手动添加的静态路由以及来自 BGP 的路由。命令 ip route show
默认与“main”表一起工作,并且等效于 ip route show table main
。如果仍然没有找到匹配项,则最后一条规则表示“lookup default”。“default”表很少使用,通常为空。
实际上,内核表具有数字 ID,“main”、“local”和“default”这些词只是在 /etc/iproute2/rt_tables 中定义的方便的详细名称
[router] ~ # cat /etc/iproute2/rt_tables
#
# reserved values
#
255 local
254 main
253 default
0 unspec
因此,回顾一下我们目前的情况,我们有一个“main”表,其中包含所有 SHDSL 的国内路由列表和一个 ADSL 的默认路由,用于所有国际流量。而且,我们有一个默认规则,即“对于所有源地址,查询 main 表”。
解决 DMZ 挑战我们现在需要做的是为所有 DMZ 流量设置一个特殊的路由表,并创建一个规则将其插入到路由决策过程中。
第一步是创建并填充新表,并将其命名为“dmz”。我们可以选择任何未保留的表 ID,并在 rt_table 文件中添加一行,将 ID 映射到我们想要的名称
[router] ~ # echo "121 dmz" >> /etc/iproute2/rt_tables
[router] ~ # ip route show table dmz
[router] ~ #
dmz 表目前为空。让我们填充它。显然,我们只需要默认路由——所有内容都应发送到 ISP1 的网关
[router] ~ # ip route add default via 203.0.113.37
↪dev vlan-shdsl table dmz
[router] ~ # ip route show table dmz
default via 203.0.113.37 dev vlan-shdsl
我们现在需要做的就是通过向路由决策过程添加查找规则来激活该表。查找规则可以基于许多不同的参数——源和/或目标地址或地址范围、传入接口、TOS(服务类型)或与 iptables 规则结合使用的任意“fwmark”值。对于我们的目的,源 IP 和传入网络接口是我们需要的“选择器”
[router] ~ # ip rule add pri 1000 from 203.0.113.208/28
↪iif vlan-dmz lookup dmz
[router] ~ # ip rule show
0: from all lookup local
1000: from 203.0.113.208/28 iif vlan-dmz lookup dmz
32766: from all lookup main
32767: from all lookup default
所有来自接口 vlan-dmz 且源地址为 203.0.113.208/28 的数据包都将查询 dmz 表。dmz 表表示默认情况下将它们全部发送到 SHDSL 链路。让我们看看它是否有效
[dmz-box] ~ # traceroute 8.8.4.4
traceroute to 8.8.4.4 (8.8.4.4), 30 hops max, 60 byte packets
1 gw-dmz.e-it.co.nz (203.0.113.209)
↪0.200 ms 0.124 ms 0.110 ms
2 rt-shdsl.isp1 (203.0.113.37) 2.676 ms 2.599 ms 2.632 ms
3 rt3.isp1 (121.98.ab.cd) 2.715 ms 2.680 ms 2.591 ms
[... some more hops ...]
10 216.239.xx.yy (216.239.xx.yy)
↪172.955 ms 172.398 ms 172.339 ms
11 * * *
12 google-public-dns-b.google.com (8.8.4.4)
↪171.703 ms 171.621 ms 170.554 ms
看起来不错。来自 DMZ 中的框的国际流量通过 SHDSL 链路传输,与此同时,我们可以重新检查一下,来自内部 LAN 中的工作站的流量仍然通过 ADSL 传输
[workstation] ~ # traceroute 8.8.4.4
traceroute to 8.8.4.4 (8.8.4.4), 30 hops max,
↪40 byte packets using UDP
1 gw-vlan-office.e-it.co.nz (192.168.130.1)
↪0.170 ms 0.128 ms 0.125 ms
2 gw-vlan-adsl.e-it.co.nz (192.168.128.254)
↪0.861 ms 0.846 ms 0.825 ms
3 core-adsl.isp2 (218.101.x.y) 22.718 ms 22.109 ms 21.931 ms
4 core-xyz.isp2 (203.98.x.y) 20.417 ms 20.222 ms 19.769 ms
[... some more hops ...]
13 64.233.x.y (64.233.x.y) 198.456 ms 197.824 ms 197.189 ms
14 * * *
15 google-public-dns-b.google.com (8.8.4.4)
↪194.318 ms 194.153 ms 194.159 ms
神奇,不是吗!一切看起来都很好,我们完成了,对吗?嗯,不完全是。
DMZ 路由的更多工作从我的工作站 ping DMZ 框时会发生什么?首先,ping 数据包从 192.168.130.100 发送到路由器。路由器查询“main”路由表,看到目标 203.0.113.222 在直接连接的 vlan-dmz 上,并将 ping 请求发送到那里。DMZ 框使用来自 203.0.113.222 到 192.168.130.100 的数据包回复——那是 vlan-office 上的我的工作站——并将其发送到路由器。路由器看到它来自 DMZ 地址范围,并查询“dmz”表!其中唯一的记录是默认路由,因此它采用该路由并将目标 IP 为 192.168.130.100 的数据包发送到 ISP,最终在那里被丢弃。糟糕!

图 4. DMZ 和办公室之间的流量中断
有很多解决方案。我们可以将“main”表中的所有非 BGP 路由复制到“dmz”表——这确实是可能的,但不是很优雅。更好的选择是在“dmz”表中添加一个新的路由条目,当匹配时,它将使内核继续执行列表中的下一条规则
[router] ~ # ip rule show
0: from all lookup local
1000: from 203.0.113.208/28 iif vlan-dmz lookup dmz
32766: from all lookup main
32767: from all lookup default
[router] ~ # ip route add throw 192.168.128.0/20 table dmz
[router] ~ # ip route show table dmz
throw 192.168.128.0/20
default via 203.0.113.37 dev vlan-shdsl
现在 ping 回复数据包会发生什么:内核看到匹配规则 1000 并查找“dmz”表。在那里,它发现目标为 192.168.130.100 的最佳匹配路由是“throw”。这告诉它选择下一个可用的规则——在我们的例子中是“32766: from all lookup main”,并查找“main”表。在这里,它找到了通往 192.168.130.0/24 子网的路径,并将 ping 回复发送到 vlan-office。问题已解决。
另一种同样好甚至更好的方法是,对于所有来自 DMZ 且目的地是我们公司内部地址范围的数据包,直接转到“main”表。让我们为其添加一个规则
[router] ~ # ip rule add pri 999 from 203.0.113.208/28
↪iif vlan-dmz to 192.168.128.0/20 table main
[router] ~ # ip rule show
0: from all lookup local
999: from 203.0.113.208/28 to 192.168.128.0/20
↪iif vlan-dmz lookup main
1000: from 203.0.113.208/28 iif vlan-dmz lookup dmz
32766: from all lookup main
32767: from all lookup default
有了这条规则,路由器将看到 ping 回复数据包与规则“from 203.0.113.208/28 to 192.168.128.0/20”匹配,并将立即查找“main”表而不是“dmz”表。就我个人而言,我最喜欢这个解决方案,因为它明确地表示“lookup main”,而不是像前一个解决方案那样更模糊的“转到下一条规则”,无论它可能是什么。

图 5. DMZ 流量按预期工作。
使更改永久生效到目前为止,我们所做的许多更改仅在路由器的内存中,并且在重新启动后将消失。让我们使它们永久生效。我们的核心路由器是 CentOS 6.2,以下步骤应适用于任何最新的基于 Red Hat Enterprise Linux 或 Fedora 的系统。
已经为“dmz”表指定了一个永久名称
[router] ~ # cat /etc/iproute2/rt_tables
# reserved values
255 local
254 main
253 default
0 unspec
# local
121 dmz
要添加新的 ip 规则,请编辑文件 /etc/sysconfig/network-scripts/rule-<interface>。一旦配置了给定的接口,规则将被加载。加载我们的规则的逻辑位置是在配置 DMZ 接口 vlan-dmz 之后
[router] ~ # cat /etc/sysconfig/network-scripts/rule-vlan-dmz
# ip rule add ...
pri 999 from 203.0.113.208/28 to 192.168.128.0/20
↪iif vlan-dmz lookup main
pri 1000 from 203.0.113.208/28 iif vlan-dmz lookup dmz
最后,在重新启动时填充“dmz”表。这在同一目录中的 route-<interface> 文件中完成
[router] ~ # cat /etc/sysconfig/network-scripts/route-vlan-dmz
# ip route add ...
default via 203.0.113.37 dev vlan-shdsl table dmz
# throw 192.168.128.0/20 table dmz ## unless the rule 999 is in place
就这样。路由现在按设计工作,并在重新启动后仍然有效。
网络 201?我在本文中解释的主题——多路由表、选择它们的规则以及 BGP 的提示——应该为您提供足够的知识来构建中等复杂的基于 Linux 的路由器。在这个行业中,您将遇到更多概念——从 OSPF 到防火墙和 NAT,再到 VPN 和高可用性网络。这些主题都不在本文的范围之内;但是,最后,使所有这些网络乐趣成为可能的核心是路由。如果您学习了 IP 路由如何工作的几个简单概念,您将了解网络的一半内容。祝您实验愉快!