旁路由的那些事

我有个坏毛病,要紧事不咋急,喜欢赶各种 ddl,空闲之余又喜欢折腾些杂七杂八的东西,也不干正事,去年在 v2 收了一个二手白色的斐讯 n1,到手就刷了个 F 大的 OpenWrt 镜像,随便调了下配置就凑合用了,一直到今年年初,结果不知道咋的突然寄了,正好那段时间 clash 全系迎来了有史以来最大的删库行动,软路由重装计划也暂时搁置了,刚好这段时间没啥事干也不想写毕设,于是就开始重装软路由的计划

对于软路由我的需求不是很多,日常我只是当个透明网关使用,用来实现去广告、流量监测、国内外分流以及 Tailscale 作为内网入口,而 n1 只有一个网口,正好用作旁路由的使用。旁路由这个词也是我在折腾 n1 的时候听到的,事实上很不学术,因为根本没有这种叫法,但在拓扑结构中旁路由确实又很形象,所以就干脆延续下去了。正因如此,F 大的镜像对我这种有电子洁癖的人来说过于完善了,很多功能用不上却也占着位置,而且由于 overflayfs 文件系统的原理,删除固件自带的软件包也无法增加空间,于是萌生了自己编译的想法

编译

本地编译

以前也进行过类似的本地编译,当时玩的是极路由 4,奈何内存过小 OpenClash 一直开不起来,这次选用的依然是 Lean’s LEDE,由于设备不同,打包则选用了 Flippy’s Packit,LEDE 比较接近 OpenWrt 官方的镜像,而 F 大的内核和打包源码对 n1 也很友好,软件源方面另外添加了 small-package,要用的 OpenClash 包在默认源当中不存在,只能三方引入

本地编译用的环境是 Archlinux,很幸运的是很久没开过结果更新竟然没有滚炸,就顺着以前搭建的编译环境继续编译了,详细过程就省略了,讲讲几个当时编译遇到的问题吧

首先就是网络问题,这也是最后逼着我云编译的原因,90% 的编译不通过都是由于网络问题,我挂的全局代理设置的环境变量,导致编译的时候有个工具死活下载不下来,没一点速度,后面关了代理才能正常下载,但是在编译过程中又不能停下来关代理,于是选择直接 curl 国内环境先下载扔进 dl 文件夹里了,这里还有一个坑,curl 下载和直接网页下载的文件 Hash 值不一样,这里猜测可能和浏览器 UA 有关

其次遇到的就是编译环境的问题了,忽略了重要的 gcc 版本,Arch 由于滚动更新所有的软件时刻保持最新,gcc13 版本发生了头文件和语法的改变,然后就报错寄了,于是下载了 gcc12 版本,并且进行了环境变量的设置来改变默认使用 CC 和 CXX 是 gcc13

1
export CC=gcc-12 CXX=g++-12

再者遇到的问题就是 xfsprogs 的编译错误了,后来发现是上游错误,而且有很多人提交了 pr,这里就不再赘述了

打包后的固件第一次能够正常进行更新,但之后更新一直显示 Mount p2 failed,手动去挂载点看也找不到相关的设备,后来细看文件大小才发现手动上传到晶晨宝盒的固件应该有损坏,挂载 u 盘移动文件正常更新,但当时我一直以为是打包的镜像有问题,甚至重装了几次编译环境,这也是一个间接让我转向云编译的原因

云编译

云编译白嫖的 github actions,仓库地址:N1-OpenWrt,整体流程借鉴了 P 大的 Actions-OpenWrt 以及 ophub 的 amlogic-s9xxx-openwrt 的 workflow 文件,添加了 LEDE 的 pr 中的使用 cache 的小段代码,以及修改了部分代码和自定义了一些其他参数

这里在两个自定义的 shell 文件中,分别添加了一行代码,用于添加 small-package 软件包和修正 xfsprogs 的编译错误:

diy-part1.sh:

1
sed -i '$a src-git smpackage https://github.com/kenzok8/small-package' feeds.conf.default

diy-part2.sh:

1
sed -i 's/TARGET_CFLAGS += -DHAVE_MAP_SYNC/TARGET_CFLAGS += -DHAVE_MAP_SYNC -D_LARGEFILE64_SOURCE/' feeds/packages/utils/xfsprogs/Makefile

用途

DNS 分流

具体的镜像安装流程就不赘述了,这里讲讲我旁路由的主要用途,由于家里和寝室里多人用网,不能直接在主路由动工,这也是为啥折腾旁路由的原因,核心原理参照恩山老哥的这篇文章,通过配置 Adguard Home + MosDNS + OpenClash 实现 DNS 分流的操作

image-20240207190937428

可以通过 logread 命令查看 OpenWrt 的日志,在报错的情况下用于查明原因

GEO 数据库订阅方面,MosDNS 需要使用 OpenClash 下载的 Loyalsoldier 的版本,OpenClash 下载数据库的默认位置在 /etc/openclash 下,分别名为 GeoIP.datGeoSite.dat,MosDNS 则是在每次启动的时候优先加载 /usr/share/v2ray 文件夹下的 geoip.datgeosite.dat ,所以需要在 root 下添加一个定时脚本来进行二者的同步,geoUpdate.sh:

1
2
3
cp /etc/openclash/GeoIP.dat /usr/share/v2ray/geoip.dat
cp /etc/openclash/GeoSite.dat /usr/share/v2ray/geosite.dat
/etc/init.d/mosdns restart

修改运行权限:

1
chmod 777 /root/geoUpdate.sh

设置定时脚本:

1
2
3
crontab -e

0 6 * * 1 /root/geoUpdate.sh

默认是周一零点自动更新 Geo 数据库,所以这里设置的是周一六点自动执行更新

Tailscale

用 Tailscale 来进行远程内网访问,同时设置 Subnet,用一个路由入口来访问内网的其他设备:

1
tailscale up --advertise-routes 192.168.31.0/24

使用自建的 Derp 服务器作为中转,拒绝官方服务器的高延迟以及保护个人的隐私,两端打通之后可获得无感的内网体验,能够随时随地访问家中的设备

这么一套折腾下来还是存在一个麻烦的问题:要科学的设备需要手动修改网关和 DNS 服务器,在这方面来说其实是个半合格的旁路由,一直以来都看了很多大佬的方案,在其中也学习到了很多网络相关的知识,但毕竟每个人所处的环境不尽相同,因地制宜,最适合自己的才是最优的方案,对我来说,n1 小巧便携,性能对于我日常使用需求来说完全够用了,当然,以后如果有条件的话还是会选择其他方案来体验新鲜的东西,一个人活在世上总归得有点爱好,毕竟为了这盘醋包的这顿饺子的事我也没少干(