前言

你可能会想:“都折腾 OpenWrt 了,直接装个‘师夷长技以制夷’插件不就完事儿了?”没错,对于许多场景来说,这确实是最简单直接的方法。但是,如果你的主路由性能不太给力,或者你不想在主路由上开启这类服务(比如担心折腾时影响家人正常上网),那该怎么办呢?

我之前的方案是在 PVE 里用 LXC 部署一个 Debian 容器,在容器里跑 Mihomo 内核作为旁路网关。然后,主路由通过 DHCP Option 6 通告这个 Debian 容器的 IP 地址给局域网设备,从而实现透明代理。但这个方案有个小缺陷:DHCP 只能通告 IPv4 地址。当设备同时获取到 IPv4 和 IPv6 地址时,访问需要代理的网站可能会优先选择 IPv6 直连,这就导致了代理失效、DNS 泄露等问题。

为了解决 IPv4/IPv6 双栈环境下国内外流量分流的问题,我查阅了不少资料。网上的教程大多是针对 ROS 或 iKuai 系统,OpenWrt 的方案要么语焉不详,要么比我接下来要介绍的方法更复杂。因此,我整理了这篇文章,希望能给有同样需求的朋友提供一个清晰、简单的解决方案。

准备工作

本文的核心是如何在 OpenWrt/ImmortalWrt 系统的主路由上,通过防火墙和策略路由实现国内外 IPv4/IPv6 流量的精确分流。我们不涉及刷机、安装特定插件或 DNS 优化等内容。

你需要准备:

  • 一台性能尚可、已安装 OpenWrt/ImmortalWrt 系统的主路由。

  • 我使用的环境:ImmortalWrt 24.10.1,firewall4 防火墙(基于 nftables)。其他 OpenWrt 变种系统可以参考后续的配置文件进行调整。

  • 清晰的思路和基本的网络知识。大部分操作都可以在 LuCI 图形界面完成,按理说不容易出错。如果遇到问题,请仔细检查每一步操作。

开始配置

下载国内 IP 地址列表

我们将使用 BGP IP 列表来区分国内和国外流量。这里推荐两个常用的 IP 列表源:

通过 SSH 连接到你的主路由,执行以下命令下载 IP 列表:

wget https://raw.githubusercontent.com/gaoyifan/china-operator-ip/refs/heads/ip-lists/china.txt -O /etc/luci-uploads/cn_ipv4.txt
wget https://raw.githubusercontent.com/gaoyifan/china-operator-ip/refs/heads/ip-lists/china6.txt -O /etc/luci-uploads/cn_ipv6.txt

注意:

  • 文件名可以自定义,但建议保持 cn_ipv4.txt 和 cn_ipv6.txt 以方便后续操作。

  • 保存目录必须是 /etc/luci-uploads/,因为后续在 LuCI 界面创建 IP 集时,只能选择此目录下的文件。

  • 如果你的网络环境不需要 IPv6 分流,可以省略第二条命令和后续所有 IPv6 相关步骤。

添加 IP 集 (IP Sets)

IP 集用于在防火墙规则中高效地匹配大量的 IP 地址。

登录 LuCI 界面,导航到 网络 (Network) -> 防火墙 (Firewall) -> IP 集 (IP Sets),然后点击 添加 (Add)。

IPv4 IP 集配置:

  • 名称 (Name): cn_ipv4 (建议不修改,与后续步骤保持一致)

  • 注释 (Remark): (可选,例如:China IPv4 Addresses)

  • Family: IPv4

  • Packet Field Match: Destination (sub)net

  • Include File: 点击下拉框,选择刚才下载的 cn_ipv4.txt 文件。

image.png

IPv6 IP 集配置 (如果需要):

重复上述步骤,添加 IPv6 的 IP 集。

  • 名称 (Name): cn_ipv6

  • 注释 (Remark): (可选,例如:China IPv6 Addresses)

  • Family: IPv6

  • Packet Field Match: Destination (sub)net

  • Include File: 选择 cn_ipv6.txt 文件。

完成后,你应该能看到两个 IP 集(或一个,如果你只配置了 IPv4)。

image.png

这一步的目的是将下载的国内 IP 地址列表加载到防火墙中,以便后续规则引用。

添加防火墙通信规则 (Traffic Rules)

接下来,我们需要创建防火墙规则,对发往 非国内 IP 的流量打上标记 (firewall mark)。

导航到 网络 (Network) -> 防火墙 (Firewall) -> 通信规则 (Traffic Rules),点击 添加 (Add)。

IPv4 流量标记规则:

常规设置 (General Settings):

  • 名称 (Name): Proxy_Mark_V4 (可以自定义)

  • 协议 (Protocol): TCP+UDP (或者 Any,根据你的需求选择)

  • 源区域 (Source zone): lan

  • 目标区域 (Destination zone): 任意区域 (转发) (或 Any zone (forwarding))

  • 操作 (Action): apply firewall mark

  • Set mark: 0x100/0x100 (这个标记值可以自定义,但要确保后续路由规则中引用的标记值与之匹配。0x100 是一个常用的值。)

高级设置 (Advanced Settings):

  • Restrict to address family: IPv4

  • Use ipset: !cn_ipv4 (注意这里是英文感叹号 ! 开头,表示 不匹配 cn_ipv4 这个 IP 集。如果上一步修改了 IP 集名称,这里也要相应修改。手动输入后按回车确认。)

  • 源 MAC 地址 (Source MAC address): (可选) 如果你只想对特定设备进行分流,可以在这里添加设备的 MAC 地址。留空则表示对 lan 区的所有设备生效。

image.png image.png

IPv6 流量标记规则 (如果需要):

重复上述步骤,为 IPv6 流量添加类似的标记规则。

常规设置 (General Settings):

  • 名称 (Name): Proxy_Mark_V6

  • 协议 (Protocol): TCP+UDP

  • 源区域 (Source zone): lan

  • 目标区域 (Destination zone): 任意区域 (转发)

  • 操作 (Action): apply firewall mark

  • Set mark: 0x100/0x100 (保持与 IPv4 规则一致的标记值,或使用不同的标记值并在后续路由规则中对应修改)

高级设置 (Advanced Settings):

  • Restrict to address family: IPv6

  • Use ipset: !cn_ipv6

  • 源 MAC 地址 (Source MAC address): (可选)

重要提示: 设备的有线网卡、2.4GHz Wi-Fi 和 5GHz Wi-Fi 通常具有不同的 MAC 地址。如果按 MAC 地址限制,请确保添加所有需要分流的接口的 MAC 地址。

防火墙配置完成 (或通过配置文件修改)

如果你习惯直接修改配置文件,或者 LuCI 界面无法完成上述操作,可以编辑/etc/config/firewall 文件。

config ipset
	option name 'cn_ipv4'
	option family 'ipv4'
	list match 'dest_net'
	option loadfile '/etc/luci-uploads/cn_ipv4.txt'

config ipset
	option name 'cn_ipv6'
	option family 'ipv6'
	list match 'dest_net'
	option loadfile '/etc/luci-uploads/cn_ipv6.txt'

config rule
	option name 'Proxy_Mark_V4'
	option src 'lan'
	option dest '*'
	option family 'ipv4'
	option ipset '!cn_ipv4' # 注意感叹号
	option target 'MARK'
	option set_mark '0x100/0x100'
	# list src_mac '11:22:33:44:55:66' # 如果需要按MAC过滤,取消注释并修改
	# list src_mac 'AA:BB:CC:DD:EE:FF' # 可以添加多个MAC地址

config rule
	option name 'Proxy_Mark_V6'
	option src 'lan'
	option dest '*'
	option family 'ipv6'
	option ipset '!cn_ipv6' # 注意感叹号
	option target 'MARK'
	option set_mark '0x100/0x100'
	# list src_mac '11:22:33:44:55:66'

编辑完成后,通过 SSH 执行以下命令重启防火墙使配置生效:

service firewall restart

验证 IP 集是否加载成功:

nft list set inet fw4 cn_ipv4
nft list set inet fw4 cn_ipv6

如果配置正确,这两个命令会输出对应的 IP 地址列表。

添加自定义路由表

我们需要为代理流量创建独立的路由表。编辑 /etc/iproute2/rt_tables 文件 (如果文件不存在,则新建它),在文件开头添加以下内容:

100 proxy_v4
200 proxy_v6

100 和 200 是路由表的 ID,可以自定义,但要确保与后续步骤一致。

proxy_v4 和 proxy_v6 是路由表的名称,方便记忆。

添加静态路由 (Static Routes)

现在,我们要为上面创建的自定义路由表添加指向旁路网关的默认路由。

导航到 网络 (Network) -> 路由 (Routing) -> IPv4 静态路由 (Static IPv4 Routes),点击 添加 (Add)。

IPv4 静态路由配置:

  • 常规设置 (General Settings):

  • 接口 (Interface): lan (或者你的旁路网关所在的接口)

  • 路由类型 (Route type): unicast

  • 目标 (Target): 0.0.0.0/0

  • 网关 (Gateway): 192.168.1.135 (修改为你的旁路网关的 IPv4 地址)

高级设置 (Advanced Settings):

  • 表 (Table): proxy_v4 (100)
image.png

IPv6 静态路由配置 (如果需要):

导航到 网络 (Network) -> 路由 (Routing) -> IPv6 静态路由 (Static IPv6 Routes),点击 添加 (Add)。

常规设置 (General Settings):

  • 接口 (Interface): lan

  • 路由类型 (Route type): unicast

  • 目标 (Target): ::/0

  • 网关 (Gateway): fe80::11:22:33:44 (修改为你的旁路网关的 IPv6 链路本地地址。通常可以在旁路网关设备上通过 ip -6 addr show dev <interface_name> 查看,选择 scope link 的地址)

高级设置 (Advanced Settings):

  • 表 (Table): proxy_v6 (200)
image.png

添加路由规则 (Routing Rules / Policy Routing)

最后一步是创建路由规则,将打了标记的流量导向我们刚刚配置的自定义路由表。

导航到 网络 (Network) -> 路由 (Routing) -> IPv4 规则 (IPv4 Rules),点击 添加 (Add)。

IPv4 路由规则配置:

常规设置 (General Settings):

  • 优先级 (Priority): 10000 (这是一个较小的值,确保此规则优先于默认规则。可以根据实际情况调整,避免与其他自定义规则冲突。)

  • 规则类型 (Rule type): unicast

  • 传入接口 (Inbound interface): lan

  • 源地址 (Source address): 0.0.0.0/0 (或留空)

  • 目标地址 (Destination address): 0.0.0.0/0 (或留空)

高级设置 (Advanced Settings):

  • 表 (Lookup table): proxy_v4 (100)

  • 防火墙标志 (Firewall mark): 0x100/0x100 (与之前防火墙通信规则中设置的 Set mark 值一致)

image.png image.png

IPv6 路由规则配置 (如果需要):

导航到 网络 (Network) -> 路由 (Routing) -> IPv6 规则 (IPv6 Rules),点击 添加 (Add)。

常规设置 (General Settings):

  • 优先级 (Priority): 10000

  • 规则类型 (Rule type): unicast

  • 传入接口 (Inbound interface): lan

  • 源地址 (Source address): ::/0 (或留空)

  • 目标地址 (Destination address): ::/0 (或留空)

高级设置 (Advanced Settings):

  • 表 (Lookup table): proxy_v6 (200)

  • 防火墙标志 (Firewall mark): 0x100/0x100

image.png

路由配置完成 (或通过配置文件修改)

同样的,如果你偏好使用配置文件,可以编辑 /etc/config/network 文件,添加以下内容:

config route
	option interface 'lan'
	option target '0.0.0.0/0'
	option gateway '192.168.1.135' # 修改为旁路网关IPv4地址
	option table 'proxy_v4'

config route6
	option interface 'lan'
	option target '::/0'
	option gateway 'fe80::11:22:33:44' # 修改为旁路网关IPv6链路本地地址
	option table 'proxy_v6'

config rule
	option priority '10000'
	option in 'lan'
	option lookup 'proxy_v4'
	option mark '0x100/0x100'

config rule6
	option priority '10000'
	option in 'lan'
	option lookup 'proxy_v6'
	option mark '0x100/0x100'

编辑完成后,通过 SSH 执行以下命令重启网络服务使配置生效:

service network restart

验证路由和规则是否生效:

ip -4 rule show
ip -6 rule show
ip -4 route show table proxy_v4 # 或者 ip -4 route show table 100
ip -6 route show table proxy_v6 # 或者 ip -6 route show table 200

这些命令应该能正确输出你配置的路由规则和自定义路由表中的内容。

成果与流量模型

恭喜!完成以上所有步骤后,你的主路由就已经具备了国内外 IPv4/IPv6 双栈流量分流的能力。
网络流量模型流程图:

image.png

或者查看网页:https://metaso.cn/s/8E3PfFQ

现在,你的局域网设备应该可以智能地分流国内外流量了,无论是 IPv4 还是 IPv6,都能得到妥善处理。享受更流畅的网络体验吧!

更新国内IP列表

如果你需要更新BGP IP列表,找AI写个脚本,然后在Luci导航到系统->计划任务中添加计划即可,注意,先清空IPset再重载防火墙

nft flush set inet fw4 cn_ipv4
fw4 reload