最近整了一台软路由,配置还不错,既然这样那肯定要折腾折腾,首先肯定是要刷个 OpenWrt 嘛,但是网上找到的固件都不太合我心意,要么是软件包过于冗杂,要么是太过精简,于是就想自己编译一个固件来用,接下来便是踩坑的开始。

老规矩,先上一张成果图:

编译部分

编译所使用的源码是 Lean’s OpenWrt。这套源码在论坛里很有名,编译成功率也高。

编译方案

编译有本地和云端两张方式可选,本来是觉得自己电脑CPU性能还可以要不本地编译吧,但了解到编译过程中需要下载Linux内核以及其他的一大堆东西时,还是选择了云端编译方案,最终选用了 P3TERX 的 Github Actions 编译方案

编译配置问题

在配置时碰到了好几个问题,这里记录一下。

首先是目标镜像的文件系统问题。一般情况下大部分人选择的都是 SquashFS,这个文件系统的优点是系统分区默认只读,所有的配置都在 /overlay 分区下,这样每次重置时就只需要清除这个分区的内容就可以。但对我来说,我是一个比较喜欢折腾的人,难免会经常对系统分区魔改啥的,而这时 Ext4 文件系统就比较符合我的要求。但是我在网上一些论坛找其他大佬编译的包时,几乎找不到Ext4文件系统的镜像,所以觉得很奇怪。

后来,当我在一个大佬的群里问起这个的时候,有人告诉我,使用 Ext4 文件系统如果不正常关机的话会造成文件系统只读或损坏的现象。然后我详细去了解了一下,发现这个问题是 Linux 系统共有的问题。不过虽然这样我任然心存一丝侥幸,自己应该不会碰到不正常关机的情况。再后来,我为了验证这个情况,再正常使用时将软路由直接断电,连续进行了三次实验,均没有发现文件系统出问题。于是我就安心的继续用我的Ext4文件系统了。(截止写文章时已经正常运行了两天半)

然后是软件包的选择编译问题,这个问题可能比较玄学,具体哪个包跟哪个包会冲突很可能要等到编译失败的时候才知道(一般都是编译两个多小时了才失败),而且网上论坛里也很少有讨论这个的。比如想包括 IPv6 功能时要选择与IPv6有关的包,这时候 odhcpd 和 odhcp-ipv6 这两个包就会冲突,而且这两个包的描述写的都是 IPv6 相关功能的,并且 odhcpd 跟另一个叫 odhcpc 的包名字很像,稍有不慎就会选错。除了这个以外其他的比如luci-samba和luci-amba4也会引起这样的冲突。

还有一个会引起冲突的就是 luci-base 和 luci-compat 当版本不对应时引起冲突。第一次的我编译的包没有编译 luci-compat,在使用时尝试安装就会装不上。而第二次在编译时就把两个包同时装上就没问题。

另外,如果你配置时选择的软件比较多,编译时可能会出现 out of space usage 的问题,这是因为默认情况下 OpenWrt 的Root分区只有 160 MB 的空间,软件一多自然就装不下了。在编译配置时把 root patition size 调大就行了,我调的是 512MB。

还有一个内核版本的问题,Lean’s OpenWrt 的最新源码所采用的Linux内核版本号是 5.4.156 (现在又升级到了5.4.158)。在 OpenWrt 的软件源仓库中,有一个叫 kmods (Kernel Modules) 的文件夹。顾名思义,就是Linux内核的附加模块。这个文件夹里又有以内核版本号和哈希值命名的文件夹,在安装这类的包时,会验证系统的内核版本号是否跟这里的一致,如果不一致是装不上的。(也可以强制安装,但大概率会出问题)

在官方最新的 Release 版本的软件库中,这个版本号是 5.4.154,即使是最新的 Snapshot 版本(即不稳定版本),这个版本号最大也只有 5.4.143,所以使用更高的版本号必然导致内核模块不兼容。如果喜欢在使用时安装其他模块的话,必然会有很多模块装不了。

Actions-OpenWrt 中提供了两个自定义脚本供使用,于是我们可以在diy-part2.sh这个脚本里对内核版本进行修改。下面是我使用的命令,仅供参考:

1
2
sed -i 's/LINUX_VERSION-5.4 = .156/LINUX_VERSION-5.4 = .154/' include/kernel-version.mk
sed -i 's/LINUX_KERNEL_HASH-5.4.156 = 06fe73e4623fcf1b3c0d0e1983d8286a2ff5b8fffbcb2163f4c01696a1c377fe/LINUX_KERNEL_HASH-5.4.154 = 058994f4666b6b0474a4d5228583e394594e406783b7e93d487c2a66c35f3c06/' include/kernel-version.mk

注意,这里我偷懒直接暴力匹配修改了,现在Lean’s OpenWrt源码使用的内核版本是5.4.158,如果需要修改请自行更换命令里的匹配字符串。

至于该如何选择软件包,esirPG大佬提供了一个说明参考列表,有需求的可以看一下:https://drive.google.com/file/d/1VHB_CoL5LHLYJ39svjWmzJinbg7_Z-Fu/view?usp=sharing

刷写部分

刷写部分的坑其实不比编译部分要少。

设想一下,当我们有一台没有装系统的电脑,我们会怎么给他装系统?

大部分人第一时间想到的是使用WinPE,或者使用启动介质(U盘,DVD等)。没错,软路由也可以这么装,大部分人也都是这么装的。但是,这个方法有着几个不可忽视的问题。

显示器问题

现在大部分的软路由都有 VGA 显示器输出接口,我的甚至有 HDMI 输出接口。然而,当我使用HDMI线连接软路由到显示器后,问题出现了:BIOS 界面无输出,进不去 WinPE。只有正常启动系统后才能看到OpenWrt的命令行界面,系统启动前基本都是屏幕闪一下就没输出了。

我也很快找到了问题所在:BIOS 等界面无法支持 HDMI 信号输出。无奈之下,当时我迅速出去买了一条 VGA 的线,总算能看到熟悉的 BIOS 界面了。

WinPE问题

费了九牛二虎之力总算进了 WinPE,然后新的问题来了:写盘软件打不开!大部分都是缺少 xxxx.dll 啥的,毕竟 WinPE 只是精(残)简(废)版的 Windows,缺什么乱七八糟的依赖都正常。

好不容易换了个PE,写盘软件也能打开了,接着发现分区软件又打不开了!当时不知道什么原因,一打开 DiskGenius 整个PE就会直接黑屏,怎么都救不活。而且毕竟我的软路由才2G内存,这么低的配置WinPE直接卡住我都不觉得奇怪…

另外在写盘时还会碰到一个问题,就是快要结束的时候突然报错。比如使用 physdiskwrite 写盘的时候,眼看快要成功了,突然来一个 write error after xxx bytes...,特别让人抓狂。但是一番搜寻之后,看到论坛里有人说出现这样的情况仍然能成功进系统。我一试,果不其然,一切正常,系统确实是写进去了。至于为什么报错,那我就不得而知了。

外置写盘法

既然用PE写盘这么多问题,那有没有其他方法呢?有!

你只需要在某宝上花二十多买一个mSATA转USB的转接卡,就可以直接把硬盘取下来,插在自己的电脑上写盘了!就像制作启动U盘一样简单!

整个过程二十分钟不到,镜像就写完了。不过还有个问题,如果你就这样启动到系统后,你会在磁盘管理里发现硬盘后面还有一大块都没有分配,而OpenWrt只有小小的512M,这样的话再加装其他软件就不够用了。

解决方法也很简单,在写完镜像之后,立即调整root分区的空间大小,使其撑满整个硬盘空间。但在这里我不推荐用 DiskGenius,因为 DiskGenius 在执行分区扩容时会检查文件系统,如果发现有一丁点的错误就无法扩容。而且DiskGenius是不提供分区修复功能的,何况还是 Ext4 分区。

如果你电脑上有 Linux 环境,那就好办了。正好前几天刚体验了 Manjaro Linux,这不就派上用场了? Linux 有个叫 GParted 的软件(默认没有,需要自己装),这个软件可以很方便的调整 Ext4 甚至 Fat 以及 NTFS 文件系统的大小。只需要在 GParted 里调整 Root 分区,使其撑满硬盘空间就行了。

组网AP部分

本来是没有这个部分的,但是这确实是个小问题,而且跟 OpenWrt 有关系,所以还是记录一下吧(凑字数

我的软路由只有两个网口,不过除了软路由之外,我还有一台斐讯K2作为AP使用。所以就要把这个路由器改成交换机+无线AP。

问题是,我的K2之前也是OpenWrt系统,对于OpenWrt怎么改交换机,在网上找到了不少帖子,似乎每个人方法都有不同点,综合了一下,下面我说一下我的方法吧。

  1. 首先是删除WAN下的所有接口(WAN和WAN6)。

  2. 然后把LAN接口的DHCP关掉(勾选接口设置下面的”忽略此接口”选项,一开始半天没找到)。

  3. 接着在物理设置里把所有接口都勾选上。

  4. 然后修改LAN接口的静态IP地址(也可以干脆把协议改成DHCP,但不推荐这么做)。这个地址有点讲究,比如主路由的网关是 192.168.1.1 ,主路由DHCP地址池的起始地址是192.168.1.100,那么这个静态IP就要设置为这中间的值比较合适。比如192.168.1.2。这样的话就不至于连接到主路由网关的情况下进不去交换机路由器的管理界面。

  5. 修改无线网卡的工作模式为 “接入点AP (WDS)” (好像不改这个也没啥关系,但我还是改了)

  6. (可选)在交换机设置里有两行VLAN的设置,这里把原本对应wan接口的那一行(也就是WAN选择了untagged的那一行)的WAN口关联改为”关”,接着把原本对应lan接口的那一行的WAN口关联改为untagged,保存。这样一来就可以实现所有接口盲插,全都可以作为交换机接口使用。(如果不设置的话只有LAN网口是能作为交换机使用的。)

总结

又写完了一篇折腾文,虽然折腾了这么久但是没有感觉到一点累,这可能就是造轮子的魅力吧。