编译OpenWrt

前言

网上有大量的OpenWrt固件供用户下载使用。这类固件旨在满足广泛用户群体的需求,因此可能包含了一些并非所有用户都会用到的功能或组件。此外,考虑到最近曝光的XZ后门事件,这让人们更加警惕第三方编译固件的安全性,毕竟无法完全确信他人编译的固件是否完全安全无虞。因此,为了确保设备的安全性和个性化需求,自行编译适合自己使用的OpenWrt固件不失为一个更为可靠的选择。

准备

  1. Linux系统,这里使用 Ubuntu 20.04 LTS x64

    VMware安装 Ubuntu

    创建虚拟机:

    兼容模式自选;

    稍后安装操作系统(之后用ISO安装);

    Linux–Ubuntu 64位;

    磁盘 80~100 GB,拆分成多个文件;

    自定义硬件注意:

    网络选桥接,便于 ssh,处理器只要总线程少于自己电脑的线程就可以,看看这篇CSDN

    在虚拟机设置-CD/DVD里面-选择下载好的Ubuntu镜像

    启动虚拟机开始安装Ubuntu

    时区选上海Shanghai 其他没什么

  2. 源码选择

    1. LEDE

      缺乏我所需的一些功能,由于使用人数众多,项目的开发重点往往是保持代码的稳定性

    2. Lienol

      与我所编译的插件冲突,导致一直编译失败

    3. ImmortalWrt(推荐)

      官方的软件源维护很好,体验无限接近主线的一个OpenWrt分支/变体,主要针对墙内用户体验做了很多工作。

    4. OpenWrt官方

      精简干净

开始编译

Ubuntu 全局上网,不要使用 root 用户编译

更新包索引文件、安装新版本包

1
2
sudo apt update -y
sudo apt full-upgrade -y

安装依赖:

下面的是 ImmortalWrt 的,比LEDE的全

不要使用 ImmortalWrt 项目里面的一键脚本,会把 Ubuntu 的软件源改成华为的

1
2
3
4
5
6
7
8
sudo apt install -y ack antlr3 asciidoc autoconf automake autopoint binutils bison build-essential \
bzip2 ccache clang cmake cpio curl device-tree-compiler ecj fastjar flex gawk gettext gcc-multilib \
g++-multilib git gnutls-dev gperf haveged help2man intltool lib32gcc-s1 libc6-dev-i386 libelf-dev \
libglib2.0-dev libgmp3-dev libltdl-dev libmpc-dev libmpfr-dev libncurses5-dev libncursesw5 \
libncursesw5-dev libpython3-dev libreadline-dev libssl-dev libtool lld llvm lrzsz mkisofs msmtp \
nano ninja-build p7zip p7zip-full patch pkgconf python2.7 python3 python3-pip python3-ply \
python3-docutils python3-pyelftools qemu-utils re2c rsync scons squashfs-tools subversion swig \
texinfo uglifyjs upx-ucl unzip vim wget xmlto xxd zlib1g-dev zstd

下载源代码

1
git clone -b <branch> --single-branch --filter=blob:none https://github.com/immortalwrt/immortalwrt

示例:下载 21.02 版本(iptables 最后一版)

1
git clone -b openwrt-23.05  --single-branch --filter=blob:none https://github.com/immortalwrt/immortalwrt

进入 immortalwrt 文件夹

1
cd immortalwrt

缝合一些其他插件

按照下面格式添加到根目录 feeds.conf.default 文件

1
src-git <文件夹名,不要重复> https://xx.xx/xxx
1
2
3
4
5
- [fw876/helloworld](https://github.com/fw876/helloworld) 科学上网插件集
- 来自神秘网友 kenzok8(ssrp、passwall、openclash 等)
  * [kenzok8/openwrt-packages](https://github.com/kenzok8/openwrt-packages)
  * [kenzok8/small](https://github.com/kenzok8/small)
  * [kenzok8/small-package](https://github.com/kenzok8/small-package) 最新源

添加后执行以下命令下载安装软件

1
./scripts/feeds update -a

创建软链接到 package/feeds 目录(package目录下的软件会被 make menuconfig 识别)

1
./scripts/feeds install -a

[./scripts/feeds 的用法见此处](# ./scripts/feeds 的用法)

添加 Mosdns 源码

GitHub项目

1
2
3
    # (OpenWrt-21.02 及更旧版本)更新golang 1.20.x 或最新版本
rm -rf feeds/packages/lang/golang
git clone https://github.com/sbwml/packages_lang_golang -b 20.x feeds/packages/lang/golang
1
2
3
4
    # (openwrt-22.03 & master)remove v2ray-geodata package from feeds 
rm -rf feeds/packages/net/v2ray-geodata
git clone https://github.com/sbwml/luci-app-mosdns -b v5 package/mosdns
git clone https://github.com/sbwml/v2ray-geodata package/v2ray-geodata

图形化配置OpenWRT组件:[翻译见此处](# 编译配置选项翻译)

[注意] 执行下述命令启动图形化配置界面之前,把“终端”命令行窗口最大化。如果窗口太小可能会导致启动失败!

1
make menuconfig

*表示编译进固件里面 M表示只编译但不写到固件里面去 (空) 留空表示不做任何操作

Target Images(目标系统)

ext4,efi不要,vmdk 安装到VMware用

squashfs镜像不支持扩展

谨慎使用带有rootfs的镜像,没有引导,需要自己折腾

(16) Kernel partition size (in MB)

(400) Root filesystem partition size (in MB)

Base system(基本系统)

dnsmasq-full—> 选满(HAVE不选), 取消dnsmasq, dnsmasq-dhcpv6两个选项,否则编译会出差!!!

下翻选firewall4 不选firewall。

Extra packages (额外包)

autocore 选

automount 不 USB 文件共享

autoautosamba 不 Samba 多媒体共享

ipv6helper IPV6选

Kernel modules(内核模块)

Network Devices

只留了e1000、ifb (虚拟网卡,记得eqos、qos采用的就是这个,方便对同一网口进行上下行限速)、igc(i225) 、macvlan、vmxnet3 (有一些把USB去掉之后可以取消)

Network Support——kmod-tun 选(openclash依赖,最后确认一下,可能会被自动取消掉)

SPI / Sound / USB /Video Support / Wireless Drivers都可以取消

Network

——odhcp6c和odhcpd-ipv6only(这两个应该会自动选上)IPv6选

—>Firewall —> ip6tables-extra 和 ip6tables-mod-nat IPv6选

—>SSH—> openssh-sftp-server 选 我不选这个无法ssh连接,后面也可以加上

LuCI

—> Collections—> luci 选

—> Modules —>Translations记得选简中

​ luci-compat 选(OpenClash依赖)

—>Applications —-根据自己的需求来选择(第一次编译少选一些,passwall的配置用动,我这很容易报错),可以看看恩山的帖子

   这几个比较绕
   上网时间控制:luci-app-timecontrol
   访问限制:luci-app-control-webrestriction
   网址过滤:luci-app-control-weburl
   定时唤醒:luci-app-control-timewol

—>Themes—>luci-theme-argon 选

保存并退出到 Terminal

下载 dl 库

-j 后面是线程数

1
make download -j8 V=s

开始编译固件

第一次编译推荐用单线程

1
make V=s -j1

弄完就可以去睡觉了,大概需要六、七个小时

编译输出路径: /bin/targets

二次编译(适用于不更改配置功能和插件,仅升级)

1
2
3
cd immortalwrt

git pull
1
2
3
4
5
make defconfig

make download -j8 V=s

make V=s -j$(nproc)

杂技巧

一些配置

  1. 更改LAN口的默认IP地址
    package/base-files/files/bin/config_generate 165 行

  2. 修改默认主题为 argone(ImmortalWrt不用改)

    1
    sed -i 's/luci-theme-bootstrap/luci-theme-argone/g' feeds/luci/collections/luci/Makefile
  3. 更改 固件版本信息

    1
    sed -i "s/OpenWrt /$(date +%Y.%m.%d) 2022/xx/xx /g" package/lean/default-settings/files/zzz-default-settings
  4. 添加自定义插件

    原理是把插件源码放到 package 目录下,编译时会自动遍历

    示例:

    - 安装最新 argon 主题 # openwrt 源码

    cd package

    git clone https://github.com/jerrykuku/luci-theme-argon.git # Lean 源码

    cd /package/feeds/luci

    rm -rf luci-theme-argon

    git clone -b 18.06 https://github.com/jerrykuku/luci-theme-argon.git

  5. 修改 SSH 登陆欢迎信息

    修改文件/package/base-files/files/etc/banner

    可以在此处定制自己的样式

如果编译OpenWrt原版

切换最新稳定分支:

1
2
3
4
5
git branch -a

git tag

git checkout v22.03

[说明] 这一步很重要,切换稳定分支,编译的版本是经过充分验证的稳定版本,不容易出现莫名其妙的bug, 减少很多白折腾。切身教训,供参考。

管理 Web 管理上面 APP 出现的菜单位置()

比如把一个出现在“服务”菜单里的app改到“网络”里,以NFT-QOS为例:

进入package下面的luci-app-nft-qos/controller,看到nft-qos.lua文件,打开看到:

entry({“admin”, “services”, “nft-qos”}, cbi(“nft-qos/nft-qos”),

上面的”services”就是“服务”,修改为”network”,这个app就会改变到“网络”菜单里了。

———某些比较复杂关系的app只修改这一处会无法运行,是因为多个函数使用了这个路径,需要逐一修改。luasrc下面所有文件都要打开查找一遍,凡是存在“services”这个一路径的(或者是admin/services/xxx这样的路径的),通通需要替换成“network”才算完成。

lean的defaultsetting有这些lua重分配命令,但是同样存在上面的问题,所以必须从源码本身去修改。

MentoHUST(锐捷认证)

用这个GitHub的

文件主体可以用GitHub的,luci用immortalwrt可以完美使用

重新编译

make clean 仅仅是清除之前编译的可执行文件及配置文件,比如bin路径下面的文件,config配置文件不会清除。

make distclean 清除所有生成的文件,连feeds也会干掉,只留下git clone完成时候的初始状态。

更改openwrt后台web登陆用户名方法

修改/etc/passwd

root:x:0:0:root:/root:/bin/ash修改为username:x:0:0:root:/root:/bin/ash

限速的配置

详见恩山的帖子

最好有以下依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        tc-tiny                                      重要

Kernel modules--->Network Support:
kmod-sched tc sfq 随机公平排队 相关 ,查看固件是否支持sfq ,终端命令:opkg files kmod-sched|grep sfq
kmod-sched-cake 流量智能队列管理(QOS)
kmod-sched-connmark
kmod-sched-core tc 限速核心
kmod-sched-ipset

Kernel modules--->Network Devices:
kmod-ifb 虚拟网卡,记得eqos、qos采用的就是这个,方便对同一网口进行上下行限速

Network--->Firewall:
iptables-mod-iprange 对IP段进行筛选(过滤)
iptables-mod-nat-extra 流量智能队列管理(QOS)

编译配置选项翻译

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
OpenWrtConfiguration【OpenWrt配置】
TargetSystem () ---> 目标系统()
Subtarget() ---> 子目标()
TargetProfile () --->目标配置文件(通用)
TargetImages ---> 保存目标镜像的格式
Enableexperimental features by default ---> 默认情况下启用实验功能
Globalbuild settings ---> 全局构建设置
Advancedconfiguration options (for developers) ---- 高级配置选项(适用于开发人员)
Buildthe OpenWrt Image Builder 构建OpenWrt图像生成器
Buildthe OpenWrt SDK构建OpenWrt SDK
Packagethe OpenWrt-based Toolchain打包基于OpenWrt的工具链
Imageconfiguration --->图像配置
Basesystem ---> 基本系统
Administration---> 管理
BootLoaders --->引导加载程序
Development---> 开发
Extrapackages ---> 额外包
Firmware--->固件
Fonts--->字体
Kernelmodules ---> 内核模块
Languages--->语言
Libraries---> 图书馆
LuCI---> LuCI 软件包
Mail--->邮件
Multimedia--->多媒体
Network--->网络
Sound---> 声音
Utilities--->实用程序
Xorg--->Xorg

./scripts/feeds 的用法

更新包列表:./scripts/feeds update -a
集成到menuconfig:./scripts/feeds install -a

此外可以直接输入./scripts/feeds查看其用法,下面简略翻译了一下用法(水平有限,若有错误欢迎指正):

用法: ./scripts/feeds <命令> [参数]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
命令:
list [参数]: 列出所有源及其内容和修订版本(如果已经安装)
参数:
-s :            源名称及其URL列表.
-r <源名称>:    特定源提供的包列表.
-d <分隔符>:    指定区分不同行的分隔符 (默认: 空格)
install [参数] <包>: 安装一个包
参数:
-a :            安装所有源提供的包或者特定源提供的包(使用-p参数).
-p <源名称>:    指定安装包的时候要使用的源.
-d <y|m|n>:     为新安装的软件包设置默认值.
search [参数] <子字符串>: 搜索一个包
参数:
-r <源名称>:    只从该源搜索
uninstall -a|<包>: 卸载一个包
参数:
-a :            卸载所有包.
update -a|<源名(一个或多个)>: 更新文件feeds.conf里的源提供的包列表.
参数:
-a :            更新feeds.conf里所有源提供的包列表. 否则只更新特定源的.
-i :            只重建索引列表. 不升级源.

End

从2024年6月22日一直到7月2日,我尝试编译了多种不同的源码,有的编译失败,有的则无法满足我的需求,迄今为止最为折腾的经历

参考文章

  1. https://github.com/immortalwrt/immortalwrt
  2. https://github.com/coolsnowwolf/lede
  3. https://github.com/Lienol/openwrt
  4. https://shimo.im/docs/gYjt9QVr8T9Vhv9X/read
  5. https://www.cnblogs.com/kn-zheng/p/17340151.html
  6. https://www.right.com.cn/forum/thread-3682029-1-1.html
  7. https://sspai.com/post/61463
  8. https://www.cnblogs.com/kn-zheng/p/17340776.html
  9. https://www.right.com.cn/forum/thread-469400-1-1.html
  10. https://eagmi.com/categories/openwrt%E7%B3%BB%E5%88%97/
  11. https://github.com/immortalwrt/immortalwrt/discussions/1109