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


关于

11188 次点击
所在节点    OpenWrt
113 条回复
chengran630
4 月 20 日
@Nyarime
大佬, 更新你的固件后,在 ikuai 云里 还是显示在线呢
“在线
未分组
4513a501d96e4b0a99843b4518f044dc
普通 ()
59.174.1.1 (中国 湖北 武汉)
3.7.19 x64 Enterprise Build202504071143” 这样一下就知道了....
chengran630
4 月 20 日
可能是需要设置 naixi ikuaiyun 2 才不会显示?我先试试
chengran630
4 月 20 日
设置 ikuaiyun=2 重启后 ikuai 后台还是显示在线,不知道是 ikuai 显示有问题 还是 没屏蔽到
有点怀疑 ikuai 没有用到自身的 host 文件

本来想学教程 NyarcPro iKuai 固件操作教程操作固件 将所有 script 中的所有 sh 文件的 ikuai 域名进行替换,但是 xz 总是报错 换了好几台机器 ubuntu 和 centos 都试过了...停住了,等 op 起床 再来看看吧
[root@localhost ikuaii]# nyarc --ikuai-decrypt iKuai8_x64_3.7.19_Build202504071142.bin d.xz
Decrypting iKuai rootfs: iKuai8_x64_3.7.19_Build202504071142.bin -> d.xz
🔑 Mode: fixed (key=77b1fa93742cb39d3383553e848a5291)
⚠️ Hash mismatch: calc=0xD50DA3DB stored=0x03200000 (may still be valid)
✅ Decrypted: d.xz (40.7MB)
✅ Decrypted: d.xz (40.7MB)
[root@localhost ikuaii]# ls
d.xz iKuai8_x64_3.7.19_Build202504071142.bin
[root@localhost ikuaii]# xz -d d.xz
xz:d.xz: 无法识别文件格式
chengran630
4 月 20 日
[root@localhost ikuaii]# nyarc --ikuai-decrypt iKuai8_x64_3.7.22_Build202603301146.bin 22.xz
Decrypting iKuai rootfs: iKuai8_x64_3.7.22_Build202603301146.bin -> 22.xz
🔑 Mode: fixed (key=77b1fa93742cb39d3383553e848a5291)
⚠️ Hash mismatch: calc=0xAFF36B3F stored=0x03200000 (may still be valid)
✅ Decrypted: 22.xz (41.0MB)
✅ Decrypted: 22.xz (41.0MB)

测试 3722 版本 好像不能识别到 key ?提示中 key 还是使用的 77b1 ?
bncfbb
4 月 20 日
--ikuai-repack 好像用不了 没任何输出
Nyarime
4 月 20 日
@lcy630409 感谢反馈,目前还是存在不少 bug ,待我 debug 后推送新版本
Nyarime
4 月 20 日
@lcy630409 我们的版本是做了免格的,不过 ikuaiyun 2 的阻断没做好,实在抱歉
打算在脚本中加 iptables 阻断,看了下二进制是不走 hosts 的也就是硬编码内容在这些服务不生效
ik_rc_client → as1.ikuai8.com:9443
as2.ikuai8.com:9443 (远程控制/云管理,这是主要的云在线连接)
ik_wpa_ppsk → yun.ikuai8.com
脚本:
client.shcoll.ikuai8.com:2016 (数据采集)
wecom.shiapi.ikuai8.com:21422
upgrade.sh → 云自动升级
webman.lua → yun.ikuai8.com/api/v3/router_bind/

等于说,我在测试 htop 兼容性的时候就看到 ik_rc_client ,这个也需要 kill 就是了
你也可以装个 htop 看下是哪个进程在通信,这个 level2 在设计上确实是要阻断的
Gipserr
4 月 20 日
ping ikuai8.com 会跳到 catl.com 这个也要屏蔽吧。
chengran630
4 月 20 日
@Nyarime 能直接把 ikuai 的域名直接改成 baidu 么?直接从代码上替换掉?
chengran630
4 月 20 日
@Nyarime 看到最新的 naixi_v13 了,是 iptables 阻断特定 ip ,这个感觉不是很可靠
最起码要实时查询域名的 ip 再阻断,ip 这东西修改太容易了
Gipserr
4 月 20 日
汇报一下 v70v5 的那个 bin 的使用情况。
yun.ikuai8.com 的后台还能看到路由器在线
但是信息(客户端)上报的情况停留在系统启动 5 秒以内。
Gipserr
4 月 20 日
过了五六分钟以后又全量终端信息上报到云平台了。看来隔绝的还没搞定。
Nyarime
4 月 20 日
@Gipserr 除了 ik_rc_client 我们处理了,你说的采集上报连的是 dis.ikuai8.com:1853 ,这个我更新后喊您
今天目标就是把这个处理掉,然后完善 luci
Nyarime
4 月 20 日
@s1oz iKuai 内核 5.10.194 没编译 xt_TPROXY.ko

问题是我没法加内核模块,除非:编译一个匹配 5.10.194 的 xt_TPROXY.ko (需要 iKuai 的内核源码 那几乎不可能
Nyarime
4 月 20 日
@lcy630409 回答你的两个问题
1 )直接二进制改成 baidu
改字符串其实是可以的,但是长度要跟原本的域名一样,另外 ikuai 如果有校验改了会崩系统
2 )上报解决的事情
1. 二进制重命名,由 naixi_boot 考虑是否加载,换句话说,你进程都没了,你还怎么上报? ik_rc_client/cre/dtalkd 根本跑不起来
2.对 monitor_process.sh patch 他那个守护进程也拉不起来
3. hosts 屏蔽 但是你知道他有一段硬编码已经写到了自己的二进制里,那个 IP 我已经改掉了
4. iptables 是兜底,或者说他们公司会一直续费这个 IP 所对应的服务器
补充:我没有卖过钱,都是免费开放用于 v 友研究,并且目前 ikuai 最新版是 4.0 而不是 3.7 这已经是老版本了
Nyarime
4 月 20 日
@Gipserr 至于这个问题,你可以进 ssh 定位下 monitor_process.sh ,这是个死循环

start() {
sleep 60 # 开机等 60 秒
while : ; do
# 检查每个进程是否存活
if ! __get_process_status ik_rc_client; then
cgroup_exec ik_rc_client & # 没了就拉起
fi
if ! __get_process_status cre; then
cgroup_exec cre &
fi
# ... 其他 20+个进程
sleep 30 # 每 30 秒轮询一次
done
}
Nyarime
4 月 20 日
@Gipserr 目前 v71v11 已经彻底解决
https://dl.naixi.net/ikuai-naixi/iKuai8_x64_3.7.19_Naixi_v71v11.bin
# 执行阻断
naixi ikuaiyun 2
Gipserr
4 月 20 日
@Nyarime 谢谢.目前最新版本的状况:
1.yun 还是显示这个路由器在线
2.终端用户会在启动后上报一次,然后就不再更新了,可能是启动过程中抢先上报了.
已经很有曙光了,以后再慢慢研究.
chengran630
4 月 20 日
@Nyarime
如果能修改域名 直接随便改,改成 ikuai9.com 都行,只要不给到 ikuai ,
看下大佬有没有空 修改一个改了域名的 我可以测试 我的 ikuai 是 esxi 里的

期待 nyarc pro 的修复版
chengran630
4 月 20 日
@Gipserr
我测试 上面哪个 iKuai8_x64_3.7.19_Naixi_v71v11.bin ,ikuai 云中 已经显示离线了

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

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

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

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

© 2021 V2EX