家里这套网络我折腾了很久:华硕 RT-BE88U 当主路由拨号,一台刷了 ImmortalWRT 的Intel N100小主机当旁路由跑 OpenClash,全屋终端网关指向旁路由,分流、去广告、海外流量各走各的,一直很稳。
直到技术奇客ITGeeker.net打算上 IPv6开始就出现各种无法访问的问题了。
那天之后,YouTube 开始转圈,部分设备的分流直接失效,旁路由的流量统计里几乎看不到这些设备。查了一圈才明白:IPv6 把旁路由整个绕过去了。
这不是配置错了,是 IPv6 的设计如此。这篇文章把原理、两种落地方案,以及后面踩到的那个更隐蔽的坑(硬件加速让防火墙规则失效)一次讲清楚。
为什么”旁路由 + IPv6″天然打架
IPv4 时代的旁路由很好理解:主路由关掉 DHCP,终端拿到的网关和 DNS 都是旁路由的地址,流量自然先经过旁路由,再决定直连还是走代理。为了不出乱子,大家通常还会在主路由上把 NAT 关掉或者干脆不用 NAT——反正旁路由自己会处理。
IPv6 不是这么玩的。IPv6 默认不做 NAT,主路由通过 RA(路由通告)和 DHCPv6 给内网每个终端发一个独立的公网地址,同时告诉终端”默认网关是我”。终端拿到地址后,访问 IPv6 目标时直接走主路由,旁路由连包都看不到。
结果就是:
- 走 IPv4 的流量:乖乖经过旁路由,分流正常
- 走 IPv6 的流量:从主路由直接出去,分流、去广告、代理全部失效
- 更糟的是,很多应用(尤其是 Google 系)会优先用 IPv6,于是”能打开但很慢/打不开”的怪现象就来了
而且华硕官方固件(包括梅林)在 IPv6 的 RA 里不给你改网关的选项,想把 IPv6 默认网关强行指到旁路由,界面里根本找不到地方。这就是所有方案的分岔点。
两条路:过滤 AAAA,或者 NAT6 强接管
| 方案 | 核心思路 | 适合谁 | 代价 |
|---|---|---|---|
| A. 过滤 AAAA | 主路由正常发 IPv6,但旁路由的 DNS 把所有 AAAA 记录过滤掉,终端只能用 IPv4 出网 | 大多数家庭;只要分流生效,不要求终端有公网 IPv6 | 终端没有 IPv6 出口;依赖 DNS 全部走旁路由 |
| B. NAT6 强接管 | 旁路由自己发 RA、自己做 IPv6 NAT,终端把旁路由当 IPv6 网关 | 必须让终端真正用公网 IPv6 跑代理 | 配置复杂,容易和主路由的 RA 打架、断流 |
我的建议很明确:先上 A,除非你有明确的”终端必须用 IPv6″的需求。 A 方案稳定到几乎不会出问题,B 方案则是能用,但对固件和动手能力要求都高。
方案 A:过滤 AAAA,让终端老老实实走 IPv4
原理一句话:让 DNS 层面”看不见” IPv6 地址,终端自然就不会去连 IPv6。
主路由(华硕 RT-BE88U)
- 进 高级设置 → IPv6
- 联机类型选 Native
- 接口按实际情况选 PPPoE(路由器拨号)或 自动获取 IP(光猫拨号)
- 打开 DHCP-PD,让主路由正常下发 IPv6 前缀
这一步不需要做任何”指向旁路由”的操作——华硕也做不到。保持 IPv6 正常工作即可。
旁路由(ImmortalWRT)
第一步:让旁路由自己有 IPv6
旁路由自己要走 IPv6 出网、也要能被外网访问(NAS 穿透就靠它),所以要单独给它一个 WAN6 接口:
- 网络 → 接口 → 添加新接口
- 名称填
WAN6,协议选 DHCPv6 客户端 - 设备选
@lan(绑定到原有 LAN 口的别名) - 提交后进入 WAN6 的高级设置,勾选 使用默认网关
- 在同一页的 DHCP 服务器 → IPv6 设置 里,把 RA 服务、DHCPv6 服务、NDP 代理 全部设为 已禁用
注意最后这一步:旁路由只”自己上网”,不负责给局域网发地址,否则就会和主路由抢着当 IPv6 网关,轻则断流,重则整网掉线。
第二步:过滤 AAAA(核心)
网络 → DHCP/DNS → 高级设置,勾选 过滤 IPv6 AAAA 记录(Filter IPv6 AAAA entries),保存并应用。
第三步:分流插件配合
在 OpenClash / HomeProxy / Passwall 里:
- 勾选 允许不合规的 DNS 解析(否则被过滤后的空结果会被插件当成解析失败)
- 在插件的 DNS 设置里关闭 IPv6 解析,避免它自己再去查 AAAA
一个必须验证的前提
AAAA 过滤只对”把旁路由当 DNS“的终端生效。如果你的终端还在用主路由 RA 里下发的 IPv6 DNS(RDNSS),它会绕过旁路由直接问主路由要 AAAA,过滤等于没做。
验证方法很简单,在任意终端上:
nslookup ipv6.google.com
- 如果返回的是旁路由的地址(或者干脆没有 AAAA 记录)→ 正常
- 如果返回了 AAAA 地址,而那台 DNS 是主路由 → 说明 DNS 没被旁路由接管,需要回主路由的 DHCP 设置里把下发的 DNS 改成旁路由地址,或在固件允许的情况下关掉 RA 的 RDNSS
最后用 test-ipv6.com 验证结果:方案 A 下显示”未检测到 IPv6 地址”是正常的,不是配置失败。此时终端走 IPv4 出网、经旁路由分流,而旁路由自己有 IPv6,两边互不干扰。
方案 B:NAT6 强接管,让 IPv6 也走旁路由
如果你就是要终端跑真 IPv6(比如某些游戏、P2P、或者单纯不想让 IPv6 变成”残疾网络”),那就得让旁路由当 IPv6 网关,同时做 NAT6。
旁路由(ImmortalWRT)
1. LAN 口接管 IPv6 分配
网络 → 接口 → LAN → DHCP 服务器 → IPv6 设置:
- RA 服务:服务器模式
- DHCPv6 服务:禁用
- NDP 代理:混合模式
为什么禁用 DHCPv6?因为安卓设备原生不支持有状态 DHCPv6,只认 SLAAC;两边都开,安卓会拿到两套地址和两个网关,直接打架。
2. NAT6 规则
ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
eth0 换成你旁路由实际对外的网口名(网络 → 接口里能看到)。
两个前置条件别漏:
- 需要安装
kmod-ipt-nat6(opkg update && opkg install kmod-ipt-nat6) - 新版 ImmortalWRT 用的是 fw4 / nftables,
ip6tables -t nat可能不生效;这种固件要在 防火墙 → 区域 里给 wan 区域开 IPv6 伪装,或者写 nft 规则,别硬套老教程的 iptables 命令
3. 插件配置(以 OpenClash 为例)
- 高级设置里勾选 启用 IPv6 流量代理
- 内核运行模式改成 TUN 模式
方案 B 的代价
- 主路由的 RA 和旁路由的 RA 必须只留一个在发,否则终端会拿到两个默认网关,表现就是”时快时慢、随机断流”
- NAT6 会破坏端到端连通性,外网主动访问内网 IPv6 设备会变麻烦
- 部分固件的 NAT6 规则重启后不持久,要写进防火墙自定义规则
这就是为什么我更推荐 A:它把复杂度留给了 DNS,而不是路由。
隐藏的坑:硬件加速让防火墙规则”脱靶”
如果说前面是架构问题,那这一段就是纯粹的”玄学变科学”。
场景是这样的:Google TV 有有线和无线两张网卡,技术奇客ITGeeker.net在华硕主路由的 FORWARD 链里按 MAC 地址把两张网卡全 DROP 了,目的很简单——电视只能走 IPv4,老老实实经过旁路由的 OpenClash。结果呢?电视照样能连上 YouTube,画质卡死,代理完全没起作用。
原因不在规则写错,而在华硕的硬件加速。
Asuswrt 默认开启 Flow Acceleration(博通平台叫 Runner / Archer / Crossbow)。当一条连接的第一批包建立状态后,后续数据包由交换芯片直接转发,完全不经过 Linux 的 Netfilter。也就是说,等你的 FORWARD 规则生效时,电视的 IPv6 连接早就进了硬件流表,后面的包全都”合法”通过。
强制”无死角重解析”的四步
先把拦截规则插到链的最前面(用 -I 而不是 -A),再去清空流表和连接跟踪:
# 1. 插到最前面,双栈双链都拦
ip6tables -I FORWARD -m mac --mac-source b8:7x:d4:9c:35:26 -j DROP
ip6tables -I FORWARD -m mac --mac-source 1e:79:26:4d:44:31 -j DROP
ip6tables -I INPUT -m mac --mac-source b8:7x:d4:9c:35:26 -j DROP
ip6tables -I INPUT -m mac --mac-source 1e:79:26:4d:44:31 -j DROP
# 2. 清空硬件加速流表(新版固件用 fcctl,老版用 fc)
fcctl flush || fc flush
# 3. 清空连接跟踪,让旧连接全部重新走一遍慢路径
conntrack -F
两个细节:
fcctl flush是新固件的命令,老固件是fc flush。先用which fcctl fc看一眼,两个都试一次更稳。conntrack不一定预装,没有的话装 Entware 的conntrack-tools。
命令执行完,必须把电视断电 10 秒再上电(或者在电视上”忘记 Wi-Fi 再连”)。不重启的话,电视端缓存的连接还会继续命中旧流表,看起来像”规则没生效”。
重启后,电视的所有新建 IPv6 握手都会撞上 INPUT/FORWARD 的死规则,IPv6 通道直接瘫痪,系统自动降级到 IPv4,这时候才真正走上旁路由的代理。
持久化:这里有个坑,别照抄就信
这个方案最大的问题是重启就没了。网上流传的做法是把脚本塞进 script_usbmount 这个 NVRAM 变量,让系统在挂载 U 盘时执行:
nvram set script_usbmount="/tmp/mnt/ASUSRouter/block_tv_ipv6.sh"
nvram commit
但要注意:较新的华硕官方固件已经会丢弃这个变量(社区从 2023 年的 388 固件起就有报告,值会被 asd 清掉,或者干脆不执行)。RT-BE88U 属于 3006.102 这一代,风险更高。
先做这个自检,别急着相信:
nvram set script_usbmount="/bin/touch /tmp/yesitworks"
sleep 15
nvram get script_usbmount # 有输出 = 变量还在
ls -l /tmp/yesitworks # 文件存在 = 钩子真的被执行了
如果 nvram get 为空、或者文件没出现,说明你的固件不吃这一套。可以选:
- 刷 Asuswrt-Merlin,用官方的
/jffs/scripts/post-mount和services-start钩子,这是最干净的路子 - 用社区的
asusware-usb-mount-script变通方案,借 Download Master 的挂载入口拉起/jffs/scripts/usb-mount-script - 干脆用一台常开的小主机(旁路由本身)定时 SSH 到主路由重放规则——最土,但最不容易被固件更新搞坏
不管用哪种,改完一定真的重启一次路由器验证,而不是看 nvram get 有值就以为成了。
最后,一份检查清单
- 终端
test-ipv6.com有没有 IPv6 出口?有 → 分流大概率被绕过 - 终端在用的 DNS 是谁?不是旁路由 → AAAA 过滤等于没做
- 旁路由的 WAN6 拿到地址了吗?
ifstatus wan6或接口页看 - 主路由和旁路由是不是都在发 RA?是 → 只留一个
- 规则加了还是不生效?先怀疑硬件加速,清流表再试
- 重启后规则丢了?先验证
script_usbmount到底有没有被执行
IPv6 是好东西,但在”主路由 + 旁路由”这种非标准架构里,它默认站在旁路由的对立面。想清楚自己要的是”分流生效”还是”终端必须有 IPv6″,剩下的就是选 A 还是选 B 的问题了。













发表回复