问题结论: OpenClash 旁路由原本运行正常,更换光猫后突然出现国内网站无法访问的问题。OpenClash 规则显示流量正确命中
DIRECT,但客户端无法建立正常连接;切换代理节点后却能正常访问。最终开启 旁路网关兼容模式(Bypass Gateway Compatible),问题得到解决。结合 OpenClash 源码分析,这次故障很可能与单臂旁路由的 NAT 和回程路由有关。
最近家里的网络更换了一台光猫。更换之前,OpenClash 一直运行正常,国内网站直连、国外网站通过代理节点访问,都没有明显问题。
换完光猫之后,出现了一个比较奇怪的现象:
- OpenClash 旁路由本机可以正常访问百度等国内网站。
- 局域网客户端通过 OpenClash 访问国内网站时,连接失败。
- 查看 OpenClash 日志,发现这些请求已经正确匹配
DIRECT。 - 手动将相同的网站切换为代理节点后,反而可以正常访问。
- 代理节点本身连接正常,国外网站也可以通过代理访问。
也就是说,OpenClash 并不是无法工作,而是 DIRECT 直连流量出了问题。
开始时怀疑是 DNS 解析、Fake-IP 或分流规则异常,但经过排查,最终发现了更值得关注的旁路由 NAT 问题。
当前网络结构如下:
互联网
│
▼
光猫(路由模式,负责 PPPoE 拨号)
│
│ DHCP
▼
主路由
192.168.1.1
│
├───────────────────────┐
│ │
▼ ▼
OpenWrt 旁路由 局域网客户端
192.168.1.111 192.168.1.x
运行 OpenClash │
▲ │
└──────────────────────────┘
客户端网关和 DNS
均指向 192.168.1.111
网络配置:
| 项目 | 配置 |
|---|---|
| 光猫 | 路由模式,PPPoE 拨号 |
| 主路由 | WAN 通过 DHCP 获取地址 |
| 主路由 LAN IP | 192.168.1.1 |
| OpenWrt 旁路由 IP | 192.168.1.111 |
| OpenClash 模式 | Fake-IP |
| OpenClash 分流模式 | Rule |
| 客户端默认网关 | 192.168.1.111 |
| 客户端 DNS | 192.168.1.111 |
这是一种常见的单臂旁路由部署方式。
客户端通过旁路由访问互联网,旁路由再将需要直接转发的数据包交给主路由,由主路由负责连接上游网络。
首先 SSH 登录 OpenWrt,检查路由表:
ip -4 route
实际输出:
default via 192.168.1.1 dev br-lan proto static
192.168.1.0/24 dev br-lan proto kernel scope link src 192.168.1.111
可以看到:
- 默认路由指向主路由
192.168.1.1。 - 旁路由使用
br-lan接口访问主路由。 - 局域网网段为
192.168.1.0/24。
默认路由没有发现明显异常。
继续测试国内网站:
curl -4 -I --connect-timeout 5 https://www.baidu.com
实际返回:
HTTP/1.1 200 OK
Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
Content-Length: 0
Content-Type: text/html
Server: bfe
这说明旁路由本机能够成功建立到百度的 HTTPS 连接。
但是,这里有一个非常容易被忽略的地方:
路由器自己能上网,不代表经过路由器转发的客户端流量也一定能正常访问。
因为路由器本机发起的连接,与 LAN 客户端转发的连接,经过的防火墙和 NAT 处理路径可能不同。
既然旁路由本身正常,下一步检查 Linux 内核是否允许转发流量。
执行:
sysctl net.ipv4.ip_forward
sysctl net.ipv4.conf.all.rp_filter
实际输出:
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 0
说明:
- IPv4 转发功能已经开启。
- 全局反向路径过滤没有启用。
同时查看策略路由:
ip -4 rule
实际输出:
0: from all lookup local
32765: from all fwmark 0x162 lookup 354
32766: from all lookup main
32767: from all lookup default
这里可以看到一个基于 fwmark 0x162 的策略路由规则。
类似规则通常用于代理流量的特殊路由处理。仅凭这一项还不能判断存在异常,需要结合具体路由表和 OpenClash 运行模式分析。
到这一步为止,并没有发现 IP 转发被禁用或者默认路由配置错误的问题。
执行:
nft list ruleset | grep -i -C 3 masquerade
在尚未开启旁路网关兼容模式时,实际只看到类似:
chain srcnat_wan {
meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 wan traffic"
}
这里开始出现了一个值得关注的线索。
正常情况下,OpenWrt 的 WAN 防火墙区域会执行 Masquerade,也就是源地址转换。
但当前旁路由的默认出口是:
dev br-lan
而不是常规的 WAN 接口。
所以,虽然存在 srcnat_wan 规则,但它不一定会处理经由 br-lan 转发的客户端流量。
需要强调的是,这个输出只是根据 masquerade 关键字过滤得到的结果,不是完整防火墙规则,也不能单凭这一项就断定 NAT 缺失。
不过结合 DIRECT 失败、代理正常的现象,旁路由 NAT 和回程路径已经成为值得优先调查的方向。
继续查看 OpenClash 的关键参数:
uci show openclash | grep -iE \
'bypass_gateway|en_mode|proxy_mode|dns'
其中几个关键结果如下:
openclash.config.en_mode='fake-ip'
openclash.config.proxy_mode='rule'
openclash.config.enable_redirect_dns='1'
openclash.config.bypass_gateway_compatible='0'
前面几个配置没有明显问题。
但最后这一项值得注意:
bypass_gateway_compatible='0'
它代表 OpenClash 的 旁路网关兼容模式,当前处于关闭状态。
OpenClash 对这个选项的提示是:
If The Network Cannot be Connected in Bypass Gateway Mode, Please Try to Enable.
意思是:
如果在旁路网关模式下无法正常联网,可以尝试开启这个选项。
由于当前恰好使用单臂旁路由,而且出现了 DIRECT 直连异常,因此决定先测试这个设置。
OpenClash 的部分版本可以在 LuCI 页面中的插件设置里找到「旁路网关兼容模式」。
如果找不到,可以直接通过 SSH 修改。
cp /etc/config/openclash \
/etc/config/openclash.bak
uci set openclash.config.bypass_gateway_compatible='1'
uci commit openclash
/etc/init.d/openclash restart
uci get openclash.config.bypass_gateway_compatible
预期返回:
1
完成上述操作后,再从局域网客户端访问之前无法连接的国内网站。
实际测试结果:开启旁路网关兼容模式后,原先无法正常访问的 DIRECT 网站恢复了访问。
这次问题在没有更换代理节点、没有改动分流规则的情况下得到解决。
如果开启之后没有效果,可以恢复:
uci set openclash.config.bypass_gateway_compatible='0'
uci commit openclash
/etc/init.d/openclash restart
为了弄清楚这个开关到底做了什么,进一步查看了 OpenClash 官方源码。
在其防火墙处理逻辑中,当 bypass_gateway_compatible=1 时,会创建额外的 NAT 规则链。
核心逻辑如下(节选):
if [ "$bypass_gateway_compatible" -eq 1 ]; then
nft 'add chain inet fw4 openclash_post'
nft 'flush chain inet fw4 openclash_post'
nft 'add rule inet fw4 openclash_post skgid == 65534 counter return'
nft add rule inet fw4 openclash_post mark "$PROXY_FWMARK" counter accept
nft 'add rule inet fw4 openclash_post ip daddr @localnetwork counter return'
nft 'add rule inet fw4 openclash_post ct direction reply counter return'
nft 'add rule inet fw4 openclash_post fib saddr type != { local } counter masquerade'
nft add rule inet fw4 srcnat meta nfproto {ipv4} \
counter jump openclash_post \
comment \"OpenClash Bypass Gateway Compatible\"
fi
源码地址:
https://github.com/vernesong/OpenClash/blob/master/luci-app-openclash/root/etc/init.d/openclash
这段逻辑最关键的是:
fib saddr type != { local } counter masquerade
它会对符合条件的流量进行 Masquerade(源地址伪装)。
同时,规则会跳过本地网络目标、回复方向的连接以及部分具有特定标记的流量,因此并非对所有经过路由器的数据包无条件执行 NAT。
假设客户端地址为:
192.168.1.100
客户端访问国内网站,连接进入旁路由。
对于被 Linux 内核直接转发、且没有执行 SNAT 的数据包,流量可能是:
客户端:192.168.1.100
│
▼
旁路由:192.168.1.111
│
│ 源 IP 仍然是 192.168.1.100
▼
主路由:192.168.1.1
│
▼
目标网站
当网站返回数据时,主路由已经知道 192.168.1.100 位于自身 LAN 网络中。
于是,主路由可能直接把响应发送给客户端,而不是重新交给旁路由。
这种请求与响应经过不同路径的情况,称为非对称路由(Asymmetric Routing)。
如果连接需要经过旁路由的连接跟踪或其他状态处理,回程绕过旁路由就可能导致连接异常。
当流量命中 Masquerade 规则时,旁路由会执行 SNAT。
例如:
客户端:192.168.1.100
│
▼
旁路由:192.168.1.111
│
│ SNAT
│ 源 IP 改为 192.168.1.111
▼
主路由:192.168.1.1
│
▼
目标网站
回程时,主路由看到的连接来源是旁路由,因此返回数据也会发送到旁路由。
旁路由再利用连接跟踪中的 NAT 状态,将返回流量正确交给原始客户端。
这样就可以避免部分连接出现非对称回程问题。
需要注意:这只是对本次现象最吻合的技术解释。由于故障发生时没有抓取完整网络数据包,还不能百分之百确认每一条失败连接都是由非对称路由导致的。
另外,由 Clash 内核自行建立的 DIRECT 连接,和内核直接转发的客户端连接,并不是同一条处理路径。
很多人容易把 DIRECT 理解为完全绕过 OpenClash。
实际上并不是。
在 Clash 规则中:
- GEOIP,CN,DIRECT
- MATCH,PROXY
DIRECT 表示匹配规则后,Clash 使用直连方式访问目标。
但这不代表所有数据包都必然完全绕过 OpenClash 的 DNS、透明代理、内核路由或防火墙处理。
尤其在 Fake-IP 模式下,客户端可能先收到 198.18.0.0/16 范围内的虚拟 IP,再由 OpenClash 接管连接并识别真实目标。
不同协议、不同规则和不同透明代理处理路径,可能产生不同的转发行为。
因此:
- 代理节点连接正常,只能说明代理出口可以使用。
- 旁路由本机可以访问国内网站,只能说明本机联网基本正常。
- DIRECT 失败,还需要进一步检查 Clash 直连出口、DNS、策略路由和防火墙转发。
不能简单地把 DIRECT 连接失败归结为分流规则错误。
这个问题同样值得讨论。
实际情况是:
原来的光猫配合 OpenClash 使用一直正常,更换光猫之后才出现 DIRECT 访问异常。
目前确认新光猫采用路由模式,负责 PPPoE 拨号,主路由通过 DHCP 获取 WAN 地址。
至于旧光猫采用桥接还是路由模式,没有保留相关信息。
因此,不能确定更换光猫前后的完整网络结构是否相同。
可能的变化包括:
- 主路由的 WAN 连接方式发生变化,例如从 PPPoE 改成 DHCP。
- 新光猫增加了一层 NAT。
- 主路由重启后,流量卸载、防火墙或连接跟踪状态发生变化。
- 更换设备时,LAN、DNS 或 IPv6 网络配置发生变化。
- 原本就存在的旁路由回程路径问题,在新的网络环境下暴露出来。
需要特别说明:上游增加一层 NAT,并不会必然导致 OpenClash DIRECT 失败。
单臂旁路由中的同网段回程问题,主要发生在客户端、旁路由和主路由之间。新光猫通常不直接参与这一段 LAN 内部转发。
所以这次故障只能确认与更换光猫在时间上有关,还不能确定光猫本身就是直接原因。
但从修复结果来看,启用兼容模式后增加的 NAT 处理,确实能够解决目前的连接异常。
这是一个比较实际的问题。
开启 bypass_gateway_compatible=1 后,OpenClash 会为符合条件的流量执行额外的 NAT 处理。
这可能带来:
| 项目 | 影响 |
|---|---|
| CPU 占用 | 额外的防火墙与 NAT 处理开销 |
| 内存占用 | 可能增加连接跟踪状态开销 |
| 网络延迟 | 普通家庭网络通常不明显 |
| 下载速度 | 多数情况下影响较小 |
| 最大转发吞吐量 | 弱性能路由器或高速宽带环境下可能受影响 |
| 连接日志 | 部分上游设备可能只看到旁路由的 IP |
| 流量卸载 | 可能受设备和防火墙实现影响 |
需要强调的是,额外 NAT 并不等于额外代理,也不会自动增加一层数据加密。
对普通家用 x86 软路由来说,通常不会有明显性能损失。
但如果使用低功耗 ARM、MIPS 设备,或者宽带达到千兆、2.5G 甚至更高速度,建议通过实际测速确认开启前后的吞吐量差异。
此外,兼容模式改变了部分转发流量的源地址,因此可能影响依赖原始客户端 IP 的上游访问控制、设备识别和统计。
如果原有网络本身没有问题,就没有必要为了所谓的兼容性而主动开启这个选项。
但对于本次这种已经确认能解决故障的场景,保持开启通常是合理选择。
开启兼容模式后,在 OpenWrt SSH 中执行:
nft -a list chain inet fw4 openclash_post
正常情况下,应能看到类似规则:
ip daddr @localnetwork counter return
ct direction reply counter return
fib saddr type != { local } counter masquerade
观察 masquerade 对应的计数器。
然后从客户端访问一个实际命中 DIRECT 的国内网站,再次执行命令。
如果相关规则的匹配计数增加,说明确实有流量命中了该 NAT 处理。
需要注意,NAT 链主要处理连接的初始数据包,因此计数变化不代表所有下载数据包都会逐个经过规则匹配。
如果还需要进一步确认,可以配合 tcpdump 和 conntrack 查看源地址转换及回程路径。
如果你遇到相同故障,可以先在 OpenWrt 中执行以下命令:
# 检查 IP 地址
ip -4 addr
# 检查路由表
ip -4 route
# 检查策略路由
ip -4 rule
# 检查 IPv4 转发
sysctl net.ipv4.ip_forward
# 检查反向路径过滤
sysctl net.ipv4.conf.all.rp_filter
# 检查 NAT 规则
nft list ruleset | grep -i -C 3 masquerade
# 检查 OpenClash 配置
uci show openclash | grep -iE \
'bypass_gateway|en_mode|proxy_mode|dns'
# 测试本机是否可以访问国内网站
curl -4 -I --connect-timeout 5 \
https://www.baidu.com
如果确定是在旁路由架构下,OpenClash 的代理连接正常、DIRECT 连接异常,并且基础路由没有明显问题,可以备份配置后尝试:
uci set openclash.config.bypass_gateway_compatible='1'
uci commit openclash
/etc/init.d/openclash restart
随后观察客户端是否恢复正常。
不要一开始就清空防火墙、重置 OpenClash、修改整套 DNS 或重新安装系统。
对于这类问题,先确定具体是哪一条流量路径异常,比盲目重装更有效。
这次故障的解决过程其实并不复杂。
最初以为是 OpenClash 的 DNS、Fake-IP 或 DIRECT 规则出了问题,但随着排查进行,发现:
- OpenWrt 旁路由本机正常联网。
- IPv4 转发和默认路由没有明显问题。
- 客户端通过 OpenClash 访问代理节点正常。
- 只有命中 DIRECT 的部分连接异常。
- OpenClash 的旁路网关兼容模式处于关闭状态。
- 开启
bypass_gateway_compatible=1后,问题得到解决。
结合 OpenClash 的官方源码,这个兼容模式通过增加 SNAT / Masquerade 规则,可以修复部分单臂旁路由的转发与回程问题。
如果你的 OpenClash 是旁路由部署,出现“代理正常、DIRECT 无法访问”的问题,建议把「旁路网关兼容模式」列为优先检查项。
但它不是万能修复选项。如果启用后依然不能访问,仍需要检查 DNS、Fake-IP、策略路由、主路由防火墙和实际回程路径。
- OpenClash GitHub:https://github.com/vernesong/OpenClash
- OpenClash 初始化与防火墙规则源码:https://github.com/vernesong/OpenClash/blob/master/luci-app-openclash/root/etc/init.d/openclash
- OpenClash 默认配置说明:https://github.com/vernesong/OpenClash/blob/master/luci-app-openclash/root/etc/openclash/overwrite/default
本文基于一次真实的 OpenWrt + OpenClash 单臂旁路由故障排查过程整理。命令输出和最终恢复结果来自实际测试,关于非对称路由的解释为结合源码与故障表现作出的技术分析,尚未通过故障时的完整抓包验证。
