通过iptables与iproute2协同实现策略路由


Linux 高级路由极简教程(Linux Advanced Routing Mini HOWTO)
本页面是一个关于 Linux 高级路由的小型 HOWTO,在其中及文后均有相关的实践过程。
首先告诉你在哪里可以找到关于 Linux 高级路由的最佳信息来源。你们中的大多数人可能知道或听说过 Linux 高级路由与流量控制网站。在那里可以看到一个非常全面的知识库,不仅基于文档,还通过易于理解的示例来展示...
致谢:Linux 高级路由与流量控制,Thea
好的,那么... 本页面将向你展示如何设置一个 Linux 系统同时使用两个不同的 ISP。
第一个例子:
目标:将来自4个网络的数据包路由到不同的ISP
假设你有两个ISP。在下面的例子中,我将使用RDS和ASTRAL(这两个是我国家的大型ISP)。对于喜欢ASCII艺术图和Lynx控制台浏览器的用户,我会使用以下图表:

在这个设置中,eth1 接口连接到 RDS ISP,而 eth2 接口连接到 ASTRAL ISP。本地网络通过 Linux 路由器连接到互联网云(Internet cloud)。将配置路由器以确保来自不同网络的数据包能够通过相应的ISP进行路由。只会在 Linux 路由器上进行操作。在 root 提示符下执行以下命令:
echo 1 RDS >> /etc/iproute2/rt_tables
echo 2 ASTRAL >> /etc/iproute2/rt_tables
这两条命令用于在 /etc/iproute2/rt_tables 文件中定义新的路由表。即创建了两个新的路由表 RDS 和 ASTRAL,它们分别对应 ID 为 1 和 2 的路由表。接下来,就可以在这些路由表中添加具体的路由规则,以便实现多 ISP 路由或其他复杂的网络配置。
执行上述命令后,/etc/iproute2/rt_tables 文件的内容如下:
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
1 RDS
2 ASTRAL
现在有了三个路由表:RDS表、ASTRAL表和 main表...
接下来需要为每个表添加默认路由:下一步是设置一些路由规则和路由:
对于 RDS 表:
ip route add default via 10.1.1.1 dev eth1 table RDS
ip rule add from 10.11.11.0/24 table RDS
ip rule add from 10.12.12.0/24 table RDS
这三条命令用于配置 Linux 系统中的路由表和策略路由规则。每个命令的作用详细解释如下:
ip route add default via 10.1.1.1 dev eth1 table RDS
这条命令在 RDS 路由表中添加一条默认路由。
default 表示这是一个默认路由,即当没有更具体的路由匹配时使用这条路由。
via 10.1.1.1 指定下一跳(网关)的 IP 地址是 10.1.1.1。
dev eth1 指定数据包将通过网络接口 eth1 发送。
table RDS 指定这条路由应该被添加到名为 RDS 的路由表中。
ip rule add from 10.11.11.0/24 table RDS
这条命令添加一个策略路由规则,指定从源 IP 地址为 10.11.11.0/24 网络的数据包应使用 RDS 路由表进行路由。
from 10.11.11.0/24 指定源 IP 地址范围是 10.11.11.0 到 10.11.11.255。
table RDS 指定这些数据包应使用 RDS 路由表进行路由。
ip rule add from 10.12.12.0/24 table RDS
这条命令与上一条类似,但针对的是源 IP 地址为 10.12.12.0/24 网络的数据包。
from 10.12.12.0/24 指定源 IP 地址范围是 10.12.12.0 到 10.12.12.255。
table RDS 同样指定这些数据包应使用 RDS 路由表进行路由。
这三条命令共同作用是确保来自特定网络(10.11.11.0/24 和 10.12.12.0/24)的数据包将通过 RDS ISP 发送出去,而其他数据包则可能遵循不同的路由规则或默认路由表。
对于 ASTRAL 表:
ip route add default via 10.8.8.1 dev eth2 table ASTRAL
ip rule add from 10.22.22.0/24 table ASTRAL
ip rule add from 10.33.33.0/24 table ASTRAL
要查看路由表:
ip route show table ASTRAL
ip route show table RDS
ip route show table main # 这与 "route -n" 相同,但格式不同...
要查看路由规则(rule):
ip rule show # all the rule list
ip rule show | grep ASTRAL # only for ASRAL
ip rule show | grep RDS # only for RDS
让我解释一下上述规则:
来自 10.11.11.0/24 和 10.12.12.0/24 网络的数据包将查找 RDS 路由表,并且由于我们添加有默认路由,这些数据包会被传递到 RDS 网关(via 10.1.1.1)。
类似地,来自 10.22.22.0/24 和 10.33.33.0/24 网络的数据包将被发送到 ASTRAL 网关(via 10.8.8.1)。
对于那些不在上述规则中显示的其他网络的数据包会发生什么?它们将简单地进入 main 路由表并遵循 main 表的路由规则...如果想阻止它们访问互联网,只需从主表中删除默认路由...(当然,这样做后你的路由器将无法再访问互联网)。
第二个例子:
目标:将目标端口为 22/tcp 的数据包路由到 RDS,将目标端口为 80/tcp 的数据包路由到 ASTRAL(无论这些数据包来自哪个网络)。这个例子几乎与第一个例子相同,只是我们将使用 iptables 来标记数据包。同样的图表...

相同的 /etc/iproute2/rt_tables :
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
1 RDS
2 ASTRAL
在开始之前,请检查您的 iptables 配置。如果不确定接下来要做什么,强烈建议阅读有关 iptables 的资料。
更多文档请访问 iptables 官方主页,或者您可以从该站点(安全与隐私部分)下载一份好的文档。
为了标记目标端口为 22 和 80 的数据包,将使用 MANGLE 表...
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 22 -j MARK --set-mark 1
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 80 -j MARK --set-mark 2
这两条 iptables 命令用于在数据包进入网络协议栈IP层时标记它们,以便后续根据这些标记进行路由决策。详细解释如下:
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 22 -j MARK --set-mark 1
-A PREROUTING:将规则添加到 PREROUTING 链中。PREROUTING 链是在从网卡收到数据包后、进行任何路由决策之前处理的。
-t mangle:指定使用 mangle 表。mangle 表主要用于修改数据包的某些特性,如 TTL、TOS 或标记(mark)。
-i eth0:指定规则应用于通过 eth0 网卡收到的数据包。
-p tcp:指定规则仅适用于 TCP 协议的数据包。
--dport 22:指定目标端口为 22 的数据包(通常是 SSH 服务)。
-j MARK --set-mark 1:如果数据包匹配上述条件,则将其标记为 1。-j 指定目标操作,MARK 是一个目标模块,--set-mark 1 设置标记值为 1。
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 80 -j MARK --set-mark 2
这条命令与上一条类似,但针对的是目标端口为 80 的数据包(通常是 HTTP 服务)。
-p tcp:指定规则仅适用于 TCP 协议的数据包。
--dport 80:指定目标端口为 80 的数据包。
-j MARK --set-mark 2:如果数据包匹配上述条件,则将其标记为 2。
这些标记随后可以被用于策略路由,例如:
标记为 1 的数据包可以通过 RDS ISP 路由。
标记为 2 的数据包可以通过 ASTRAL ISP 路由。
对于 RDS 表:
ip route add default via 10.1.1.1 dev eth1 table RDS # 与第一个例子相同
对于 ASTRAL 表:
ip route add default via 10.8.8.1 dev eth2 table ASTRAL # 与第一个例子相同
下一步是根据标记的数据包添加一些路由规则:
对于 RDS:
ip rule add from all fwmark 1 table RDS
这条命令用于添加一个策略路由规则,该规则基于数据包的防火墙标记(fwmark)来决定使用哪个路由表。详细解释如下:
ip rule add:这是 ip 命令的一个子命令,用于添加新的策略路由规则。
from all:这表示该规则适用于所有源地址的数据包。换句话说,无论数据包的源 IP 地址是什么,只要它们符合其他条件,这条规则都会生效。
fwmark 1:这是一个条件,指定只有当数据包的防火墙标记(fwmark)为 1 时,这条规则才适用。防火墙标记是通过 iptables 或其他工具设置的,用于标识特定类型的数据包。
table RDS:如果数据包满足上述条件(即其防火墙标记为 1),则该数据包将使用名为 RDS 的路由表进行路由决策。
这条规则的效果是:
所有被标记为 1 的数据包(例如,目标端口为 22 的 SSH 数据包)将使用 RDS 路由表进行路由。
如果 RDS 路由表中有一条默认路由(例如,ip route add default via 10.1.1.1 dev eth1 table RDS),那么这些数据包将通过 eth1 接口和网关 10.1.1.1 发送出去。
对于 ASTRAL:
ip rule add from all fwmark 2 table ASTRAL
您可以使用与第一个例子相同的命令来查看路由表和规则列表。现在已经有了一个基于目标端口的路由解决方案了...
通过iptables与iproute2协同实现策略路由
(前提:了解多路由表、策略路由的概念、熟悉iptables和iproute2工具包)
假设网络中有两个外部接口,IP地址分别为eth0:172.16.1.1/24,eth1:10.0.0.1/24,连接内部网络的接口为eth2:192.168.1.1。现在设计这样一个策略,将所有来自内部网络的web服务的数据,走向172.16.1.1这个出口,而其它的数据走向 10.0.0.1 这个出口。
#接口设置
ifconfig eth0 172.16.1.1 netmask 255.255.255.0
ifconfig eth1 10.0.0.1 netmask 255.255.255.0
ifconfig eth2 192.168.1.1 netmask 255.255.255.0
echo 1 >/proc/sys/net/ipv4/ip_forward
#将web服务类的数据包打上标示100
#这一步很关键,用于实现策略路由的是iproute2工具包,但是iproute2工具包是无法根据端口来进行匹配的,因此需要借助iptables来配合
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 100
#增加多路由表,假设172.16.1.1这一出口的网关是172.16.1.254
ip route add 0/0 via 172.16.1.254 table 100
#设置路由策略:凡是数据包标记位上是100的数据,查询100号路由表
ip rule add fwmark 100 table 100
#NAT 如果需要的话,进行NAT,不需要的话,就直接路由
iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE
这里主要是说明了把iptables和iproute2协同以后可以做出很多很强的应用,你可以利用iptables强劲的对数据报的识别能力来将不同类型的数据包打上你自己定义的标示,然后利用iproute2的策略路由的功能来进行路由。
关于策略性路由(iproute2)
策略性是指对于IP包的路由是以网络管理员根据需要定下的一些策略为主要依据进行路由的。例如我们可以有这样的策略:“所有来直自网A的包,选择X路径;其他选择Y路径”,或者是“所有TOS为A的包选择路径F;其他选者路径K”。Cisco 的网络操作系统 (Cisco IOS) 从11.0开始就采用新的策略性路由机制。而Linux是在内核2.1开始采用策略性路由机制的。策略性路由机制与传统的路由算法相比主要是引入了多路由表以及规则的概念。
多路由表(multiple Routing Tables)
传统的路由算法是仅使用一张路由表的。但是在有些情形底下,我们是需要使用多路由表的。例如一个子网通过一个路由器与外界相连,路由器与外界有两条线路相连,其中一条的速度比较快,一条的速度比较慢。对于子网内的大多数用户来说对速度并没有特殊的要求,所以可以让他们用比较慢的路由;但是子网内有一些特殊的用户却是对速度的要求比较苛刻,所以他们需要使用速度比较快的路由。如果使用一张路由表上述要求是无法实现的,而如果根据源地址或其它参数,对不同的用户使用不同的路由表,这样就可以大大提高路由器的性能。
规则(rule)
规则是策略性的关键性的新的概念。我们可以用自然语言这样描述规则,例如我门可以指定这样的规则:
规则一:“所有来自192.16.152.24的IP包,使用路由表10, 本规则的优先级别是1500”
规则二:“所有的包,使用路由表253,本规则的优先级别是32767”
我们可以看到,规则包含3个要素:
什么样的包,将应用本规则(所谓的SELECTOR,可能是filter更能反映其作用);
符合本规则的包将对其采取什么动作(ACTION),例如用那个表;
本规则的优先级别。优先级别越高的规则越先匹配(数值越小优先级别越高)。
策略性路由的配置方法
传统的linux下配置路由的工具是route,而实现策略性路由配置的工具是iproute2工具包。这个软件包是由Alexey Kuznetsov开发的。这里简单介绍策略性路由的配置方法,详细的使用方法请参考Alexey Kuznetsov写的 ip-cfref文档。策略性路由的配置主要包括接口地址的配置、路由的配置、规则的配置。
基于策略的路由比传统路由在功能上更强大,使用更灵活,它使网络管理员不仅能够根据目的地址而且能够根据报文大小、应用或IP源地址来选择转发路径。在/etc/iproute2/rt_tables的这个文件存有linux系统路由表,默认表有255 254 253三张表:
255 local 本地路由表存有本地接口地址,广播地址,已及NAT地址,local表由系统自动维护,管理员不能操作此表。
254 main 主路由表 传统路由表,ip route若没指定表亦操作表254,一般存所有的路由。
注:平时用ip ro sh查看的亦是此表设置的路由。
253 default 默认路由表一般存放默认路由。
注:rt_tables文件中表以数字来区分表0保留最多支持255张表 。
再看路由表默认的所有规则:
# ip rule list
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
规则0,它是优先级别最高的规则,规则规定,所有的包,都必须首先使用local表(254)进行路由。本规则不能被更改和删除。
规则32766,规定所有的包,使用表main进行路由。本规则可以被更改和删除。
规则32767,规定所有的包,使用表default进行路由。本规则可以被更改和删除。
在默认情况下进行路由时,首先会根据规则0在本地路由表里寻找路由,如果目的地址是本网络,或是广播地址的话,在这里就可以找到合适的路由;如果路由失败,就会匹配下一个不空的规则,在这里只有32766规则,在这里将会在主路由表里寻找路由;如果失败,就会匹配32767规则,即寻找默认路由表。如果失败,路由将失败。从这里可以看出,策略性路由是往前兼容的。
策略性路由的应用
基于源地址选路(Source-Sensitive Routing)
如果一个网络通过两条线路接入互联网,一条是比较快的ADSL,另外一条是比较慢的普通的调制解调器。这样的话,网络管理员既可以提供无差别的路由服务,也可以根据源地址的不同,使一些特定的地址使用较快的线路,而普通用户则使用较慢的线路,即基于源址的选路。
根据服务级别选路(Quality of Service)
网络管理员可以根据IP报头的服务级别域,对于不同的服务要求可以分别对待对于传送速率、吞吐量以及可靠性的有不同要求的数据报根据网络的状况进行不同的路由。
节省费用的应用
网络管理员可以根据通信的状况,让一些比较大的阵发性通信使用一些带宽比较高但是比较贵的路径一段短的时间,然后让基本的通信继续使用原来比较便宜的基本线路。例如,管理员知道,某一台主机与一个特定的地址通信通常是伴随着大量的阵发性通信的,那么网络管理员可以安排一些策略,使得这些主机使用特别的路由,这些路由是按需拨号,带宽比较高的线路,通信完成以后就停止使用,而普通的通信则不受影响。这样既提高网络的性能,又能节省费用。
负载平衡(Load Sharing)
根据网络交通的特征,网络管理员可以在不同的路径之间分配负荷实现负载平衡。
Linux系统IPv4/IPv6双栈接入优先使用IPv4设置
根据RFC3484协议Linux默认情况下IPv6优先级高于IPv4,应用程序优先使用IPv6地址。因部分场景下IPv6的使用不一定畅通,可以参照如下方式设置IPv4作为默认的连接方式。
1.使用IPv4连接优先,不禁用IPv6。需要修改gai.conf配置文件使其生效。编辑如下文件:
/etc/gai.conf
查找如下配置,将前面的 # 去掉并保存,如果前面没有 # 号表示已经更改过设置了。如果没有查找到该行直接在文件末尾添加。
precedence ::ffff:0:0/96 100
Redhat默认没有 /etc/gai.conf 该文件,可以执行如下命令,拷贝该文件后修改:
cp -p /usr/share/doc/glibc-common-2.17/gai.conf /etc/
BC-linux执行如下命令:
cp -p /usr/share/doc/glibc-common/gai.conf /etc/
修改完成保存生效。采用此方式,双栈情况下优先使用IPv4,同时不影响IPv6的使用。
说明
::ffff:0:0/96 为IPv4/IPv6转换地址 (IPv4-mapped IPv6 address)。
2.如果确实不需要IPv6,可以采用如下方式禁用IPv6。
echo "1" > /proc/sys/net/ipv6/conf/all/disable_ipv6
如需恢复,删除掉 /proc/sys/net/ipv6/conf/all/disable_ipv6 文件即可。
本页面是一个关于 Linux 高级路由的小型 HOWTO,在其中及文后均有相关的实践过程。
首先告诉你在哪里可以找到关于 Linux 高级路由的最佳信息来源。你们中的大多数人可能知道或听说过 Linux 高级路由与流量控制网站。在那里可以看到一个非常全面的知识库,不仅基于文档,还通过易于理解的示例来展示...
致谢:Linux 高级路由与流量控制,Thea
好的,那么... 本页面将向你展示如何设置一个 Linux 系统同时使用两个不同的 ISP。
第一个例子:
目标:将来自4个网络的数据包路由到不同的ISP
假设你有两个ISP。在下面的例子中,我将使用RDS和ASTRAL(这两个是我国家的大型ISP)。对于喜欢ASCII艺术图和Lynx控制台浏览器的用户,我会使用以下图表:

在这个设置中,eth1 接口连接到 RDS ISP,而 eth2 接口连接到 ASTRAL ISP。本地网络通过 Linux 路由器连接到互联网云(Internet cloud)。将配置路由器以确保来自不同网络的数据包能够通过相应的ISP进行路由。只会在 Linux 路由器上进行操作。在 root 提示符下执行以下命令:
echo 1 RDS >> /etc/iproute2/rt_tables
echo 2 ASTRAL >> /etc/iproute2/rt_tables
这两条命令用于在 /etc/iproute2/rt_tables 文件中定义新的路由表。即创建了两个新的路由表 RDS 和 ASTRAL,它们分别对应 ID 为 1 和 2 的路由表。接下来,就可以在这些路由表中添加具体的路由规则,以便实现多 ISP 路由或其他复杂的网络配置。
执行上述命令后,/etc/iproute2/rt_tables 文件的内容如下:
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
1 RDS
2 ASTRAL
现在有了三个路由表:RDS表、ASTRAL表和 main表...
接下来需要为每个表添加默认路由:下一步是设置一些路由规则和路由:
对于 RDS 表:
ip route add default via 10.1.1.1 dev eth1 table RDS
ip rule add from 10.11.11.0/24 table RDS
ip rule add from 10.12.12.0/24 table RDS
这三条命令用于配置 Linux 系统中的路由表和策略路由规则。每个命令的作用详细解释如下:
ip route add default via 10.1.1.1 dev eth1 table RDS
这条命令在 RDS 路由表中添加一条默认路由。
default 表示这是一个默认路由,即当没有更具体的路由匹配时使用这条路由。
via 10.1.1.1 指定下一跳(网关)的 IP 地址是 10.1.1.1。
dev eth1 指定数据包将通过网络接口 eth1 发送。
table RDS 指定这条路由应该被添加到名为 RDS 的路由表中。
ip rule add from 10.11.11.0/24 table RDS
这条命令添加一个策略路由规则,指定从源 IP 地址为 10.11.11.0/24 网络的数据包应使用 RDS 路由表进行路由。
from 10.11.11.0/24 指定源 IP 地址范围是 10.11.11.0 到 10.11.11.255。
table RDS 指定这些数据包应使用 RDS 路由表进行路由。
ip rule add from 10.12.12.0/24 table RDS
这条命令与上一条类似,但针对的是源 IP 地址为 10.12.12.0/24 网络的数据包。
from 10.12.12.0/24 指定源 IP 地址范围是 10.12.12.0 到 10.12.12.255。
table RDS 同样指定这些数据包应使用 RDS 路由表进行路由。
这三条命令共同作用是确保来自特定网络(10.11.11.0/24 和 10.12.12.0/24)的数据包将通过 RDS ISP 发送出去,而其他数据包则可能遵循不同的路由规则或默认路由表。
对于 ASTRAL 表:
ip route add default via 10.8.8.1 dev eth2 table ASTRAL
ip rule add from 10.22.22.0/24 table ASTRAL
ip rule add from 10.33.33.0/24 table ASTRAL
要查看路由表:
ip route show table ASTRAL
ip route show table RDS
ip route show table main # 这与 "route -n" 相同,但格式不同...
要查看路由规则(rule):
ip rule show # all the rule list
ip rule show | grep ASTRAL # only for ASRAL
ip rule show | grep RDS # only for RDS
让我解释一下上述规则:
来自 10.11.11.0/24 和 10.12.12.0/24 网络的数据包将查找 RDS 路由表,并且由于我们添加有默认路由,这些数据包会被传递到 RDS 网关(via 10.1.1.1)。
类似地,来自 10.22.22.0/24 和 10.33.33.0/24 网络的数据包将被发送到 ASTRAL 网关(via 10.8.8.1)。
对于那些不在上述规则中显示的其他网络的数据包会发生什么?它们将简单地进入 main 路由表并遵循 main 表的路由规则...如果想阻止它们访问互联网,只需从主表中删除默认路由...(当然,这样做后你的路由器将无法再访问互联网)。
第二个例子:
目标:将目标端口为 22/tcp 的数据包路由到 RDS,将目标端口为 80/tcp 的数据包路由到 ASTRAL(无论这些数据包来自哪个网络)。这个例子几乎与第一个例子相同,只是我们将使用 iptables 来标记数据包。同样的图表...

相同的 /etc/iproute2/rt_tables :
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
1 RDS
2 ASTRAL
在开始之前,请检查您的 iptables 配置。如果不确定接下来要做什么,强烈建议阅读有关 iptables 的资料。
更多文档请访问 iptables 官方主页,或者您可以从该站点(安全与隐私部分)下载一份好的文档。
为了标记目标端口为 22 和 80 的数据包,将使用 MANGLE 表...
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 22 -j MARK --set-mark 1
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 80 -j MARK --set-mark 2
这两条 iptables 命令用于在数据包进入网络协议栈IP层时标记它们,以便后续根据这些标记进行路由决策。详细解释如下:
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 22 -j MARK --set-mark 1
-A PREROUTING:将规则添加到 PREROUTING 链中。PREROUTING 链是在从网卡收到数据包后、进行任何路由决策之前处理的。
-t mangle:指定使用 mangle 表。mangle 表主要用于修改数据包的某些特性,如 TTL、TOS 或标记(mark)。
-i eth0:指定规则应用于通过 eth0 网卡收到的数据包。
-p tcp:指定规则仅适用于 TCP 协议的数据包。
--dport 22:指定目标端口为 22 的数据包(通常是 SSH 服务)。
-j MARK --set-mark 1:如果数据包匹配上述条件,则将其标记为 1。-j 指定目标操作,MARK 是一个目标模块,--set-mark 1 设置标记值为 1。
iptables -A PREROUTING -t mangle -i eth0 -p tcp --dport 80 -j MARK --set-mark 2
这条命令与上一条类似,但针对的是目标端口为 80 的数据包(通常是 HTTP 服务)。
-p tcp:指定规则仅适用于 TCP 协议的数据包。
--dport 80:指定目标端口为 80 的数据包。
-j MARK --set-mark 2:如果数据包匹配上述条件,则将其标记为 2。
这些标记随后可以被用于策略路由,例如:
标记为 1 的数据包可以通过 RDS ISP 路由。
标记为 2 的数据包可以通过 ASTRAL ISP 路由。
对于 RDS 表:
ip route add default via 10.1.1.1 dev eth1 table RDS # 与第一个例子相同
对于 ASTRAL 表:
ip route add default via 10.8.8.1 dev eth2 table ASTRAL # 与第一个例子相同
下一步是根据标记的数据包添加一些路由规则:
对于 RDS:
ip rule add from all fwmark 1 table RDS
这条命令用于添加一个策略路由规则,该规则基于数据包的防火墙标记(fwmark)来决定使用哪个路由表。详细解释如下:
ip rule add:这是 ip 命令的一个子命令,用于添加新的策略路由规则。
from all:这表示该规则适用于所有源地址的数据包。换句话说,无论数据包的源 IP 地址是什么,只要它们符合其他条件,这条规则都会生效。
fwmark 1:这是一个条件,指定只有当数据包的防火墙标记(fwmark)为 1 时,这条规则才适用。防火墙标记是通过 iptables 或其他工具设置的,用于标识特定类型的数据包。
table RDS:如果数据包满足上述条件(即其防火墙标记为 1),则该数据包将使用名为 RDS 的路由表进行路由决策。
这条规则的效果是:
所有被标记为 1 的数据包(例如,目标端口为 22 的 SSH 数据包)将使用 RDS 路由表进行路由。
如果 RDS 路由表中有一条默认路由(例如,ip route add default via 10.1.1.1 dev eth1 table RDS),那么这些数据包将通过 eth1 接口和网关 10.1.1.1 发送出去。
对于 ASTRAL:
ip rule add from all fwmark 2 table ASTRAL
您可以使用与第一个例子相同的命令来查看路由表和规则列表。现在已经有了一个基于目标端口的路由解决方案了...
通过iptables与iproute2协同实现策略路由
(前提:了解多路由表、策略路由的概念、熟悉iptables和iproute2工具包)
假设网络中有两个外部接口,IP地址分别为eth0:172.16.1.1/24,eth1:10.0.0.1/24,连接内部网络的接口为eth2:192.168.1.1。现在设计这样一个策略,将所有来自内部网络的web服务的数据,走向172.16.1.1这个出口,而其它的数据走向 10.0.0.1 这个出口。
#接口设置
ifconfig eth0 172.16.1.1 netmask 255.255.255.0
ifconfig eth1 10.0.0.1 netmask 255.255.255.0
ifconfig eth2 192.168.1.1 netmask 255.255.255.0
echo 1 >/proc/sys/net/ipv4/ip_forward
#将web服务类的数据包打上标示100
#这一步很关键,用于实现策略路由的是iproute2工具包,但是iproute2工具包是无法根据端口来进行匹配的,因此需要借助iptables来配合
iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 100
#增加多路由表,假设172.16.1.1这一出口的网关是172.16.1.254
ip route add 0/0 via 172.16.1.254 table 100
#设置路由策略:凡是数据包标记位上是100的数据,查询100号路由表
ip rule add fwmark 100 table 100
#NAT 如果需要的话,进行NAT,不需要的话,就直接路由
iptables -t nat -A POSTROUTING -o eth2 -j MASQUERADE
这里主要是说明了把iptables和iproute2协同以后可以做出很多很强的应用,你可以利用iptables强劲的对数据报的识别能力来将不同类型的数据包打上你自己定义的标示,然后利用iproute2的策略路由的功能来进行路由。
关于策略性路由(iproute2)
策略性是指对于IP包的路由是以网络管理员根据需要定下的一些策略为主要依据进行路由的。例如我们可以有这样的策略:“所有来直自网A的包,选择X路径;其他选择Y路径”,或者是“所有TOS为A的包选择路径F;其他选者路径K”。Cisco 的网络操作系统 (Cisco IOS) 从11.0开始就采用新的策略性路由机制。而Linux是在内核2.1开始采用策略性路由机制的。策略性路由机制与传统的路由算法相比主要是引入了多路由表以及规则的概念。
多路由表(multiple Routing Tables)
传统的路由算法是仅使用一张路由表的。但是在有些情形底下,我们是需要使用多路由表的。例如一个子网通过一个路由器与外界相连,路由器与外界有两条线路相连,其中一条的速度比较快,一条的速度比较慢。对于子网内的大多数用户来说对速度并没有特殊的要求,所以可以让他们用比较慢的路由;但是子网内有一些特殊的用户却是对速度的要求比较苛刻,所以他们需要使用速度比较快的路由。如果使用一张路由表上述要求是无法实现的,而如果根据源地址或其它参数,对不同的用户使用不同的路由表,这样就可以大大提高路由器的性能。
规则(rule)
规则是策略性的关键性的新的概念。我们可以用自然语言这样描述规则,例如我门可以指定这样的规则:
规则一:“所有来自192.16.152.24的IP包,使用路由表10, 本规则的优先级别是1500”
规则二:“所有的包,使用路由表253,本规则的优先级别是32767”
我们可以看到,规则包含3个要素:
什么样的包,将应用本规则(所谓的SELECTOR,可能是filter更能反映其作用);
符合本规则的包将对其采取什么动作(ACTION),例如用那个表;
本规则的优先级别。优先级别越高的规则越先匹配(数值越小优先级别越高)。
策略性路由的配置方法
传统的linux下配置路由的工具是route,而实现策略性路由配置的工具是iproute2工具包。这个软件包是由Alexey Kuznetsov开发的。这里简单介绍策略性路由的配置方法,详细的使用方法请参考Alexey Kuznetsov写的 ip-cfref文档。策略性路由的配置主要包括接口地址的配置、路由的配置、规则的配置。
基于策略的路由比传统路由在功能上更强大,使用更灵活,它使网络管理员不仅能够根据目的地址而且能够根据报文大小、应用或IP源地址来选择转发路径。在/etc/iproute2/rt_tables的这个文件存有linux系统路由表,默认表有255 254 253三张表:
255 local 本地路由表存有本地接口地址,广播地址,已及NAT地址,local表由系统自动维护,管理员不能操作此表。
254 main 主路由表 传统路由表,ip route若没指定表亦操作表254,一般存所有的路由。
注:平时用ip ro sh查看的亦是此表设置的路由。
253 default 默认路由表一般存放默认路由。
注:rt_tables文件中表以数字来区分表0保留最多支持255张表 。
再看路由表默认的所有规则:
# ip rule list
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
规则0,它是优先级别最高的规则,规则规定,所有的包,都必须首先使用local表(254)进行路由。本规则不能被更改和删除。
规则32766,规定所有的包,使用表main进行路由。本规则可以被更改和删除。
规则32767,规定所有的包,使用表default进行路由。本规则可以被更改和删除。
在默认情况下进行路由时,首先会根据规则0在本地路由表里寻找路由,如果目的地址是本网络,或是广播地址的话,在这里就可以找到合适的路由;如果路由失败,就会匹配下一个不空的规则,在这里只有32766规则,在这里将会在主路由表里寻找路由;如果失败,就会匹配32767规则,即寻找默认路由表。如果失败,路由将失败。从这里可以看出,策略性路由是往前兼容的。
策略性路由的应用
基于源地址选路(Source-Sensitive Routing)
如果一个网络通过两条线路接入互联网,一条是比较快的ADSL,另外一条是比较慢的普通的调制解调器。这样的话,网络管理员既可以提供无差别的路由服务,也可以根据源地址的不同,使一些特定的地址使用较快的线路,而普通用户则使用较慢的线路,即基于源址的选路。
根据服务级别选路(Quality of Service)
网络管理员可以根据IP报头的服务级别域,对于不同的服务要求可以分别对待对于传送速率、吞吐量以及可靠性的有不同要求的数据报根据网络的状况进行不同的路由。
节省费用的应用
网络管理员可以根据通信的状况,让一些比较大的阵发性通信使用一些带宽比较高但是比较贵的路径一段短的时间,然后让基本的通信继续使用原来比较便宜的基本线路。例如,管理员知道,某一台主机与一个特定的地址通信通常是伴随着大量的阵发性通信的,那么网络管理员可以安排一些策略,使得这些主机使用特别的路由,这些路由是按需拨号,带宽比较高的线路,通信完成以后就停止使用,而普通的通信则不受影响。这样既提高网络的性能,又能节省费用。
负载平衡(Load Sharing)
根据网络交通的特征,网络管理员可以在不同的路径之间分配负荷实现负载平衡。
Linux系统IPv4/IPv6双栈接入优先使用IPv4设置
根据RFC3484协议Linux默认情况下IPv6优先级高于IPv4,应用程序优先使用IPv6地址。因部分场景下IPv6的使用不一定畅通,可以参照如下方式设置IPv4作为默认的连接方式。
1.使用IPv4连接优先,不禁用IPv6。需要修改gai.conf配置文件使其生效。编辑如下文件:
/etc/gai.conf
查找如下配置,将前面的 # 去掉并保存,如果前面没有 # 号表示已经更改过设置了。如果没有查找到该行直接在文件末尾添加。
precedence ::ffff:0:0/96 100
Redhat默认没有 /etc/gai.conf 该文件,可以执行如下命令,拷贝该文件后修改:
cp -p /usr/share/doc/glibc-common-2.17/gai.conf /etc/
BC-linux执行如下命令:
cp -p /usr/share/doc/glibc-common/gai.conf /etc/
修改完成保存生效。采用此方式,双栈情况下优先使用IPv4,同时不影响IPv6的使用。
说明
::ffff:0:0/96 为IPv4/IPv6转换地址 (IPv4-mapped IPv6 address)。
2.如果确实不需要IPv6,可以采用如下方式禁用IPv6。
echo "1" > /proc/sys/net/ipv6/conf/all/disable_ipv6
如需恢复,删除掉 /proc/sys/net/ipv6/conf/all/disable_ipv6 文件即可。