我的路由器浪漫 小标题致敬我的化学浪漫乐队(逃)
大学时期我就听闻了所谓的路由器改造,就是用开源的 OpenWrt 系统刷写原本的路由器,让它拥有更多有趣的功能。但那时候我并没有太深入了解,同时也不知道有一群玩软路由的爱好者群体。那时候的室友在某鱼上买了一个已经刷好的路由器,听说自带代理功能,还挺羡慕。但是,由于代理在每个客户端上都可以实现,没必要专门用一个路由器去做,所以我当时自觉对这方面的需求不大。
就这样,我与路由器的定制化错过了将近5年时间。这5年里我一直没注意正在使用的路由器,也从未去看过软路由相关的文章和论坛。然而,就在今年,我又重新关注起了这个小盒子。原因有很多,一是大半年来一直在捣鼓东西,从
Emacs 到 Arch Linux 再到 PowerShell … 真的是生命不息,折腾不止了。第二个原因是我对路由器层面代理的需求也日渐旺盛,特别是在技术领域。很多开源软件、脚本都不会自动识别出系统代理,走的还是原本的请求方式,导致编译程序或更新程序的时候会遇到各种各样的 Bug 。最简单的例子就是 GHCup
安装 Haskell 开发环境的时候,我甚至写了专门的文章来讲 这个事情 。这种问题一次两次还好,都能通过配置环境变量或设置镜像源来碰碰运气,但遇到太多次难免不让人抓狂。
本着 折腾至上 的想法,我立马从某鱼上下单了一个二手小米 R3G 路由器。下单之前我已在论坛上确认过这个路由器用比较轻松的方式破解,刷写的过程也比较简单。刚开始的时候,我直接从 OpenWrt 官网下载编译好的 OpenWrt
二进制内核文件,按照网上的教程刷到路由器里面(这样的教程太多了)。在代理上,我也直接下载了现成的 OpenClash 插件,安装到路由器的 OpenWrt
系统。系统稳定运行,就这样安稳地过了1个多月。
但是后来我发现了糟心的地方。OpenClash 对于我这多年前的小路由器来说太重了,经常内存占用达到90%以上。OpenClash 失效的次数也多,期间我还要重启路由器,十分麻烦。
经过一翻搜寻,终于发现了更轻量化的 SSR Plus 。然而,任凭我怎么找也找不到现成的为小米 R3G 编译的 SSR Plus 插件。有一些仓库里有定时的编译任务,但基本都不是最新的。我算半个追新派,想让用的软件都保持在最新状态(商业软件除外)。一翻思想斗争之后,我决定直接从零开始编译一个路由器系统。
源码选用了 OpenWrt 一个比较出名的 Fork : LEDE 。编译环境选用了
Arch Linux 。作者推荐使用 Ubuntu 或 Debian ,但毕竟我算是 Arch 爱好者,想试试在喜欢的系统上编译一下。
讲了这么多废话,下面终于可以进入正题了。
一次就过的编译指南 如果你正在阅读这篇指南,请注意下面几点:
这篇指南只是一个编译 LEDE 内核的教程,不涉及破解路由器、刷 Breed
以及所有编译以外的教程 本次是为了编译出小米 R3G (MIPS)上可用的 LEDE 镜像,过程中踩的坑可能是这个架构上特有的,如果你是其他架构,请有选择地参考本篇指南 编译时 LEDE 仓库的最新提交是 6e84aeb589e322813e353d7f13c3c0e873664cec
,指南也只能对这个提交负责 下面就进入编译之旅吧!
1. 准备环境 更新 Arch Linux 到最新状态:
1
2
sudo pacman -Syu
sudo yay -Syu
下载 AUR 中好心人准备好的 Openwrt 编译工具集:
2. 准备源码 打开 LEDE仓库 浏览一边上面的编译安装步骤。
拉取源码:
1
2
git clone https://github.com/coolsnowwolf/lede
cd lede
打开代理插件源的仓库 helloworld ,浏览一遍上面的配置方法。
添加代理插件源 helloworld :
1
2
sed -i "/helloworld/d" "feeds.conf.default"
echo "src-git helloworld https://github.com/fw876/helloworld.git" >> "feeds.conf.default"
下载编译所需的所有脚本:
1
2
./scripts/feeds update -a
./scripts/feeds install -a
进行配置:
配置如下(LEDE默认选的组件不去动它,这是额外添加的组件):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Target System >> MediaTek Ralink MIPS
Subtarget >> MT7621 based boards
Target Profile >> Xiaomi Mi Router 3G
Extra packages >> ipv6helper
Firewall >> ipv6tables >> ip6tables-extra 和 ip6table-mod-nat
Base system >> firewall4 (取消 firewall 或设置为 M)
Kernel modules >> Network Support >> kmod-wireguard
LuCI >> Collections >> luci-ssl-openssl
LuCI >> Themes >> luci-theme-argon
LuCI >> Applications >> luci-app-passwall2 (进下面的 Configuration 选中全部)
LuCI >> Applications >> luci-app-ssr-plus
Shadowsocks Client Selection -> Shadowsocks-rust
Shadowsocks Server Selection -> Shadowsocks-rust
V2ray-core Selection -> Xray-core
然后选中下面 ssr-plus 包的所有可选项(Include... )
LuCI >> Applications >> luci-app-smartdns
LuCI >> Applications >> luci-app-mosdns
LuCI >> Applications >> luci-app-uhttpd
LuCI >> Protocls >> luci-proto-wireguard
LuCI >> Protocls >> luci-proto-openconnect
你可以在 附件下载 中下载我的 .config 配置文件。
至此按道理已经可以开始编译,但为了避免可能的问题,下面要对源码进行部分修改。
3. 修改源码 修复 NaiveProxy 编译失败问题 具体报错为:naiveproxy clang++: error: clang frontend command
failed with exit code 70 。
这里的解决办法是直接用官方为 MIPS 编译好的二进制包。具体操作过程如下:
1
2
3
4
5
# 在 lede 源代码根目录
# 备份 Makefile 文件
cp ./feeds/helloworld/naiveproxy/Makefile ./feeds/helloworld/naiveproxy/Makefile.bak
# 修改 Makefile
vim ./feeds/helloworld/naiveproxy/Makefile
直接将整个内容替换成(来源于 Bard大佬 ):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# SPDX-License-Identifier: GPL-3.0-only
#
# Copyright (C) 2021 ImmortalWrt.org
include $( TOPDIR ) /rules.mk
PKG_NAME := naiveproxy
PKG_VERSION := 131.0.6778.86-1
PKG_RELEASE := 1
PKG_SOURCE := naiveproxy-v$( PKG_VERSION) -openwrt-$( ARCH_PACKAGES) .tar.xz
PKG_SOURCE_URL := https://github.com/klzgrad/naiveproxy/releases/download/v$( PKG_VERSION) /
PKG_HASH := skip
PKG_LICENSE := BSD 3-Clause
PKG_LICENSE_FILES := LICENSE
PKG_MAINTAINER := Tianling Shen <[email protected] >
PKG_BUILD_DIR := $( BUILD_DIR) /naiveproxy-v$( PKG_VERSION) -openwrt-$( ARCH_PACKAGES)
include $( INCLUDE_DIR ) /package.mk
define Package/naiveproxy
SECTION := net
CATEGORY:= Network
SUBMENU:= Web Servers/Proxies
TITLE:= Make a fortune quietly
URL:= https://github.com/klzgrad/naiveproxy
DEPENDS:= @!( arc|| armeb|| mips|| mips64|| powerpc|| TARGET_gemini) +libatomic
endef
define Package/naiveproxy/description
NaïveProxy uses Chrome 's network stack to camouflage traffic with strong
censorship resistance and low detectability. Reusing Chrome' s stack also
ensures best practices in performance and security.
endef
define Build/Compile
endef
define Package/naiveproxy/install
$( INSTALL_DIR ) $( 1) /usr/bin
$( INSTALL_BIN ) $( PKG_BUILD_DIR ) /naive $( 1) /usr/bin/naive
endef
$( eval $( call BuildPackage ,naiveproxy ))
你可能需要将 PKG_VERSION
替换成最新版本的编号,请首先去
NaiveProxy官方仓库 确认一下最新预编译的编号是什么。
修复 shadowsocks-rust 编译失败问题 问题源自 getrandom 这个 crate 在 0.3.2 版本里引用了 libc::getrandom ,但是 libc 并没有定义这个函数。我推测是 MIPS 下的 libc 没有支持。
这里使用补丁解决,在 Cargo.toml 配置里将 getrandom 的版本回退到 0.3.1 。
1
2
3
4
5
# 在 lede 源代码根目录
# 创建补丁目录
mkdir -p ./feeds/helloworld/shadowsocks-rust/patches
# 新建一个补丁
vim ./feeds/helloworld/shadowsocks-rust/patches/001-fix-getrandom.patch
001-fix-getrandom.patch 的具体内容为:
1
2
3
4
5
6
7
8
9
10
11
12
13
Index: shadowsocks-rust-1.22.0/Cargo.toml
===================================================================
--- shadowsocks-rust-1.22.0.orig/Cargo.toml
+++ shadowsocks-rust-1.22.0/Cargo.toml
@@ -246,6 +246,9 @@ shadowsocks-service = { version = "1.22.
windows-service = { version = "0.7", optional = true }
+[patch.crates-io]
+getrandom = { git = 'https://github.com/rust-random/getrandom.git', tag = 'v0.3.1' }
+
[target.'cfg(unix)'.dependencies]
daemonize = "0.5"
你可以在 附件下载 中下载到这个 patch 文件。
你也可以在编译失败的时候直接修改 Shadowsocks-rust 的源码:
1
2
3
# 在 lede 源代码根目录
# 编辑源码中的 Cargo.toml ,具体路径依据你的平台和版本可能有变化
vim ./build_dir/target-mipsel_24kc_musl/shadowsocks-rust-1.22.0/Cargo.toml
然后在文件里 覆盖 Cargo 依赖 :
1
2
3
# 添加这两行
[ patch . crates-io ]
getrandom = { git = 'https://github.com/rust-random/getrandom.git' , tag = 'v0.3.1' }
为了方便后续使用,你可以使用 quilt 生成补丁文件:
1
2
3
4
5
6
7
sudo pacman -S quilt
# 进入 shadowsocks 源码目录
quilt new 001-fix-getrandom.patch
quilt edit Cargo.toml
quilt refresh
# 回到 lede 源码根目录,直接拷贝补丁
cp -r ./build_dir/target-mipsel_24kc_musl/shadowsocks-rust-1.22.0/patches ./feeds/helloworld/shadowsocks-rust/
修复 v2dat 编译失败问题 问题和解决方法参见 这个 issue 。
直接添加编译选项
1
vim ./feeds/packages/utils/v2dat/Makefile
添加一项 PKG_USE_MIPS16:=0 就能解决问题。
4. 开始编译 简单的两行,不必多言。
1
2
make download -j8
make V = s -j1
然后等待大约3个小时,镜像就能编译完成。在经历了 3. 修改源码 后,我是一次编译通过的。
后记 附上一张编译成功结束的截图纪念一下:
这是刷入路由器之后的 LuCI 界面:
给路由器刷上编译完成的镜像后,到目前为止运行都是正常的。我又开启了
IPv6 功能,为每个设备分配了一个地址。代理目前也正常,路由器内存占用不超过50% ,代理速度比 OpenClash 快太多了。
软路由这块能折腾的东西太多,等空闲的时候再来研究研究吧。
附件下载