# 手动编译OpenWRT19.07并打NAT补丁
# 0x0 环境
使用了一台x86_64的headless的Ubuntu服务器作为实验设备。该服务器由18.04滚至20.04而来,但应该不影响后续环境。
目标设备为WRT32X (opens new window),是工坊使用那台路由器。
# 0x1 安装依赖
OpenWRT的文档可谓是非常丰富(英文的)。
首先,去看OpenWRT官网 (opens new window)。这是所有信息的来源。
左边栏里看一看,嗯,Documentation => Developer guide
,直接点进去。
立马就看到了Build Images Quickstart (opens new window)点进去。
从1. Prerequisites
开始过文档。
按照官网examples of package installations (opens new window)安装依赖
首先在apt前通通
sudo apt update
更新软件列表。
文档里写了Ubuntu对应包的安装命令:
sudo apt install build-essential ccache ecj fastjar file g++ gawk \
gettext git java-propose-classpath libelf-dev libncurses5-dev \
libncursesw5-dev libssl-dev python python2.7-dev python3 unzip wget \
python3-distutils python3-setuptools rsync subversion swig time \
xsltproc zlib1g-dev
运行即可。
1.3
中的内容忽略即可,意思是不要使用root权限执行。
然后获取源码:
git clone https://git.openwrt.org/openwrt/openwrt.git
cd进去cd openwrt
以下命令均在这个目录下执行
我们要编译当前最新的发布版。
# Q: 为什么要编译最新发布版
- opkg软件源只有各大发布版
- 只有内核配置和官方一致才能使用在线软件源
- 发布版“稳定性可保障”“问题可溯源”
切换HEAD到某个发布版。
git checkout v19.07.7
然后更新feeds:
./scripts/feeds update -a
./scripts/feeds install -a
# 0x2 配置目标
接下来配置编译目标。为了和官方版本保持相同的构建参数,需要从官方build bot那里拿到对应的.config
。从这里开始与官方教程不同,这些内容为增补官方教程
对于这块板子,文件url是https://downloads.openwrt.org/releases/19.07.7/targets/mvebu/cortexa9/config.buildinfo
。它在固件下载目录下。找到它的方法很简单:
- 去Download页找到ToH (opens new window),在里面找到设备
- 复制固件链接,如
http://downloads.openwrt.org/releases/19.07.7/targets/mvebu/cortexa9/openwrt-19.07.7-mvebu-cortexa9-linksys_wrt32x-squashfs-factory.img
- 删除最后的文件名后访问
http://downloads.openwrt.org/releases/19.07.7/targets/mvebu/cortexa9/
- 页面最下方即可找到
config.buildinfo
下载该文件并命名为.config
:
curl https://downloads.openwrt.org/releases/19.07.7/targets/mvebu/cortexa9/config.buildinfo -o .config
下载到的.config
是最小化的,需要将其展开:
make defconfig
接下来再次跟随官方教程,筛选编译目标。
# Q: 为什么要下载这个文件
- 不下载这个,直接编译,需要手动配置各种包,比如默认情况下luci都不会包含进去
- 为了不和在线软件源产生冲突
- 保证内核选项与官方一致,才能使用官方源下载内核相关的包
现在从build bot下载的配置文件会编译当前架构的所有设备,我们不需要所以重新只选择我们要的设备:
make menuconfig
进去选择WRT32X。
方向键选择Save
回车保存。再选择Exit
退出。
此时源码的配置就完成了。
# 0x3 首次编译
make -j20
我CPU有20个线程核心。-j
后面的数值按需修改。
实际建议开个screen再编译,避免中途需要断开连接的问题:
screen -S make_openwrt
然后在screen里执行make。想撇后台可以摁CTRL + A + D
去detach。再次来的时候screen -r make_openwrt
即可。
# 0x4 检查 vermagic
只有使用和官方一致的编译配置才能安全的使用在线软件源。opkg因此拥有这么一套检查机制。如果vermagic值不匹配的话就无法以后使用opkg在线安装部分内核模块的包。
vermagic is that 45ed73a630a4bec3328fc33ca1c2e1c2 and is a hash calculated from
- all compilation options related to kernel, and
- names of all kernel modules enabled in the kernel compilation .config (either =y or =m)
首先获取本地编译的vermagic
cat ./build_dir/target-*/linux-*/linux-*/.vermagic
会打引出一串md5,即为当前编译得到的vermagic
再去openwrt官方软件源寻找官方的vermagic。操作方法:
- 去上文提到过的固件url目录那里(自己按需修改)
https://downloads.openwrt.org/releases/19.07.7/targets/mvebu/cortexa9
- 页面下方有
packages
目录,点进去 - 有一个
Packages
文件,打开它。
这个文件就是软件包列表。如果浏览器直接打开了这个文件,那么就搜索kernel
。如果浏览器下载了这个文件,那就本地用工具,搜索kernel
:
任何一个依赖kernel的包都可以说明问题。划线处即为官方vermagic。
现在对比本地编译得到的vermagic和官方值。如果一致,那就继续。不一致请检查上述步骤有无遗漏。
现在已经成功编译得到了和官方镜像配置一致的发布版。
# 0x5 NAT补丁
这里的NAT补丁特指Chion82 (opens new window)与LGA1150 (opens new window)的FullCone补丁,以及相关其它补丁。
# Q: 为什么要这个补丁
- 我们是Zerotier等内网穿透用户群体。一个FullCone NAT能够带来非常舒适的直连体验
当然,从masquerade换到fullcone理论会导致一些安全性问题。也不排除一些鲁棒不佳的socket服务爆炸。
# 概览
可以找到的类似于开始页面的地址是: https://github.com/LGA1150/openwrt-fullconenat
通过阅读README可知,一共需要patch三个地方:
- 一个新的package作为iptables扩展
- 一个luci的patch,用于图形化配置nat类型
- 一个内核patch
如果我们要对内核进行patch,那就必须得自己编译整个系统镜像。其它两个都可以作为扩展进行部分编译。但是既然都要编译了不如全部编译一遍。
# 打内核补丁
注:当前该补丁适用于4.14内核
wget -P target/linux/generic/hack-4.14/ https://raw.githubusercontent.com/coolsnowwolf/lede/master/target/linux/generic/hack-4.14/952-net-conntrack-events-support-multiple-registrant.patch
注:适用于OpenWRT21的5.4内核补丁位于 https://github.com/coolsnowwolf/lede/raw/master/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch
使用命令:
wget -P target/linux/generic/hack-5.4/ https://github.com/coolsnowwolf/lede/raw/master/target/linux/generic/hack-5.4/952-net-conntrack-events-support-multiple-registrant.patch
# 添加fullconenat包
下载源码。这一步直接将源码放进了代码树中。
git clone -b master --single-branch https://github.com/LGA1150/openwrt-fullconenat package/fullconenat
配置编译选项
make menuconfig
在Network -> Firewall -> iptables-mod-fullconenat
这个位置把该选项前面的<>
摁两次空格改为<*>
,意为直接编译进镜像。
使用方向键选择Save
后再选择Exit
退出
# 添加luci补丁
mkdir package/network/config/firewall/patches
wget -P package/network/config/firewall/patches/ https://github.com/LGA1150/fullconenat-fw3-patch/raw/master/fullconenat.patch
pushd feeds/luci
wget -O- https://github.com/LGA1150/fullconenat-fw3-patch/raw/master/luci.patch | git apply
popd
# 绕过vermagic
对内核动了手脚,vermagic已经变了。为了能够继续使用在线软件源,需要欺骗openwrt。
这一步有风险,但是鉴于只添加了nat补丁而没有动其它配置,也就只能这样。
Use at your own risk.
将之前编译得到的.vermagic
复制出来:
cp ./build_dir/target-*/linux-*/linux-*/.vermagic .
修改内核mk中生成vermagic的代码:
sed -i -e 's/^\(.\).*vermagic$/\1cp $(TOPDIR)\/.vermagic $(LINUX_DIR)\/.vermagic/' include/kernel-defaults.mk
再次进行编译。
重做0x3
和0x4
# 0x6 完成
编译得到的系统镜像在./bin/target/*/*/
# 0xf 参考
构建官方一致的镜像: https://openwrt.org/docs/guide-developer/build-system/use-buildsystem#build_system_usage
本地编译的vermagic: https://libremesh.org/development-kernel_vermagic.html
vermagic来源: https://forum.openwrt.org/t/cannot-use-released-kernel-module-for-compile-openwrt/50075/12
bypass vermagic calc: https://oldwiki.archive.openwrt.org/doc/howtobuild/tl-mr3420.build#kmod_compatibility_hack