前言
很久没写博客了,最近正好有空可以谈谈我最近更新的家庭网络架构。我所有的网络组件都部署在一台 J1900 的机器上,安装的操作系统是 debian 10,主板配有四个网口。我将其中三个网口合并为一个 bridge 用来构建我的私有子网,供主机和路由器插线连接,另一个网口连接光猫作为出口。
科学上网
通过在软路由上使用 iptables + tproxy 重定向 TCP/UDP 流量到 clash,可以实现全局翻墙,所有设备无需设置。在讨论我遇到的问题之前,有必要了解一下 clash 在软路由上怎么进行规则判断的,换言之 clash 怎么知道我们当前的连接是否需要走代理。
DNS
软路由上的流量被重定向后,clash 只能获取的目标 ip,但是根据 ip 地区判断是远远不够的,那么该如何获取 ip 对应的域名呢?clash 自带了一个 DNS server,在软路由上将所有 DNS 请求转发给它,那么它就能记录域名和 ip 的对应关系。但是由于存在许多问题,这种 redir-host 模式在较新的 clash 中被删除了。它最大的问题就是无法应对 DNS 污染,例如最上游 DNS 被污染时,返回 google 的 ip 是 127.0.0.1 这种,那么该请求直接在主机上请求失败了。
FakeIP
在使用 redir-host 的过程中,我经常遇到网络不正常的情况,迫于无奈只能切换到 fake-ip 模式。它的原理就是 clash 的 DNS server 返回一个虚假的内网 ip,例如 198.168.0.0/16,同时记录 ip 与 hostname 的对应关系,这样就可以避免 DNS 污染的问题。当然 fake-ip 也有缺陷,例如 QQ 的某些域名指向就是 127.0.0.1,因为需要和 QQ 客户端通信,另外 Windows 的网络探测服务也无法在 fake-ip 模式下工作。对于这些特殊的域名,我们可以在 clash 配置中过滤掉,让它们返回真实的查询结果。
| 1 | dns: | 
游戏加速
游戏加速说到底还是代理,只不过是延迟很低的线路,使用小米等路由器同时开启翻墙和游戏加速插件肯定会有冲突,但是在自己配置的 Linux 路由器里,我可以精准地控制每一条规则。
docker
一年前我的方案是将 openwrt 版本的 UU加速器 跑在 docker 里,它其实是一个为主机加速提供的方案,所以我写了个 python 脚本将我的软路由伪装成 PS4:
| 1 | #!/usr/bin/env python3 | 
想象一下,UU加速器 在容器 172.17.0.3 中广播 UDP 包,然后这个脚本在软路由的 172.17.0.1 上收到了这个包,并成功回复让对方认为自己是一台 PS4。然后在手机 APP 上就可以开启加速,这个时候我们只需要在软路由上将需要加速的包路由给 172.17.0.3 即可,流量会顺利地从容器的 tun 网卡进入 UU加速器 的专线。
| 1 | # https://github.com/Hackerl/docker-uuplugin | 
启动后添加路由规则:
| 1 | ip rule add fwmark 0x163 table 0x163 | 
这个路由规则的意思是如果流量带有 0x163 标志,那么就路由给 172.17.0.3,接着我们可以在 iptables 里给特定流量打上标志:
| 1 | iptables -t mangle -N UUPLUGIN | 
例如我们给 UDP 高端口号的包打上标志,这其实是大多数网络游戏的通讯方式,例如英雄联盟。
虚拟机
使用 docker 运行 UU加速器 进行游戏加速也存在问题,一就是可选择的节点并不多,毕竟这是主机加速方案,二就是它的 iptables 限制了只代理某些源 ip。由于第二个限制,我们没有办法直接在它的容器中部署 socks5 代理,以集成到 clash 规则中,当然我可以修改它的规则,但是每次启动加速都要修改的话太麻烦了。此时我有了一个大胆的想法,我可不可以在软路由上跑一个 windows 虚拟机,然后将流量转发到虚拟机中去加速,一想到 J1900 廉价的性能我心里就充满了问号。
我首先安装了一个 windows 7 虚拟机,连上 VNC 后果然很卡,然后部署了一个简单的 socks5 代理,接着将英雄联盟台服的域名全部抠出来,写好 clash 规则:
| 1 | script: | 
尝试了一下确实可以工作,所有英雄联盟相关的流量都由虚拟机代理。那么接下来要做的就是怎么把这台虚拟机压缩一下,J1900 的确有点带不动,而且为了一个游戏加速我也并不是很乐意耗费这么多 CPU 和内存。我在网上找到了一个 Windows 7 Super-Nano Lite,镜像居然只有 316MB,确定这可以跑起来吗?我安装了一下确实跑起来了,但是包括网络驱动之类的东西全部被删除了。

磁盘占用只有 600MB,内存也只用了 200MB,为了进一步优化性能,我使用 virt-install 安装虚拟机时设置的网络和磁盘驱动都是 virtio:
| 1 | wget https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.173-4/virtio-win-0.1.173_x86.vfd | 
在使用 VNC 安装的时候会提示找不到驱动器,因为 windows 7 无法识别 virtio 设备,所有在界面上点击加载驱动,加载 virtio-win-0.1.173_x86.vfd 软盘中的磁盘和网络驱动。安装后的系统是无法显示中文的,因为中文包也被删除了。找一台完整的 windows 7 机器,拷贝 C:\Windows\System32\C_936.NLS 以及 C:\Windows\Fonts\msyh.ttf 到虚拟机中,中文就不会乱码了。安装完加速器后,需要部署一个支持 TCP/UDP 的 socks5 代理,我找了一圈发现没几个支持 UDP 的,最后选择了 3proxy,配置文件如下:
| 1 | #!/usr/local/bin/3proxy | 

搞完这个之后在英雄联盟台服开了把大乱斗,延迟居然才 30 比国服还低,看了下软路由的资源占用,虚拟机低负载时 qemu 进程稳定占用 45% 左右的单核 CPU,算是可以接受的范围,毕竟它只是 J1900 啊!有了这个比较稳定的虚拟方案后,其实可以将一些 windows 独占的软件放到里面,通过软路由上的 smb 共享文件,但是我现在使用的百度云、迅雷都是使用的 docker + noVNC 方案,暂时没有其余想折腾的东西了。