我在家里的一台旧笔记本上部署了透明代理服务,让连上家里网络的设备都能赛博漫游到国外,不过最近,在我的透明代理网络下,米家设备全部没法联网。我的透明代理工作机制如下:
OpenWRT 强制启用 DHCP,给米家设备设置特定的 IP 地址,并把米家设备的网关设置为主路由;其他设备的网关设置为 OpenWRT。
OpenWRT 会把所有需要转发(FORWARD,即目标地址非 OpenWRT 本身)的请求发送给透明代理端口(localhost:12345),接着运行在 OpenWRT 上的 v2ray 会对来自 12345 端口的请求分流,国内请求直接发送,国外请求通过代理协议发送到服务端。
经过一番排查后,我发现在最近的一次主路由固件升级过后,OpenWRT 强制启动 DHCP 失效了,米家设备的网关被主路由设置成了 OpenWRT 。米家设备需要请求 https://:Mijia Cloud
。而 Mijia Cloud
的 IP 地址是米家设备通过其他接口获取的,无法通过正常的 DNS 解析。这时,就引发了 v2ray 的一个问题:v2ray 在分流时会嗅探请求的域名以及域名解析后的 IP 地址,帮助判断请求是否需要被代理。因为 Mijia Cloud
无法被解析,导致嗅探功能出错,v2ray 无法进一步处理请求,导致请求被丢弃。
知道了问题的成因,解决方法就很简单,通过 OpenWRT 上的 iptables 分流,让来自米家设备的请求绕过代理:
iptables -t mangle -A V2RAY -s 192.168.68.<mijia device ip> -j RETURN
但是这样做,米家设备还是无法联网,通过 tcpdump 发现米家设备只能发送请求,无法接收响应。
又是一番搜索,怀疑是一些路由器会校验请求来源设备 IP 跟数据包中来源 IP 的一致性,米家设备请求被 OpenWRT 转发到主路由网关,导致来源设备 IP 跟数据包中的来源 IP 不一致,最终请求被拦截在了主路由处。要解决这个问题,得在 OpenWRT 对应的网络接口上启用「动态 IP 伪装」,说白了就是 NAT 。
其他设备也是被 OpenWRT 转发到主路由的,为什么它们没有出现这种问题呢?这时就需要进一步了解 Linux 的网络原理了:
所有发往网关的请求应该都需要转发(FORWARD,因为请求的目标 IP 不是网关本身),但是所有基于这篇透明代理白话文设置的透明代理中,转发流量都被 iptables 发到了 12345 端口,变成了入站请求(INPUT),经过代理软件处理后,作为出站请求(OUTPUT)发出,这些流量就不再被认为是转发流量了,在主路由看来,这些被 v2ray 处理过的流量来源请求都是 OpenWRT ,所以不会触发来源请求校验失败。而被 iptables 分流的米家设备请求,从主路由看来,都是由 OpenWRT 发出但是来自米家设备 IP 的,导致校验失败。
上面的根因分析完全是我半吊子的推测,可能不够准确、专业,但是启用 OpenWRT 的「动态 IP 伪装」之后,确实解决了米家设备无法联网的问题。
参考链接
- Netfilter. (2023, January 7). In Wikipedia. https://en.wikipedia.org/wiki/Netfilter
- Team, D. (2016). 关于防火墙设置。里面有个MSS钳制和IP动态伪装是什么意思-OPENWRT专版-恩山无线论坛 – Powered by Discuz! Right.com.cn; 恩山无线论坛. https://www.right.com.cn/forum/thread-180794-1-1.html
- 透明代理(TPROXY) | 新 V2Ray 白话文指南. (2014). V2fly.org. https://guide.v2fly.org/app/tproxy.html
- v2fly. (2022, December 10). [app/dispatcher] [proxy/dns] Support domain string validation by Vigilans · Pull Request #2188 · v2fly/v2ray-core. GitHub. https://github.com/v2fly/v2ray-core/pull/2188
发表回复