配图: brown wooden ship’s wheel photo – Free Image on Unsplash
最近想在自用的软路由上装某个包,而那个包没有提供预编译的软件包,需要自行编译,而且由于某些原因,还不提供文档,只能自己摸索。由于个人喜欢原版固件多于 Lineol 和 Lean 两位的修改版,而又想尝试 Passwall,所以想尝试一下用原版 OpenWrt 的 SDK 编译 Passwall 看看是否可行。前几次因为种种原因,都失败了,最近这一次比较幸运,成功了。另外发现这次用的办法挺通用的,而且查了一圈,比较少有人这么做,故这里讲一下这次用的方法。
OpenWrt 项目的文档比较健全,好多东西都可以找到文档,但是呢,需要对 OpenWrt 的生态熟悉,且对 OpenWrt 怎么组织文档也要熟悉,不然,也不太好找到合适的资料,有几次就因为没找到,去 https://forum.openwrt.org/ 发贴询问后有人直接发文档链接出来,确实是需要的文档,但是就是没找到,emmm….
不管是编译 OpenWrt 固件还是软件包,第一步都是搭建环境,之前有几次尝试,都是因为这一步没有完成,才放弃的,编译环境依赖的东西很多很杂,不是很好搭,虽然好多东西都是查文档或者 Google 得到,但还是麻烦的,对没有相关经验甚至没有编程经验的人来说,门槛有点过高了。
昨天突然想到能不能用 Docker 呢,如果有做好的编译环境镜像,可以快速搭环境,同时 Docker 跨平台,各个平台上都可以以同样的方式编译软件包了,方便实用。
有没有镜像呢,查了一下,还真有,OpenWrt 官方提供了全架构的 ImageBuilder 和 SDK Docker 镜像,只需要找到对应的架构的镜像使用,就可以了,不需要关心编译环境本身的一些依赖缺失或者版本不对等等问题,只需要偶尔有些软件包需要安装一些系统工具的时候,稍加修补即可。
这里拿最开始想编译的那个包为例,讲一下整个过程
正文开始
安装 Docker
这里推荐 Docker 官方文档, https://docs.docker.com/get-docker/ ,已安装过的,可以略过此节。
找到对应的 SDK 镜像
Docker 镜像的名字和 OpenWrt 的架构直接相关,当前版本支持的架构可以在这里看到 https://downloads.openwrt.org/releases/21.02-SNAPSHOT/targets/ ,比如软路由一般用的 x86/64 和 R2S 的 rockchip/armv8,其对应的镜像就是 openwrtorg/sdk:x86_64-21.02-SNAPSHOT
和 openwrtorg/sdk:rockchip-armv8-21.02-SNAPSHOT
,总之,在 https://hub.docker.com/r/openwrtorg/sdk 这里找就对了,总能找得到的。
编写编译脚本
通常,编译软件包的时候,经常会看到几条命令,类似这样的
|
|
总结一下,这几行命令,做了以下几件事
- 下载 SDK 并解压
- 添加软件源
- 添加软件包(上面的例子中,这一步就是添加了要编译的软件包,主要是其 Makefile)
- 编译
这次要编译的是 Passwall,源码在这里 https://github.com/xiaorouji/openwrt-passwall
他和 shadowsocks-libev 不同的是,这个项目已经把所有的软件包组织成了 OpenWrt Feeds,编译时只需要添加这个 feed 就可以了,转换成的脚本如下:
|
|
启动容器,执行编译脚本
|
|
这是一个 docker-compose 配置,使用 docker-compose 启动即可,命令如下
|
|
完成后即可在 bin 目录中看到对应的软件包
编译过程总结
以上步骤为了讲解,具体使用可以这样
|
|
包签名
在使用 OpenWrt 过程中,经常会遇到一个东西,叫签名,比如添加软件源后,要手动添加一个 key
|
|
再比如编译固件或者包时,添加了一个 feed,编译时会遇到签名验证错误 signature check failed
等,这时候就需要添加对应的 key 或者删除签名验证
|
|
不验证是不建议的,有这个机制来保证安全的情况下,还是建议使用。
再有就是我们看到,opkg 源都会看到类似这样的结构:
这些东西都是签名这个机制中的东西,
Packages.asc 的 GPG 生成的签名,Packages.sig 是 usign 生成的签名,由私钥生成,而 .pub 文件就是公钥,用来验证私钥生成的签名,确保相应的包文件确实是由信任的人或者机构签发的,说了这么多,我们已经生成了包文件,那么想生成签名怎么办呢?
签名生成
根据 OpenWrt 文档,https://openwrt.org/docs/guide-user/security/release_signatures 和 https://openwrt.org/docs/guide-user/security/keygen,得到的信息,OpenWrt 支持两种签名方式,GNUPG 和 OpenBSD signify,我们通常看到的像下面这样的公钥,是 OpenBSD signify 工具生成的
|
|
OpenWrt 官方提供了 usign 来实现和 OpenBSD signify 一样的功能。
usign 的使用见文档 https://openwrt.org/docs/guide-user/security/keygen#generate_usign_key_pair
生成的密钥对的私钥,要好好保存,这是证明你是合法的发布者的唯一方式,密钥的生成需要私钥,复制一份私钥,命名为 key-build
并放到 SDK 的根目录下,在编译完成后执行 make package/index
命令的时候,签名会自动生成
一个之前的疑惑
这里只讲一个我个人之前迷惑的问题,之前编译 R2S 的软件包的时候遇到签名验证失败问题,没有找到解决方法,就移除了签名验证,另外那次发现 R2S 的 SDK 解压后有一个 keys 文件夹,里面都是看起来是随机生成文件名的文件,内容是 key
|
|
看到这些只知道是根据这些 key 来验证的,但是这名字从哪来的?后来看到 https://openwrt.org/docs/guide-user/security/keygen#add_public_key_to_the_repository 这个文档的时候,知道这个文件名是这个公钥的 fingerprint,所以要这样得到 fingerprint
|
|
将生成的公钥重命名成其 fingerprint,再放到 keys 文件夹就可以正常验证签名了。
搭建 OpenWrt 软件源
软件包编译好了,可以拷到系统里进行安装,但是又不太方便,可不可以做软件源,这样只需要 opkg install xxx
就可以安装了, GitHub 就可以提供这样的服务,当然这并不是 GitHub 的本意,只不过是因为 GitHub 提供了对仓库文件的直接访问机制而已
比如 simonsmh/openwrt-dist 仓库下的 readme.md 文件就可以通过下面的链接访问到
https://github.com/simonsmh/openwrt-dist/raw/master/readme.md
opkg 软件源也只不过是需要对一个目录下的所有文档进行访问就可以了,那么把 bin 下 带着这些文件的文件夹初始化为一个 git 仓库并推送到 GitHub 仓库,就可以了
|
|
比如推送到了 xxx/passwall 的 x86/64 分支,那么下面的链接就可以作为一个软件源来使用了
|
|
因为可以在链接后面加一个 Packages 就可以访问到软件源的索引,这样它就是一个合法的软件源
这样就可以在 OpenWrt 系统的 /etc/opkg/customfeeds.conf
中添加源
|
|
或者在编译固件或软件包时,添加到 repositories.conf
|
|
当然如果需要验证签名,还需要处理一下,添加对应的 key 文件到系统中。
这里有一个真实的例子:
https://github.com/simonsmh/openwrt-dist/raw/packages/x86/64 是可以作为软件源的,因为 https://github.com/simonsmh/openwrt-dist/raw/packages/x86/64/Packages 是可以访问到的
写在最后
这里通过一个例子将了使用 Docker 编译 OpenWrt 软件包,其他的软件包也可以这样编译,方法是通用的,只不过中间要进行一些小的调整,希望对大家有所帮助。