Linux中需用策略路由配合iptables标记实现服务流量定向:先用iptables对OUTPUT链打fwmark,再通过ip rule和ip route绑定独立路由表,同时处理回程路径与持久化配置。

Linux系统中,要让特定服务(比如某个端口、用户或进程)的网络流量走指定网卡或路由表,不能只靠普通静态路由,必须结合策略路由(Policy Routing)与 iptables/nftables 标记机制来实现访问隔离。
1. 基于用户或端口标记流量
核心思路是:先用 iptables 给匹配的出向数据包打上防火墙标记(fwmark),再让内核根据该标记查指定路由表。例如,让 nginx(运行在 www-data 用户下)所有外发连接强制走 eth1:
- 用 iptables mangle 表对 OUTPUT 链做标记:
iptables -t mangle -A OUTPUT -m owner --uid-owner www-data -j MARK --set-mark 100
(若按端口区分,可改用-m tcp --dport 8080) - 注意:--uid-owner 只对本地发起的连接有效,不适用于转发或容器内进程;Docker 或 systemd 服务需额外处理 UID 或改用 cgroup/bpf 标记
2. 创建独立路由表并配置规则
标记只是起点,还需定义对应路由表和规则,告诉内核“标了 100 的包去查哪张表”:
- 编辑 /etc/iproute2/rt_tables,追加一行:
100 rt_eth1 - 添加策略规则:
ip rule add fwmark 100 table rt_eth1 - 为该表配置默认路由(假设 eth1 网关是 192.168.2.1):
ip route add default via 192.168.2.1 dev eth1 table rt_eth1 - 确保该表有对应网段直连路由(如 eth1 地址是 192.168.2.10/24):
ip route add 192.168.2.0/24 dev eth1 scope link table rt_eth1
3. 处理连接跟踪与回程路径
仅配置出向策略路由会导致响应包可能从主表接口返回,引发 asymmetric routing 或被丢弃。需保证回程也一致:
- 启用反向路径过滤宽松模式(避免因回程接口不匹配而丢包):
sysctl -w net.ipv4.conf.eth1.rp_filter=2 - 若服务监听在 eth1 所在网段,建议绑定监听地址(如 nginx listen 192.168.2.10:80),避免响应从默认接口发出
- 必要时用 iptables 对 RELATED,ESTABLISHED 连接也打相同 mark,确保连接跟踪状态统一:
iptables -t mangle -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j CONNMARK --restore-mark
iptables -t mangle -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j MARK --set-mark 100
4. 持久化与验证
重启后规则会丢失,需固化配置:
- iptables 规则可用 iptables-save > /etc/iptables/rules.v4(Debian/Ubuntu)或使用 systemd 服务加载
- ip rule 和 ip route 建议写入网络管理器脚本(如 NetworkManager dispatcher)、systemd networkd 配置,或封装为 /etc/network/if-up.d/ 脚本
- 验证是否生效:
启动服务后执行 ip rule show 查策略规则;
用 ip route get 8.8.8.8 oif eth1 mark 0x64(0x64 = 100 十六进制)确认查表结果;
抓包 tcpdump -i eth1 port 53 观察 DNS 请求是否真从 eth1 发出











