引子
OneinStack是一个简单快捷的LNMP安装工具,它可以在各种常见的Linux发行版(Debian/Ubuntu/RHEL系等)上快速部署Nginx Web服务器、MySQL/MariaDB等数据库以及PHP环境,同时可以安装的版本也很丰富,使用起来非常方便,是一个相当好用的 LNMP 安装包。
但是,这个好用的安装包却在去年(2023年10月)爆出了大问题,其镜像源被投毒,下载的二进制文件含有木马。
同样受此影响的还有著名的“军哥LNMP”,手法和Oneinstack如出一辙,都是官方源的DNS解析被CNAME到了被劫持的CDN节点上。
与此同时,这两个一键安装包被 “矜贵网络科技有限公司” 收购,官网都取得了ICP备案,备案的主体正是这家公司(现在已经变更备案主体,但仍无法确认原作者是否仍对项目有实际控制权)。值得注意的是,这家公司还经营一个盗版 MAC 软件网站,网站中同样有含有病毒的软件,似乎这家公司只是黑产背后的“白手套”。
虽然这两个一键安装包后来都“修复”了被劫持的情况,但现在究竟是谁在运营这些安装包的镜像源?原作者是否仍对镜像源和软件官网有控制权?之前发生过如此重大的安全问题,而原作者的轻描淡写态度让用户无法再安心使用这些工具。
上图为Oneinstack作者在Github上做出的说明。
Oneinstack着实好用,就此陨落也着实可惜。所以,真的要说再见了吗?
还有救!
Oneinstack脚本本身在Github是开源的,接受开源社区的Code View监督,脚本本身并没有被投毒。而它支持自定义镜像源,只要我们能找到其他可信的第三方Mirror镜像,或者我们手动搭建一个Mirror镜像,来替换掉它的官方镜像,就基本是安全的。当然为了追求更高的安全性,你还可以使用旧版本的脚本。
配置第三方镜像并使用
Oneinstack出事之后,有开发者开源了一个叫做oneinstack-mirror-generator的第三方镜像源生成器,可以让我们自己制作第三方镜像供Oneinstack使用。实测安装PHP、Nginx、MySQL可以基本顺利安装,偶有报错但不难处理。
开源库地址在此。
这个镜像生成器是用Python编写的,生成的镜像可以部署在Cloudflare Pages上。作者还公开了镜像Demo,我们可以直接使用,这个Demo会由Github Actions自动维护,以更新镜像中的软件包版本。如果不放心,你可以自行部署,自行部署私有镜像的步骤在下一小节。
使用步骤如下:
Step1. 拉取Oneinstack源码
git clone https://github.com/oneinstack/oneinstack
直接拉取Oneinstack的源码,不包含二进制安装包。当然,在这一步你可以选择回退到旧版本。
Step2. 修改options.conf
# mirror link
mirror_link=https://oneinstack-redirect-mirror.pages.dev
将官方源替换为镜像源生成器作者提供的镜像Demo。
Step3. 修改versions.txt(可选)
Oneinstack将所有待安装软件的版本记录在了安装包根目录下的versions.txt中。但是,随着时间推移和原作者更新相对滞后,versions.txt中的软件包版本有可能过时。这时候就要修改versions.txt进行手动更新。镜像生成器会生成推荐的软件版本,在此,我们需要将想要安装的软件的版本号在versions.txt中进行更新。
当然,你也可以选择当安装出现报错时手动下载缺少的软件包,手动解决可能出现的问题。
Step4. 使用&处理报错
如果你在第三步中处理的不好,没有完全替换,或者软件包版本更新的原因,安装过程中可能会出现一些报错。实际上这些报错处理起来都很简单。
示例1
安装PHP过程中,可能出现如下报错:
可以看到,上述报错修开始于"argon2-20190702",提示脚本找不到这个文件夹。因为在src目录下,可能由于软件版本更新的问题,下载下来的依赖argon2-20190702.tar.gz解压后的文件夹名称为phc-winner-argon2-20190702,而不是写死在脚本中的argon2-20190702。
修复方式:我们只需要将解压后的文件夹名改回argon2-20190702,重新进行安装过程就可以了。它会继续编译PHP并成功安装。
mv phc-winner-argon2-20190702 argon2-20190702
还有一些类似的报错,只需要阅读日志,修改src目录中下载或解压下来的文件/文件夹名称就可以解决。
示例2
安装PHP ImageMagick扩展时,可能出现如下报错:
这种报错大概率就是没有修改versions.txt,导致脚本下载的软件包在第三方镜像源中并不存在,实际上下载下来的是镜像源的描述页面。可以看到下面一张截图,ImageMagick-7.11-23.tar.gz仅仅只有191KB,而镜像源中存在的33版本下载下来却有16MB。
修复方式:建议从镜像源中下载7.1.1-33版本的ImageMagick,之后将文件名修改为ImageMagick-7.11-23.tar.gz后再继续安装。
部署私有镜像
在oneinstack-mirror-generator作者搭建的镜像Demo工作正常时,不建议自行部署私有镜像,利用Github Actions自动部署镜像的人一旦过多可能导致Github Actions的IP被拉黑,导致滥用。
需要:一个Github账号和一个Cloudflare账号。
Step1. 仓库准备
在Github上Fork oneinstack-mirror-generator开源库,地址在此。
在Github新建一个名叫oneinstack-redirect-mirror的仓库,并完成初始化。
Step2. 修改源码
修改自己Fork的oneinstack-mirror-generator仓库中根目录下.github/workflows文件夹中的redirect_rule.yml如下:
name: Redirect Rule Maker
on:
workflow_dispatch:
push:
branches:
- main
paths-ignore:
- '**.md'
# schedule:
# - cron: '0 0 * * *'
# 注释掉以上两行,取消Actions定时自动运行,需要部署最新镜像的时候我们再手动部署,以节省资源,同时防止IP被拉黑。
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout repo content
uses: actions/checkout@v4
- name: setup python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: install python dependencies
run: |
pip install -r ${{ github.workspace }}/requirements.txt
- name: Generate Config
run : |
python -u ${{ github.workspace }}/main.py
- name: Commit Output
uses: cpina/github-action-push-to-another-repository@main
env:
API_TOKEN_GITHUB: ${{ secrets.TOKEN }}
with:
source-directory: ./output/
destination-github-username: '[这里改成你的Github用户名]' #注意修改这里!
destination-repository-name: 'oneinstack-redirect-mirror'
user-email: [这里改成你的邮箱] #注意修改这里!
target-branch: main
建议开启Github的email privacy功能,防止你的电子邮件地址泄露。可以参见这篇官方文档。
Step3. 创建Token
进入Github,点击右上角你的头像,再点击Settings,再点击新页面左下角的Developers Settings。也可以直接点击这个链接直达。
按照下方图示创建一个Token,保存备用。
Note可以理解成名称随便填写,Expiration有效期可以拉满,repo和workflow复选框全部勾上。
Step4. 配置oneinstack-redirect-mirror仓库
进入Github中的oneinstack-redirect-mirror仓库,进入仓库设置,点击左边的Actions,再点击General,进入设置项。
滑到最下面的Workflow permissions,选择Read and write permissions后保存。
Step5. 配置oneinstack-mirror-generator仓库
进入Github中的oneinstack-mirror-generator仓库,进入仓库设置,左边偏下位置Secrets and variables,再点击Actions。
新建一个名字叫做TOKEN(全部大写)的secrets,内容是刚刚申请的Token。
最后进入仓库的Actions。因为是Fork来的项目,Actions默认被禁用。我们要启用Actions。然后运行Redirect Rule Maker,这样就可以在oneinstack-redirect-mirror仓库中得到最新的镜像。
Step6. 部署到Cloudflare
Mirror镜像的技术栈是Cloudflare Pages,需要部署在Cloudflare上。
登录到Cloudflare Dashboard,来创建一个Pages。
选择Pages,连接到Git,之后选择oneinstack-redirect-mirror仓库,不要选择成oneinstack-mirror-generator了。一路Next,很简单,齐活。这样你自己的Oneinstack Mirror镜像就搭建好了。
Enjoy it!
参考资料
mirrors.oneinstack.com 国内完整包 含恶意代码 · Issue #511 · oneinstack/oneinstack
oneinstack一键脚本似乎已经被一家名叫“金华市矜贵网络科技有限公司”的公司收购,该公司运营有一个盗版MAC软件网站 · Issue #510 · oneinstack/oneinstack
dalao-org/oneinstack-mirror-generator: Oneinstack required package mirror generator
关于LNMP供应链投毒事件风险提示
写在最后:如果oneinstack-mirror-generator的作者不希望此项目被公之于众,请联系我删除本文。





















