做OpenWrt开发,首先离不开OpenWrt环境。
如果手上已经有路由器、网关、软路由等刷了OpenWrt的设备,自然非常方便调试。但如果手上的设备正在做主力,显然不合适;加之,为了做开发单独入手一台设备,也并非100%必要。
因此,用QEMU来运行OpenWrt不失为简便且低成本的方式。不过直接运行QEMU很容易踩坑,经常出现各种意想不到的状况。最终,基于先行者们的经验,总算成功跑起了OpenWrt。
以下就总结我摸索出的正确打开方式,以及踩过的那些坑。下文所有命令均在Arch Linux下进行,其他Linux发行版方法类似。
最后修订:2022年6月29日。
QEMU正确的运行方式
第一步:下载OpenWrt磁盘镜像
OpenWrt及其镜像源提供了预先编译好的X86(或X86_64)磁盘镜像,可以直接使用QEMU挂载。
本文采用清华大学TUNA镜像源的OpenWrt 19.07.1 Ext4镜像。下载并解压:
1 |
|
第二步:运行虚拟机
使用QEMU运行OpenWrt,大致遵循以下三个步骤:
- 首先要创建供OpenWrt使用的网络设备,其中常用的有bridge、TAP等。建议使用TAP,设置相对简便,用于调试完全足够。Arch Linux(或其他支持的发行版)下可以直接使用
ip
命令来创建。 - 创建完毕之后,就可以调用QEMU来启动虚拟机、加载磁盘镜像了。调用QEMU时,需要指定恰当的参数来正确打开网络设备和磁盘镜像。
- 运行结束后,也不忘移除刚刚创建的TAP设备。
将下面的代码保存为run_qemu.sh
,它将自动完成上述任务。
1 |
|
创建完毕后,赋予可执行权限,并使用root权限运行(创建网络设备需要root权限):
1 |
|
此时,QEMU的窗口就会打开,窗口中显示内核日志。当内核日志停止滚动时,按回车键即可进入OpenWrt的终端,默认情况下没有密码。
打开浏览器,打开网址http://192.168.1.1
,即可进入OpenWrt的LuCI管理界面,就是熟悉的味道。
参数说明
QEMU运行中,个别特殊的参数值得展开说明。
(a) -drive file=$IMAGE,format=raw,if=virtio
这个参数用来加载磁盘镜像。OpenWrt提供的磁盘镜像并未使用QCOW、VMDK、VDI等格式封装,而是直接对一个指定大小的文件用fdisk
进行分区,这类文件属于“raw”镜像,须显式指定磁盘镜像的类型。
参数中的virtio
表示使用Linux下的虚拟化IO框架VirtIO,具体可参考这篇文章。
(b) --enable-kvm
启用KVM虚拟化,在打开虚拟化功能(如英特尔的Intel Virtualization、AMD的VT-x)的电脑上加快虚拟机运行速度。
尽管OpenWrt是极其轻量级的系统,但如果你不加这个参数,虚拟机就会跑得比乌龟还慢,简直怀疑人生。
加上之后,运行速度立刻飞起,内核日志噌噌刷,就是真机一样的丝滑。
(c) -machine q35
这个参数指定虚拟机的“机型”。通常跑OpenWrt时,更多时候会用上q35
,好处是不用加载额外的驱动,用OpenWrt自带的驱动即可。
(d) 关闭图形界面
如果不想显示QEMU的图形界面,可以加入-nographic
参数,QEMU将以无界面模式(headless mode)运行。
你也可以使用VNC远程桌面来管理,此时也会关闭QEMU的图形界面。使用-vnc :1
参数,则QEMU将默认在192.168.1.101:5901
开启VNC服务器,可以使用兼容的VNC客户端来连接。
我踩的坑
坑0x01
镜像文件不支持
最早我使用的镜像是OpenWrt官方repo提供的21.02.3 combined镜像(上海交大镜像地址),但是该镜像启动到半途,内核日志就一动不动了。切到QEMU的serial模式一看,竟然是kernel panic——原因是无法挂载根文件系统。
于是换成上文提到的老版本镜像,启动成功。如果是开发LuCI的话,老版本也绰绰有余了。
坑0x02
TAP的IP地址
上文run_qemu.sh
脚本中有以下语句,用以给新建的TAP设备指定静态IP地址,防止路由重叠,地址指定为192.168.1.n
(n>1
)。OpenWrt启动后则以192.168.1.1
作为默认网关。
1 |
|
由于我家的光猫网关地址就是192.168.1.1
,这样配置将导致光猫网关被指向虚拟机,因此我想把这里的IP改为其他网段,例如192.168.9.101
。但修改后,无法通过192.168.9.1
来访问OpenWrt管理界面。其他网段亦然。
看来问题出在OpenWrt的默认设置上。玩过OpenWrt的朋友都知道,路由器的网关地址是在OpenWrt中设置的,官方固件默认就是192.168.1.1
(Lean大神的固件则是192.168.20.1
)。如果想换用其它的网关地址,还要使用uci
更改OpenWrt的设置(或者是登录LuCI,修改LAN端口的静态地址,过程略)。
你可以在QEMU的窗口中运行以下命令修改:
1 |
|
然后,同步修改run_qemu.sh
中TAP虚拟网卡的网段:
1 |
|
修改完成后,关闭虚拟机,重新运行run_qemu.sh
,即可以新地址访问OpenWrt。
总结
经过一番折腾之后,基于QEMU的OpenWrt开发环境就搭建好了。我主要用它来练习LuCI的开发,同为x86架构的虚拟机可以直接用来测试电脑上的二进制文件,免去交叉编译的麻烦。现阶段可以省一笔购买设备的费用了。
参考资料
- 使用QEMU搭建OpenWrt开发环境(启动脚本的来源)
- 使用 QEMU 虚拟机安装 OpenWrt 做软路由(OpenWrt 19.07.1版本镜像,以及
-drive
、-vnc
参数的用例) - OpenWrt官方文档:QEMU
- 本文作者: 爱拼安小匠
- 本文链接: https://anclark.github.io/2022/06/14/OpenWRT/OpenWRT_Qemu/
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 3.0(署名-非商用-禁止演绎 3.0) 许可协议。转载请注明出处!