在 iKuai 爱快软路由上原生运行 OpenWrt 软件包

4 月 19 日
 Nyarime

熬了一个通宵,在爱快软路由 iKuaiOS 系统上实现了 musl 兼容层,使整个 OpenWrt 的软件包生态可以原生运行在爱快上,不需要虚拟机、Docker 装 OpenWrt ,总之也是 https://v2ex.ih06.com/t/1206925 闲鱼插件哥给的灵感,不过 iKuai 的国内用户量是真的很大,稳定性和多 IPv6 线路、流控能力都广受好评,那么好的系统连一个 root 都没有,生态封闭得爱快云上只有一个 Docker 插件,想装个 htop 、tcpdump 都不行。

大概研究了下,iKuai 的 binary 用的是 uClibc ,而新的 OpenWrt 用的是 musl libc ,因此两者不兼容直接跑会报错。得益于 OpenWrt 有 20k+的软件包,我从一开始补 opkg 、chroot openwrt 到最后的 musl 支持,向各位 V 友汇报。

不过爱快都在搞 4.0 了,3.7.x 本身就没在维护了,就当 EOL 前的狂欢吧。


正文

核心发现

Linux 内核支持同时运行多种 libc的程序,每个 ELF 二进制文件在 header 里指定了自己的动态链接器( interpreter ):

uClibc 程序: /lib/ld64-uClibc.so.0
musl 程序:   /lib/ld-musl-x86_64.so.1
glibc 程序:  /lib64/ld-linux-x86-64.so.2

内核根据 ELF header 自动选择对应的 linker 。只要把 musl 的 linker 放到 iKuai 上,musl 程序就能跑。

实现步骤

1. 放置 musl 动态链接器

# 从 OpenWrt rootfs 中获取 musl linker
# ld-musl-x86_64.so.1 实际上就是 musl libc.so 的 symlink
ln -sf /path/to/musl/libc.so /lib/ld-musl-x86_64.so.1

2. 配置库搜索路径

musl 的 linker 使用/etc/ld-musl-x86_64.path(类似 glibc 的ld.so.conf):

echo "/path/to/musl/libs" > /etc/ld-musl-x86_64.path
echo "/path/to/musl/usr/lib" >> /etc/ld-musl-x86_64.path
echo "/usr/lib" >> /etc/ld-musl-x86_64.path

3. 安装 opkg 包管理器

opkg 是 OpenWrt 的包管理器。我们使用了一个glibc 静态编译版本( 680KB ),可以在 iKuai 上原生运行:

opkg update    # 更新 6 个 OpenWrt 仓库
opkg install --force-depends --force-space --force-checksum htop

4. 验证

$ /usr/bin/htop --version
htop 3.3.0

$ /usr/bin/tcpdump --version  
tcpdump version 4.99.4
libpcap version 1.10.4

musl 程序和 uClibc 程序在同一个 iKuai 系统上和平共处!


为什么这样做?

不用 Docker

Docker 在软路由上需要额外资源(内存、存储),而且官方 Docker 插件版本老旧。很多时候你只是想装个小工具,不值得开 Docker 。

不用 chroot

最初我们尝试了 chroot 方案(下载一个 mini OpenWrt rootfs ,chroot 进去用)。可以工作,但:

不用刷 OpenWrt

有些人直接刷 OpenWrt 。但 iKuai 的多 WAN 、流控、行为管理是 OpenWrt 做不到的。

musl 兼容层是最轻量的方案:一个 symlink + 一个 path 文件 = 整个 OpenWrt 生态。


Naixi 项目

我们把这些工作整合成了Naixi——一个 iKuai 增强固件:

Naixi Plugin Manager

插件管理:
  naixi list                 列出所有插件
  naixi install <file|url>   安装插件(tar.gz)
  naixi enable <name>        启用插件
  naixi disable <name>       禁用插件

OpenWrt 兼容层:
  naixi opkg install <包名>  安装 OpenWrt 包(原生运行)
  naixi opkg update          更新包列表
  naixi opkg list            列出可用包
  # https://dl.naixi.net/ikuai-naixi/naixi_latest.sh

已安装组件展示

=== 已安装组件 ===
  ✓ docker v202102031900  [naixi]   运行中
  ✓ lucky v1.1.16         [naixi]   运行中
  ✓ opkg v1.0.0           [naixi]   运行中
  ✓ shell v202306081801   [pmd]     运行中
  · htop 3.3.0-1          [opkg]    已安装
  · tcpdump 4.99.4-1      [opkg]    已安装

云平台控制: Level 2
musl 兼容层: ✓ 已初始化 (12.6M)
opkg 原生环境: ✓ 已初始化 (opkg version 0.7.0)

四种来源的组件统一管理:

重启持久化

iKuai 的 rootfs 在内存中,重启后 opkg 装的包会丢失。Naixi 通过 boot 脚本自动恢复:

# 安装时自动记录
opkg list-installed > /etc/log/naixi/opkg-installed.txt

# 重启时自动恢复
opkg update && cat opkg-installed.txt | awk '{print $1}' | xargs opkg install --force-*

技术细节

iKuai 用的是 uClibc ,不是 glibc

很多人以为 iKuai 基于标准 Linux 发行版( glibc )。实际上 iKuai 使用的是uClibc

$ /lib/ld-musl-x86_64.so.1 --list /usr/sbin/tcpdump
  /lib/ld64-uClibc.so.0 (0x7f4b1e325000)
  libc.so.0 => /lib/ld64-uClibc.so.0

这意味着:

overlay 持久化

iKuai 自带 overlay filesystem 在/usr上:

overlay on /usr type overlay (rw,relatime,lowerdir=/usr,upperdir=/overlay/upper,workdir=/overlay/work)

opkg 安装的文件通过 overlay 写入,但/overlay/upper在 tmpfs 中。Naixi 通过记录+重装方式解决持久化。

可用的 OpenWrt 包

理论上 OpenWrt x86_64 仓库的所有包都能安装。已验证:

包名 版本 状态
htop 3.3.0
tcpdump 4.99.4
opkg 0.7.0
curl - 待测试
python3 - 待测试
luci - 需要 ubus ,受限

下载安装

用户名:sshd ,密码就是你设置的那个远程维护密码,登录后就是 root 权限。

安装 OpenWrt 运行环境

  1. 安装 opkg 插件:naixi install https://dl.naixi.net/ikuai-plugin/opkg.tar.gz

  2. 开始使用:opkg update && opkg install htop

  3. 执行htop可见 ik_rc_client 等爱快进程

  4. 插件可通过 naixi list查询列表及运行状态


安全声明

仅用于探索 iKuai 系统的可扩展性,使用naixi指令前请了解:


关于

11202 次点击
所在节点    OpenWrt
113 条回复
Nyarime
4 月 20 日
@lcy630409 v72 主要在写 openwrt 兼容层,目前 ikuai 缺少的东西有点多,luci 上去都报错
Gipserr
4 月 20 日
@lcy630409 重启马上去 yun 看是在线的,过一会才离线.
Gipserr
4 月 20 日
手工重启抓包:

按时间顺序

1. 21:48:14
192.168.2.250 先向 223.5.5.5:53 查 packages.ikuai8.com 的 AAAA/A 。
随后连 113.113.100.48:443 ,我从 ClientHello 里弱提取到了 SNI=packages.ikuai8.com
2. 21:48:51
再次向 114.114.114.114:53 查 packages.ikuai8.com
随后明文访问 113.113.100.48:80 ,这个是这次最硬的证据:
GET /cre/3/cre_123.3.x86_64.ikp HTTP/1.1
Host: packages.ikuai8.com
3. 21:48:52 到 21:48:56
连续多次向 114.114.114.114:53 查 dis.ikuai8.com
紧接着发起了 6 次到 47.94.237.123:1853 的短 TCP 会话,都是几百字节到一千多字节的二进制 payload ,时序上很像跟 dis.ikuai8.com 同一条链路。
这一条我判断为“高疑似爱快自家调度/分发链路”,但域名和目标 IP 没法在这份 WAN 侧样本里完全坐实。
4. 21:48:52
查了两次 time6.aliyun.com ,随后向 203.107.6.88:123 发了两次 NTP 请求。
这条更像标准时间同步,不像异常验证。
5. 21:48:58 到 21:49:04
连续多次向 114.114.114.114:53 查 downloads.openwrt.org
随后建立了 6 次到 146.75.114.132:443 的 TLS 连接,我从 ClientHello 里弱提取到了 downloads.openwrt.org
这条可以认为是爱快主动访问 OpenWrt 下载源。
6. 21:49:01
有 1 次到 123.57.179.21:1863 的短 TCP 二进制会话,payload 约 952 字节。
这条没有直接域名证据,只能标成“未知自定义连接”。
7. 21:49:35
向 114.114.114.114:53 查 www.ip138.com ,随后访问 120.39.215.140:80:
GET / HTTP/1.1
Host: www.ip138.com
User-Agent: Mozilla/5.0 (Linux; iKuaiOS; x86) AppleWebKit/537.36 (KHTML, like Gecko)
8. 21:50:05
同样又来了一次 www.ip138.com 检测,请求内容和 User-Agent 一样。
9. 21:50:13
只有 1 个到 220.202.27.130:443 的单独 RST 包,没有看到这次抓包内对应的建连过程,这条不能拿来下结论。

这次能坐实的主动外发

- packages.ikuai8.com
证据最强,既有 DNS ,也有 TLS SNI ,还有明文 HTTP GET /cre/3/cre_123.3.x86_64.ikp
- downloads.openwrt.org (这个可能是你的 opkg 升级)
有 DNS ,也有 TLS SNI
- www.ip138.com
有 DNS 、明文 Host ,还有明确的 iKuaiOS User-Agent
- time6.aliyun.com -> 203.107.6.88:123
标准时间同步

这次最值得盯的可疑点

- dis.ikuai8.com 查询后,连续打 47.94.237.123:1853
- 123.57.179.21:1863 的单次二进制短连接


(ip138.com 是我测活的 http 设定)
chengran630
4 月 20 日
@Gipserr dns 223.5.5.5 114 是 ikuai dns 设置里的默认 dns 么?可以修改这个 dns 测试么?如果这个 dns 是可以设置的 那么可以做一个假 dns 来应答 ikuai8.com 域名
Gipserr
4 月 20 日
@lcy630409 可能可以内置一个 dns ,这个是写到 resolv 的 dns 。
sghsgh
4 月 20 日
谢谢,终于可以 IK 上跑个楼梯了
a56143575
4 月 20 日
大佬牛逼!这个只是适合在 X86 机器上吧?
lxxiil
4 月 21 日
请问大佬,那个 sk5 分流插件可以去掉授权吗,300 元真的好贵
Nyarime
4 月 21 日
@sghsgh 你想跑就跑吧,更新最新的 v72v4
https://dl.naixi.net/ikuai-naixi/iKuai8_x64_3.7.19_Naixi_v72v4.bin
然后初始化一下,直接 naixi install https://dl.naixi.net/ikuai-plugin/naixi-compat-x86_64.tar.gz 就行了
于是你的 9090 端口就出现了 LuCI ,密码跟你的维护密码一样( SSH 密码同)
Gipserr
4 月 21 日
@Nyarime 爱快牛逼,更新了这个版本,安装 naixi-compact 重启以后,我爱快的配置全丢了。
云绑定被解除,内外网配置的配置页面打不开,一片空白,网卡绑定刷新一下配置页面就变回空白,重启以后也是这样。
然后再上传 bin 提示:错误: 无法识别这个文件。
是不是被爱快遥测干掉了配置。还好是个用来测试的系统。
Nyarime
4 月 21 日
@Gipserr 你确定是 v72v4 造成的吗,让我 debug 一下
Gipserr
4 月 21 日
测试了一下爱快命令行的重置功能,重置以后的结果是:
1.重置以后要重新设置 web 密码/IP
2.进去以后在 web 内外网还是无法配置
3.ssh 连接要重新启用,要自己设置 sshd 的密码,不能共用 web 的了
4.ssh 上去以后,naixi 的系统和配置还在
5.还是无法上传 bin 更新系统
Gipserr
4 月 21 日
@Nyarime 不确定,我是挂了一晚,回来看到你有更新,更新了以后出现这样的结果。不知道是不是爱快已经提前做了手脚了。因为更新 v72v4 以后我马上刷了爱快云,这个服务器还是显示在线和有客户端的。因为昨天抓包提示启动的时候会访问 packages ikuai com 抓一个 /cre/3/cre_123.3.x86_64.ikp ,它也可以抓其他东西。
Gipserr
4 月 21 日
@Nyarime 我重新做了一个 3.7.17 的干净系统,不配置 wan ,只配置了 lan ,用 v72v4 更新进入系统,版本号是 3.7.19 ,各项配置都正常,也能重新用 v72v4 的 bin 再次升级,没有报 “无法识别这个文件“ 。 证明 ikuai 肯定做了手脚。
Nyarime
4 月 21 日
@Gipserr 请提供下版本号,我们在 debug compat 层安装确实是遇到了这个问题,并且也 v72v4 修复后观察了一阵子,可能你需要详细的说明下情况,我自己 debug 后先推个 v72v5 给你,实测装完 compat 后是没这个问题的
当时遇到那个问题我们虚拟机就恢复快照了,而且重置、rc.console 选 6 也没法修复,最后回滚。然后后续测试就没有再发现这个问题。我先回退到官方版的免费版环境,一步一步来试试,应该就能排除掉问题

顺带一提,使用 naixi ikuaiyun clean 清除云平台信息、再用 naixi ikuaiyun 2 阻断全部,最后重启
试试全新安装上 v73: https://dl.naixi.net/ikuai-naixi/iKuai8_x64_3.7.19_Naixi_v73.bin
940i3s34v4F1HW41
4 月 21 日
大佬
chengran630
4 月 21 日
@Gipserr
我昨晚测试 iKuai8_x64_3.7.19_Naixi_v71v11.bin 后 到现在还能正常使用,我在帖子中都贴了 GWID 。如果说要处理 应该不会放过我吧...
Gipserr
4 月 21 日
早前装完 compat 以后我的确也没见到 9090 起来。
现在我在干净的系统装了 v73 ,clean 了云平台,阻断了 2 ,挂久一点看看会不会被改啥,谢谢。
另:开机会连接 packages.ikuai8.com ,为什么 hosts 没有加这个域名呢?@Nyarime
Gipserr
4 月 21 日
@lcy630409 你这个 ikuai 有绑定他们云平台吗?
Nyarime
4 月 21 日
@lcy630409 v71v11 里面我默认是 ikuaiyun2 ,甚至是运行进程里没有 ik_rc_console ,它怎么可能抹你机器。大概是我写了一个 bug ,这个会在 v74 修复,大概根因是 naixi_boot 脚本的 "opkg restored from cache" 步骤——往满的 rootfs 写 opkg 文件导致破坏,然后你会发现 iKuai 重启后就不正常了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://v2ex.ih06.com/t/1206946

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX