在拥有多个网络连接的服务器环境中,传统的基于目标地址的路由决策往往无法满足复杂的业务需求,我们可能希望将所有Web流量(HTTP/HTTPS)引导至一个带宽更高但成本也较高的线路,而将其他所有流量(如SSH、数据库同步)通过一个稳定且廉价的线路,这时,策略路由便成为了一个强大的解决方案,它允许网络管理员根据数据包的源地址、目标地址、端口、协议等多种信息,来制定更加精细化的路由规则,本文将以CentOS系统为例,深入探讨如何配置基于端口的策略路由。
策略路由的核心组件
在开始配置之前,理解其背后的三个核心组件至关重要:路由表、路由规则和数据包标记。
多路由表:Linux系统默认使用一张主路由表(
main
,表ID为254),策略路由允许我们创建并管理多张额外的路由表,每张表都可以有自己独立的一套路由规则(默认网关、静态路由等),我们可以在/etc/iproute2/rt_tables
文件中为这些表定义友好的名称,方便管理。路由规则:规则是连接数据包与路由表的桥梁,它定义了一个“选择器”,当数据包满足该选择器的条件时,系统就会查找指定的路由表来进行转发决策,规则的匹配条件可以非常丰富,包括数据包的源IP、目标IP、服务类型(TOS)、防火墙标记等。
数据包标记:这是实现策略路由最常用且最灵活的手段,我们利用
iptables
的mangle
表来“标记”符合特定条件的数据包(所有目标端口为80的数据包被打上标记“100”),我们创建一条路由规则,规定所有被标记为“100”的数据包都去查询我们预先定义好的某个专用路由表。
实战场景:基于端口的流量分流
假设一台CentOS服务器有两张网卡:
eth0
:IP地址为168.1.10
,连接到ISP A,作为默认出口,网关为168.1.1
。eth1
:IP地址为0.0.10
,连接到ISP B,我们希望所有Web流量(TCP 80和443端口)都从此口出去,网关为0.0.1
。
创建并配置自定义路由表
我们需要为ISP B创建一张独立的路由表。
编辑路由表定义文件:
vi /etc/iproute2/rt_tables
在文件末尾添加一行,为我们的新表命名并分配一个ID(ID范围1-252为自定义保留):
# # reserved values # 255 local 254 main 253 default 0 unspec # # local # #1 inr.ruhep # 自定义路由表 100 ISP_B_TABLE
填充路由表内容:
为ISP_B_TABLE
添加默认路由和本地网络路由。# 添加默认路由,所有通过该表查询的流量都发往ISP B的网关 ip route add default via 10.0.0.1 dev eth1 table ISP_B_TABLE # 确保能正确响应从eth1进来的ARP请求等,可添加本地网络路由 ip route add 10.0.0.0/24 dev eth1 src 10.0.0.10 table ISP_B_TABLE
可以查看新表的内容:
ip route show table ISP_B_TABLE
使用iptables标记数据包
我们需要 iptables
来捕获目标端口为80和443的数据包,并为其打上标记(0x1
)。
# 清空mangle表的PREROUTING链(可选,但建议在干净环境下操作) iptables -t mangle -F PREROUTING # 标记目标端口为80(HTTP)的数据包 iptables -t mangle -A PREROUTING -p tcp --dport 80 -j MARK --set-mark 0x1 # 标记目标端口为443(HTTPS)的数据包 iptables -t mangle -A PREROUTING -p tcp --dport 443 -j MARK --set-mark 0x1
说明:
-t mangle
:指定操作mangle表,该表专用于修改数据包的服务类型(TOS)、TTL或标记。-A PREROUTING
:在数据包进入路由决策之前进行处理。--set-mark 0x1
:为匹配的数据包设置一个十六进制标记0x1
,这个数字可以自定义,只需在后续规则中保持一致即可。
创建路由规则,关联标记与路由表
我们创建一条规则,告诉内核:凡是带有 0x1
标记的数据包,都去查阅 ISP_B_TABLE
这张路由表。
# 添加规则 ip rule add fwmark 0x1 table ISP_B_TABLE # 查看现有规则列表 ip rule list
输出结果中应该会包含这样一行:32765: from all fwmark 0x1 lookup ISP_B_TABLE
刷新路由缓存并测试
配置完成后,刷新内核的路由缓存使新规则立即生效。
ip route flush cache
测试方法:
可以从服务器 traceroute
一个公网的Web服务(如 www.google.com
),观察第一跳是否是 0.0.1
,然后再 traceroute
一个其他IP(如 8.8.8
),观察第一跳是否是默认的 168.1.1
,也可以使用 tcpdump -i eth1
或 tcpdump -i eth0
来监听网卡,确认数据包是否按预期流出。
配置的持久化
上述命令在重启后会失效,我们需要将它们保存下来。
保存iptables规则:
service iptables save # 或者在CentOS 7/8上 iptables-save > /etc/sysconfig/iptables
持久化路由和规则:
最推荐的方法是创建一个systemd服务。- 创建服务文件:
vi /etc/systemd/system/policy-routing.service
- 填入以下内容:
[Unit] Description=Apply Policy Routing Rules After=network.target [Service] Type=oneshot ExecStart=/sbin/ip route add default via 10.0.0.1 dev eth1 table ISP_B_TABLE ExecStart=/sbin/ip route add 10.0.0.0/24 dev eth1 src 10.0.0.10 table ISP_B_TABLE ExecStart=/sbin/ip rule add fwmark 0x1 table ISP_B_TABLE ExecStart=/sbin/ip route flush cache RemainAfterExit=yes [Install] WantedBy=multi-user.target
- 启用并启动服务:
systemctl daemon-reload systemctl enable policy-routing.service systemctl start policy-routing.service
- 创建服务文件:
至此,一个完整的、基于端口的策略路由配置就完成了,并且能在系统重启后自动生效。
相关问答FAQs
Q1:策略路由和常规路由的本质区别是什么?
A1: 本质区别在于决策依据的灵活性,常规路由(或称目的地址路由)的决策过程是“一维”的,它只关心数据包的目标IP地址,然后在单一的主路由表中查找最长匹配的路由条目,而策略路由是“多维”的,它在进行常规路由查询之前,增加了一个“策略”匹配阶段,这个阶段可以检查数据包的多种属性(源IP、端口、协议、TOS、防火墙标记等),一旦匹配到某条策略,就会按照该策略指定的路由表进行转发,这使得路由控制从“去哪里”的单一维度,扩展到了“谁、要去哪里、通过什么方式”的多维度精细化管理。
Q2:配置后策略路由不生效,应该如何排查?
A2: 排查问题应遵循从数据包入口到出口的顺序,逐步检查配置点:
- 检查iptables标记:使用
iptables -t mangle -L -v -n
命令,查看PREROUTING链中对应的规则是否有数据包匹配计数(pkts和bytes列),如果计数为零,说明数据包根本没有被这条规则捕获,可能是端口或协议写错了。 - 检查路由规则:使用
ip rule list
确认规则是否已正确添加,检查规则的优先级(数值越小优先级越高),确保没有被其他更早的规则“拦截”。 - 检查自定义路由表:使用
ip route show table <你的表名>
确认表内的路由条目(特别是默认网关)是否正确无误。 - 使用抓包工具:在指定的出口网卡(如本例中的
eth1
)上使用tcpdump -i eth1 port 80
,看是否有相关流量从该网卡发出,如果没有,结合前三步的检查结果定位问题,如果有,但无法通信,则可能是ISP B的线路本身存在问题(如NAT、防火墙等)。
【版权声明】:本站所有内容均来自网络,若无意侵犯到您的权利,请及时与我们联系将尽快删除相关内容!
发表回复