当前位置: 首页 > news >正文

Linux 策略路由深度解析

默认路由只能"不知道去哪就走这条",而策略路由(Policy Routing)能:“HTTP 走这条、SSH 走那条、来自办公室的流量走 VPN”。本文从 Linux 内核路由框架出发,系统解析ip rule、多路由表、iptables打标联动,及相应场景示例。

一、内核路由框架

1.1 为什么需要策略路由?

普通路由决策只依赖目标 IP 地址查路由表:

数据包 → 查 main 路由表 → 匹配目标网段 → 送出

策略路由则可以在查路由表之前,先根据多种条件选择用哪张路由表:

数据包 → 查 RPDB(规则库)→ 命中规则 → 查指定路由表 → 送出 │ ├── 条件可以是:源 IP、fwmark、TOS、入接口... └── 每条规则指向一张独立的路由表

1.2 内核路由查找流程

否: 转发/本机发出

数据包到达

是本地入站?

查 local 表
优先级 0

遍历 RPDB 规则
按优先级从小到大

规则条件匹配?

查规则指向的路由表

找到路由?

按该路由转发

所有规则都不匹配?

返回不可达

1.3 三张默认路由表

Linux 启动后自动创建三张路由表,定义在/etc/iproute2/rt_tables

$cat/etc/iproute2/rt_tables# reserved values255local# 本地地址和广播地址路由(内核维护,勿手动修改)254main# 主路由表(ip route 命令默认操作的表)253default# 默认路由表(通常为空,可被 ip rule 引用)0unspec# 未指定

优先级关系(数值越小优先级越高):

表名表号用途是否可自定义
local255本地接口 IP、loopback、广播否,内核自动管理
main254用户添加的常规路由
default253备用默认路由
自定义1-252策略路由专用表

二、ip rule:路由策略数据库

2.1 核心概念

ip rule管理的是RPDB(Routing Policy DataBase,路由策略数据库),它决定每个数据包用哪张路由表。

每条规则的组成:

优先级 : 匹配条件 → 动作(查哪张路由表)

2.2 查看当前规则

$iprule show0: from all lookuplocal# 本地流量优先32766: from all lookup main# 默认走 main 表32767: from all lookup default# 最后兜底走 default 表

字段解读

字段含义
0/32766优先级(priority),数字越小越优先
from all匹配条件:来自所有地址
lookup local/main/default动作:查哪张表

2.3 匹配条件一览

策略路由的强大之处在于多维度的匹配能力

# ===== 按源地址 =====ipruleaddfrom192.168.1.0/24 table100ipruleaddfrom10.0.0.5 table200# ===== 按目标地址 =====ipruleaddto8.8.8.8 table300# ===== 按入接口 =====ipruleaddiif eth0 table100ipruleaddiif ppp0 table vpn# VPN 拨号接口# ===== 按 fwmark(防火墙标记)=====ipruleaddfwmark1table100ipruleaddfwmark2table200# ===== 按 TOS(服务类型)=====ipruleaddtos 0x10 table100# 低延迟流量# ===== 按 fwmark + 源地址组合 =====ipruleaddfwmark1from192.168.1.0/24 table100# ===== 按 UID(用户)=====ipruleadduidrange1000-1000 table user_table# ===== 按协议端口(需要 iptables 配合)=====# 先用 iptables 按端口打 fwmark,再用 fwmark 匹配

2.4 规则管理

# 添加规则(指定优先级)ipruleaddfrom192.168.2.0/24 table200priority100# 删除规则iprule del from192.168.2.0/24 table200iprule del priority100# 清空所有规则(危险操作!会删掉默认规则)iprule flush# 仅在指定优先级处插入ipruleaddfrom192.168.3.0/24 table300pref5000

三、多路由表场景

3.1 HTTP 走专线,其余走默认

需求:本机192.168.0.36,HTTP(80端口) 走网关192.168.0.3,其余流量走192.168.0.1

网络拓扑:

默认流量

HTTP 80

本机 192.168.0.36

网关 .1
普通出口

网关 .3
专线/代理

互联网

互联网

完整配置:

# Step 1: 查看当前路由和规则(基准对比)iproute showiprule show# Step 2: 注册自定义路由表# 向 /etc/iproute2/rt_tables 追加echo"100 out_http">>/etc/iproute2/rt_tables# Step 3: 给自定义表添加路由# 注意:不仅要加默认路由,还要加直连网段路由iprouteadd192.168.0.0/24 dev eth0 table out_http# 直连网段iprouteadddefault via192.168.0.3 table out_http# 默认走 .3# Step 4: main 表保持默认路由iprouteadddefault via192.168.0.1# 或者已有则跳过# Step 5: 用 iptables 给 80 端口出站流量打上 fwmark 3iptables-tmangle-AOUTPUT-ptcp--dport80-jMARK --set-mark3# Step 6: 创建规则——fwmark=3 的包查 out_http 表ipruleaddfwmark3table out_http# Step 7: 验证配置iprule showiproute show table out_http iptables-tmangle-LOUTPUT-n-v

关键细节:自定义路由表必须包含直连网段路由192.168.0.0/24 dev eth0),否则本机发出的包在查out_http表时找不到到网关192.168.0.3的 ARP 路径,导致"目标不可达"。


3.2 双出口负载均衡

需求:两个 ISP 出口,按源 IP 分流——办公室网段走 ISP-A,服务器网段走 ISP-B。

# 注册两张自定义表echo"100 isp_a">>/etc/iproute2/rt_tablesecho"200 isp_b">>/etc/iproute2/rt_tables# ISP-A 出口配置(eth0, 网关 192.168.1.1)iprouteadd192.168.1.0/24 dev eth0 table isp_aiprouteadddefault via192.168.1.1 table isp_a# ISP-B 出口配置(eth1, 网关 10.0.0.1)iprouteadd10.0.0.0/24 dev eth1 table isp_biprouteadddefault via10.0.0.1 table isp_b# 策略规则:按源 IP 选择出口ipruleaddfrom192.168.1.0/24 table isp_a# 办公室走 ISP-Aipruleaddfrom10.0.0.0/24 table isp_b# 服务器走 ISP-B

验证出站路径:

# 从不同源 IP 发起请求,观察走的网关curl--interface192.168.1.100 https://ifconfig.me# 应显示 ISP-A 的公网 IPcurl--interface10.0.0.50 https://ifconfig.me# 应显示 ISP-B 的公网 IP

3.3 VPN 分流(目标直连,其他走 VPN)

# VPN 拨号后产生 ppp0 接口echo"50 vpn">>/etc/iproute2/rt_tables# VPN 表的路由iprouteadddefault dev ppp0 table vpn# 目标 IP 段走 main 表(直连),其余走 VPN# 需要配合 ipset + iptables 做批量打标ipset create china hash:net# 把目标 IP 段加入 ipset(省略,通常借助脚本批量导入)# ipset add china 1.0.1.0/24# ...# iptables: 目标不是目标 IP 的打上 fwmark 50iptables-tmangle-AOUTPUT-mset!--match-set china dst-jMARK --set-mark50# 规则: fwmark 50 → 走 VPN 表ipruleaddfwmark50table vpn

四、iptables 打标联动

4.1 为什么需要 iptables 配合?

ip rule本身只能匹配 IP 层元数据(源/目标 IP、TOS、入接口),无法看端口。需要通过 Netfilter 框架在数据包上打出 fwmark 标记ip rule再根据标记选路。

4.2 fwmark 的工作流

路由表RPDB(ip rule)Netfilter(iptables)应用程序路由表RPDB(ip rule)Netfilter(iptables)应用程序发出 HTTP 请求 (dport=80)mangle/OUTPUT 链匹配 dport 80 → 打 fwmark=3包进入路由决策规则 fwmark 3 命中→ 查表 out_http查 out_http 表default via 192.168.0.3从 eth0 送出,下一跳 192.168.0.3

4.3 打标位置选择

# PREROUTING: 所有入站包(含本机接收和转发)iptables-tmangle-APREROUTING-ptcp--dport80-jMARK --set-mark3# OUTPUT: 本机发出的包(最常用)iptables-tmangle-AOUTPUT-ptcp--dport80-jMARK --set-mark3# FORWARD: 经过本机转发的包iptables-tmangle-AFORWARD-ptcp--dport80-jMARK --set-mark3
适用场景
PREROUTING本机作为路由器,为转发流量做策略路由
OUTPUT本机作为客户端发出流量(最常用)
FORWARD本机作为网关,转发其他主机的流量

4.4 高级打标:组合条件

# 按端口 + 目标 IPiptables-tmangle-AOUTPUT-ptcp--dport443-d10.0.0.0/8-jMARK --set-mark10# 按用户 UIDiptables-tmangle-AOUTPUT-mowner --uid-owner1000-jMARK --set-mark20# 按进程 GIDiptables-tmangle-AOUTPUT-mowner --gid-owner2000-jMARK --set-mark30# 按连接状态iptables-tmangle-AOUTPUT-mstate--stateNEW-ptcp--dport22-jMARK --set-mark40# 恢复已有的 connmarkiptables-tmangle-AOUTPUT-jCONNMARK --restore-mark

CONNMARK:连接级别的标记。配合--save-mark可以在连接的首包打标后自动应用到该连接的所有后续包,避免每个包都重新匹配规则。

4.5 持久化配置

# iptables 规则持久化aptinstalliptables-persistent iptables-save>/etc/iptables/rules.v4# ip rule/route 持久化# 方法一:写入 /etc/network/interfacescat>>/etc/network/interfaces<<'EOF' auto eth0 iface eth0 inet static address 192.168.0.36 netmask 255.255.255.0 gateway 192.168.0.1 up ip route add default via 192.168.0.3 table out_http up ip rule add fwmark 3 table out_http EOF# 方法二:systemd networkd 或 NetworkManager dispatcher 脚本cat>/etc/NetworkManager/dispatcher.d/10-policy-route<<'EOF' #!/bin/bash if [ "$2" = "up" ]; then ip route add 192.168.0.0/24 dev eth0 table out_http ip route add default via 192.168.0.3 table out_http ip rule add fwmark 3 table out_http fi EOFchmod+x /etc/NetworkManager/dispatcher.d/10-policy-route

五、复杂场景

5.1 多出口故障切换(Failover)

使用ip route的多跳(multipath)或检测脚本:

# 方案 A: 基于 metric 的静态备份iprouteadddefault via192.168.0.1 metric100# 主线路,metric 低优先iprouteadddefault via192.168.0.3 metric200# 备线路,metric 更高# 方案 B: 静态多路径(加权负载 + 故障检测)# 需要内核开启 CONFIG_IP_ROUTE_MULTIPATHiprouteadddefault nexthop via192.168.0.1 weight1\nexthop via192.168.0.3 weight1# 方案 C(生产推荐): keepalived + 检测脚本# 检测主线路通断,自动切换路由

5.2 基于 cgroup 的进程级路由

# 创建 cgroupmkdir-p/sys/fs/cgroup/net_cls/viagw3echo0x00100003>/sys/fs/cgroup/net_cls/viagw3/net_cls.classid# iptables 匹配 cgroupiptables-tmangle-AOUTPUT-mcgroup--cgroup0x00100003-jMARK --set-mark3# 将进程加入 cgroupecho$PID>/sys/fs/cgroup/net_cls/viagw3/tasks# 至此该进程所有出站流量走 out_http 表

5.3 命名空间级路由隔离

# 创建独立网络命名空间ipnetnsaddns1# 在 ns1 中配置独立的路由策略ipnetnsexecns1ipruleaddfrom10.0.0.2 table100ipnetnsexecns1iprouteadddefault via10.0.0.1 table100# 在 ns1 中运行程序ipnetnsexecns1curlhttps://example.com

六、nftables 现代替代

iptables正在被nftables取代。同样的策略路由,nftables 写法更简洁:

# nftables 替代 iptablesnftaddtable inet mangle nftaddchain inet mangle OUTPUT{typeroute hook output priority mangle\;}nftaddrule inet mangle OUTPUT tcp dport80meta markset3# 保存nft list ruleset>/etc/nftables.conf

nftables vs iptables 对比

维度iptablesnftables
语法每个表/链独立命令统一层级语法
性能每个规则独立内核模块单个nf_tables内核模块
IPv4/IPv6分别管理inet族统一管理
动态更新需替换整条规则支持原子规则添加

七、排障方法

7.1 策略路由排障三步法

Step 1:确认规则匹配

# 查看规则优先级顺序iprule show|sort# 确认打标是否生效iptables-tmangle-LOUTPUT-n-v# 看 pkts 计数器是否增长

Step 2:确认路由表可达

# 模拟查指定表iproute get8.8.8.8 mark3# 输出: 8.8.8.8 via 192.168.0.3 dev eth0 table out_http mark 3# 确认下一跳 ARP 可达ipneigh show|grep192.168.0.3

Step 3:确认接口和逆向路由

# 数据包实际走的接口对不对?iproute get8.8.8.8 from192.168.0.36# 抓包验证tcpdump-ieth0-nhost192.168.0.3 and port80

7.2 常见问题

问题现象根因解决办法
策略路由不生效优先级比 main 表默认规则低调整优先级,确认ip rule顺序
标记后依然走错出口自定义路由表缺少直连网段路由添加ip route add 192.168.0.0/24 dev eth0 table xxx
iptables 打标无效果打在了错误链上(如在 PREROUTING 打本机出站包)本机出站用OUTPUT
重启后规则丢失未持久化使用 iptables-persistent + 启动脚本
反向路径过滤(rp_filter)丢包内核认为包从来路不对sysctl net.ipv4.conf.all.rp_filter=0

八、命令手册

命令速查

# ===== ip rule =====iprule show# 查看所有规则ipruleaddfrom SRC table TABLE# 按源 IPipruleaddfwmark MARK table TABLE# 按防火墙标记ipruleaddiif IFACE table TABLE# 按入接口iprule del priority N# 按优先级删除# ===== ip route =====iproute show table TABLE# 查看指定路由表iprouteaddNETWORK dev IFACE table TABLE# 添加网段路由iprouteadddefault via GW table TABLE# 添加默认路由iproute get DST[mark MARK][from SRC]# 模拟路由查找# ===== iptables (mangle) =====iptables-tmangle-L-n-v# 查看 mangle 表(带计数器)iptables-tmangle-AOUTPUT-ptcp--dportPORT-jMARK --set-mark N iptables-tmangle-AOUTPUT-mowner --uid-ownerUID-jMARK --set-mark N# ===== 持久化 =====iptables-save>/etc/iptables/rules.v4

路由表号约定

1-252 : 用户自定义策略路由表 253 : default 表 254 : main 表(默认) 255 : local 表(内核保留)
http://www.jsqmd.com/news/1080073/

相关文章:

  • IntelliJ IDEA 2025安装包校验失败?JetBrains官网已悄然下架SHA-256旧签名证书——紧急启用新校验密钥指南(仅限48小时内有效)
  • 开封全屋定制谁家最便宜
  • Delphi 设计期窗口DPI设置
  • 关于激光管安装的相关事宜
  • 计算机毕业设计之基于SSM的锦州风味美食推广系统设计与实现
  • AI真能替代安全专家吗?聊聊AI技术在入侵检测系统中的作用与挑战
  • 亲子娱乐想让家庭再来,不能只让孩子玩、大人等
  • GHelper终极指南:华硕笔记本性能调校的完整解决方案
  • 对比中法意英日五国服饰溢价系数,量化不同国家文化赋予服装的附加价值。
  • 终极Windows右键菜单管理指南:ContextMenuManager完全使用教程
  • Windows 7 SP2完整方案深度解析:让经典系统在现代硬件上重获新生
  • 用「丢了目标函数的训练任务」比喻,聊聊长期提不起劲怎么破
  • 告别环境配置噩梦:我用FlyEnv三天,彻底扔掉了Docker Desktop
  • 《断魂剑》定档 7 月 21 日 爱奇艺优酷双平台燃爆今夏
  • Scale-Across场景与技术方案初探
  • python网络爬虫学习
  • 低代码与原生开发博弈,2026 小程序开发行业技术趋势报告
  • Window 安装 MySQL流程(可视化工具)
  • 终极NVIDIA Profile Inspector使用指南:解锁显卡隐藏性能的免费神器
  • DVWA文件包含漏洞实战:从原理到高级利用与防御
  • 你的ERP/MES成本数据为什么不准?问题可能出在BOM的数据治理上
  • okbiye AI 数据分析:零基础一键生成论文数据报告,甩掉 SPSS 繁琐操作
  • 安卓APK反编译与防护实战:从JADX原理到多层次安全加固
  • 第8篇:初遇Power Query——一键清洗大区报表
  • 终极指南:如何使用unp4k工具解密和提取Star Citizen游戏资源
  • 高考热门专业十年大洗牌:你爸妈推荐的那些,大学自己都不开了
  • 灵晟登顶-OpenAI自研芯片-高通入场-AI算力三线突围
  • 4个月小白也能拿下大模型Offer?收藏这份2026校招必看指南!
  • 深度解析PX4神经网络控制:如何让无人机像老司机一样智能飞行
  • 兰亭妙微原创作品 | 智能制造驾驶舱UI设计