在 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指令前请了解:


关于

11204 次点击
所在节点    OpenWrt
113 条回复
chengran630
4 月 21 日
@Gipserr 绑定了的,阻断问题 大佬应该处理差不多了
不过我还是固执的认为 阻断固定 ip 不妥当,还是应该尝试获取域名的实时 IP 去阻断
我看大佬 好像已经把 monitor_process 处理了
if [ -f /usr/ikuai/script/utils/monitor_process.sh ] && ! grep -q "NAIXI_BLOCK_RC" /usr/ikuai/script/utils/monitor_process.sh; then
sed -i '/ik_rc_client/i\# NAIXI_BLOCK_RC\nreturn 0' /usr/ikuai/script/utils/monitor_process.sh 2>/dev/null
fi
chengran630
4 月 21 日
@Nyarime 按照原理来说 应该是不会被远控了

大佬对这个开心版 有什么计划么?想做到什么程度
chengran630
4 月 21 日
还有 我不太建议 把 ipv6 的设置 直接集成,只提供其他功能 比如 root
修改让使用者自己弄

ipv6 的数量 确实是 ikuai 官方的一个盈利点,这样直接带破解 容易引起官司
Gipserr
4 月 21 日
@lcy630409 做到小米那种 root 模式我觉得就好了,尽量不要对原来的系统功能覆盖太多,自己用 AI 编程跑几个服务在上面,减少一些外部机器的依赖。我看来 ikuai 原来的缺点就是不能跑高权限的 docker ,不能跑 wireguard 服务器端(付费的可以跑客户端)。我用 ikuai 不用 openwrt 的原意就是 openwrt 的升级/依赖/dns/端口映射/防火墙这些搞得我很不爽。
Nyarime
4 月 21 日
@Gipserr 我在 v74 版本拿了 43 字节的假文件做替身,可以说云平台实际上是根除了
至于后门问题,已经云控组件物理删除( ik_rc_client/cre/dtalkd/ik_wecom ),换句话说 pmd 下载了 cre 的 pkg 也释放不出来(被替身脚本占位)
cat /usr/sbin/ik_rc_client
cat /usr/sbin/cre
这 43 字节:#!/bin/sh\nwhile true; do sleep 86400; done\n

另外我解释一下为什么会出现无法识别、web 爆炸,经过一上午的排除,得出一个结论:往一个即将塞满的 rootfs 塞入 runtime 是不合适的,最后重构了一下,从我最后一条回复到现在埋头苦干
固件: https://dl.naixi.net/ikuai-naixi/iKuai8_x64_3.7.19_Naixi_v75v2.bin
安装:升级后执行 naixi openwrt init

该版本实现:
LuCI 中文管理界面(:9090 )
opkg 包管理器(安装到持久化分区)
零 rootfs 写入(不破坏 iKuai Web UI )
自动安装:naixi openwrt init 一键搞定
至于插件适配,该放我去睡觉了...
Nyarime
4 月 21 日
@lcy630409 ipv6 你修改都无所谓的,因为 /etc/mnt 本就是持久化分区
我的脚本只会作为一个 OpenWrt 运行兼容层存在,不喜欢你可以不装 又或者利用我开发的 Nyarc 自行解包、组装,总而言之工具已经放出来了,想怎么做是你的自由
至于说我特地选择 3.7.19 而不是最新的 3.7.22 或 4.0 ,就是为了避免官司问题 其次我并没有进行贩卖
单纯就是看闲鱼那帮 或者是前阵子发 3.7.14 (带 root )那帖的人不爽,我看评论区格了不少人

至于 iKuai 系统,最新的 v4.0 自己拆包看吧,组装方法我就不放了避免法律问题
敢用 iKuai 官方的人,甚至是买爱快 OEM 路由器的,那都是艺高人胆大
https://dl.naixi.net/nyarc/report/4024_audit_report_cn.html
Nyarime
4 月 21 日
@lcy630409 分 4 步
1 )杀进程,然后 pmd 会接着下载 ikp 接着释放,最后直接 43 字节码住
2 )杀守护,就你说的 monitor_process.sh 我已经处理过了
3 ) hosts 屏蔽,可你知道人家硬编写了( hardcode )有啥用
4 )阻断 IP ,你说的对,但这些 IP 基本上很少见得到,又或者是可能误杀 CDN 节点
-------------------------------------------------------------------
至于我下说的是,1 、2 已经可以食用了,3 、4 单纯就是多余的步骤、求保险
至于说官方干啥了自己解包自行研究吧,本文仅供学习交流,严禁用于商业用途,请于 24 小时内删除。请支持正版!
Gipserr
4 月 21 日
@Nyarime 牛逼,互联网精神与你同在。
earpiece5631
4 月 21 日
我也是昨晚 3 点过看到 72V4 就刷了,也是界面出问题了,起床后才起来重置的。
Gipserr
4 月 21 日
继续反馈一下:我刚才升级了 v75v2 ,默认登录进去,wg/docker 都是没有的(我原来 iso 全新安装,没有给硬盘分区)。

然后我给硬盘分区,重启以后,发现/tmp/ikpkg 下载了一些软件:

app_show docker docker-bin ik_host netboard nginx_conf pmd pre_cdn_stats shell

ik_host 里面有可以遥测增加的 IP:
cre_host
dis.ikuai8.com:1853
59.110.171.18:1853
47.94.237.123:1853
59.110.171.18:2016
47.94.237.123:2016
pmd_host 里面有:
cat pmd_host
123.57.179.21:1863
123.57.179.21:15602
pkgmanager.ikuai8.com:15602
59.110.6.135:1863
59.110.6.135:1560

shell 里面看来是个云备份工具
下载的 docker 也没有搞清楚怎么运行起来(因为后台是云平台操纵启用的,我没有绑定云平台)
chengran630
4 月 21 日
@Gipserr
看来 还是修改域名最靠谱了 将 ikuai8.com 改为 ikuai9.com 之类的
6AbK2rj2vLBD
4 月 21 日
@Gipserr 看你说的,这个意思就是无论登不登录云平台或者账号,都会自动从官方服务器下载一些组件
Gipserr
4 月 21 日
@lcy630409 这玩意真像病毒,想尽一切办法给自己保活。禁止写/tmp/ikpkg 不知道行不行。
s1oz
4 月 21 日
我直接一了百了,ik_rc_client/pmd/cre/ikaudit_update/ikaudit_update 之类全干掉,monitor_process 删掉相关的,然后手动加个 lib 的规则更新,最后给个假的绑定码伪绑定开机自动载入 docker😈
chengran630
4 月 21 日
@s1oz 大哥 docker 怎么启动 之前用的 docker 断掉云控之后 就没显示了
Gipserr
4 月 21 日
@lcy630409 codex “帮我去 sshd@10.10.10.253 看看 /tmp/ikpkg/下面我同事设置的 docker 自动启动的条件是什么,我忘了。”

/tmp/ikpkg 里面的包是 /etc/log/packages 里面开机解压的
chengran630
4 月 21 日
....没有了 是被制裁了?
Gipserr
4 月 21 日
## 我做了什么

### 1. 修复了 Docker 的持久启动链

这台机器不是普通 Linux 根盘,而是 `RAM root`。很多运行时文件重启后会丢,所以不能把修复写在 `/tmp` 或 `/usr` 的 RAM 层,必须写到持久层。

我把最小修复落在:

```text
/etc/log/naixi/compat/boot.sh
```

作用是:

- 开机时把 `/etc/log` 挂成 Docker 的持久工作盘映射
- 自动补 `/docker` 和 `/usr/sbin/docker`
- 如果系统恢复了原来的 `docker_server`,就走原链路
- 如果重启后只恢复了 `docker-bin`、没恢复 `docker` 脚本包,就直接用 `dockerd` fallback 起引擎

## 2. 清掉了高风险包和自恢复链

已删除并持续阻断的对象包括:

- `pmd`
- `cre`
- `ik_rc_client`
- `ik_host`
- `shell`
- `pre_cdn_stats`
- `ikaudit`
- `monitor_process.sh`

对应的持久包、运行目录、入口文件和 RAM root 自恢复脚本都已经清理,并写进了开机清理逻辑。

## 3. 封死了高风险云拉取 / 外联链

现场最危险的链路是:

```text
update_hosts.sh
-> 从 302.ikuai8.com 获取主机列表
-> submit.lua 拉取 submit3
-> 本地直接执行
```

这条链现在的处理方式是:

- 开机强杀 `update_hosts.sh` / `submit.lua` / `async.lua`
- 删除 `/tmp/iktmp/ik_hosts` 和 `/tmp/iktmp/submit`
- 把 `/usr/ikuai/script/utils/update_hosts.sh` 改写成 no-op
- 把 `/usr/ikuai/script/utils/submit.lua` 改写成空壳

同时保留 `Naixi cloud level 2` 的原有阻断:

- `/etc/hosts` 将一批 `ikuai8.com` 云域名 sinkhole 到 `127.0.0.1`
- `iptables OUTPUT` 对多个 `iKuai` 云 IP 做 `DROP`

## 4. 现场验证结果

本次整改后,我已经做过两次 reboot 后现场复核,确认以下结论成立:

- `Docker` 第二次 reboot 后已能自动起来
- `docker info` 正常
- 高风险的 `update_hosts.sh` / `submit.lua` / `async.lua` 没有复活
- `pmd/cre/ik_rc_client/ik_audit/monitor_process` 相关进程没有复活
- `/tmp/iktmp/ik_hosts` 和 `/tmp/iktmp/submit` 没有复活
- `netstat -anp | grep ESTABLISHED` 现场未看到新的云端已建立连接
Ne
4 月 21 日
大佬牛逼,不用也先支持大佬。
earpiece5631
4 月 21 日
完结撒花,还好下了个最新版

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

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

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

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

© 2021 V2EX