编译 Openwrt X86,适配 Hyper-V,百兆满速
首先非常感谢 Soha King 分享的教程,基本整个思路是跟着那篇教程走。实测 100M 光纤,通过 5G Wifi 中继,测速有 90M 左右。
为啥要自己编译 Openwrt?
第一个考虑是安全,别人的固件,用着总觉得有点不那么放心。其实这么说是有点矫情了,人家分享个固件,图你什么呢?人与人之间应该有着基本的信任不是么。
第二个考虑是:Openwrt 编译的包,不能原生支持 Hyper-V,需要加 patch,只能自己编译。能不能用别人加完 patch 编译好的?不能,请参考第一条。
其实这里还有一个疑问:为啥非要用 Hyper-V,VirtualBox 不行么?
刚开始我也这么想的,所以测试时候先装的 VirtualBox。终于跑起来之后,很兴奋,但很快就发现问题,网速测试,只有 20-30M。
难道真的是我的板载网卡垃圾?经过一番研究问题主要出在这:
VirtualBox 模拟了网卡驱动,使得 Openwrt 可以识别网卡,然而这个驱动却并不是那么好用,导致 NAT 性能受限。
经过 N 轮调试,各种换网卡,各种装驱动,最多只能达到 50M 左右,我的百兆宽带就是浪费了一半,这显然不是我想要的。
幸运的是,我搜到了 Soha King 写的教程,Google 搜索排在 openwrt+hyper-v 的第一位,可见点击率一定很高!这教程开篇就提到了 NAT 性能问题,并提供了一个解决方案,不过是 Hyper-V 的,所以我也就从 VirtualBox 转战 Hyper-V。当然不排除 VirtualBox 也有解决办法,说不定 openwrt 里加装合适的网卡驱动即可,不过我是比较懒,也就没有再试了。
编译适配 Hyper-V 的 Openwrt X86
我没有选择 x64 版,原因是有点怀疑 openwrt 到底能不能利用多核和大内存,其实单核已经足以秒杀路由器了,所以还是选用传统的 Generic X86,最大支持单核 CPU 和 900M 内存。
看 average load 就知道,真的是用不到多核,期间有下载有看视频,average load 依旧是 0.00 啊!
OK,回归正题。
准备编译环境:
1 |
sudo apt-get install build-essential openssl unzip libncurses5-dev zlib1g-dev libssl-dev subversion |
Git Clone:
1 |
git clone git://git.openwrt.org/15.05/openwrt.git |
修改文件:
package/kernel/linux/modules/virtual.mk,文件末尾添加 Hyper-V 部分:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# # Hyper-V Drives depends on x86 or x86_64. # define KernelPackage/hyperv-balloon SUBMENU:=$(VIRTUAL_MENU) DEPENDS:=@(TARGET_x86||TARGET_x86_64) TITLE:=Microsoft Hyper-V Balloon Driver KCONFIG:= \ CONFIG_HYPERV_BALLOON \ CONFIG_HYPERVISOR_GUEST=y \ CONFIG_PARAVIRT=n \ CONFIG_HYPERV=y FILES:=$(LINUX_DIR)/drivers/hv/hv_balloon.ko AUTOLOAD:=$(call AutoLoad,06,hv_balloon) endef define KernelPackage/hyperv-balloon/description Microsofot Hyper-V balloon driver. endef $(eval $(call KernelPackage,hyperv-balloon)) define KernelPackage/hyperv-net-vsc SUBMENU:=$(VIRTUAL_MENU) DEPENDS:=@(TARGET_x86||TARGET_x86_64) TITLE:=Microsoft Hyper-V Network Driver KCONFIG:= \ CONFIG_HYPERV_NET \ CONFIG_HYPERVISOR_GUEST=y \ CONFIG_PARAVIRT=n \ CONFIG_HYPERV=y FILES:=$(LINUX_DIR)/drivers/net/hyperv/hv_netvsc.ko AUTOLOAD:=$(call AutoLoad,35,hv_netvsc) endef define KernelPackage/hyperv-net-vsc/description Microsoft Hyper-V Network Driver endef $(eval $(call KernelPackage,hyperv-net-vsc)) define KernelPackage/hyperv-util SUBMENU:=$(VIRTUAL_MENU) DEPENDS:=@(TARGET_x86||TARGET_x86_64) TITLE:=Microsoft Hyper-V Utility Driver KCONFIG:= \ CONFIG_HYPERV_UTILS \ CONFIG_HYPERVISOR_GUEST=y \ CONFIG_PARAVIRT=n \ CONFIG_HYPERV=y FILES:=$(LINUX_DIR)/drivers/hv/hv_util.ko AUTOLOAD:=$(call AutoLoad,10,hv_util) endef define KernelPackage/hyperv-util/description Microsoft Hyper-V Utility Driver endef $(eval $(call KernelPackage,hyperv-util)) # # Hyper-V Storage Drive needs to be in kernel rather than module to load the root fs. # define KernelPackage/hyperv-storage SUBMENU:=$(VIRTUAL_MENU) DEPENDS:=@(TARGET_x86||TARGET_x86_64) +kmod-scsi-core TITLE:=Microsoft Hyper-V Storage Driver KCONFIG:= \ CONFIG_HYPERV_STORAGE=y \ CONFIG_HYPERVISOR_GUEST=y \ CONFIG_PARAVIRT=n \ CONFIG_HYPERV=y FILES:=$(LINUX_DIR)/drivers/scsi/hv_storvsc.ko AUTOLOAD:=$(call AutoLoad,40,hv_storvsc) endef define KernelPackage/hyperv-storage/description Microsoft Hyper-V Storage Driver endef $(eval $(call KernelPackage,hyperv-storage)) |
target/linux/x86/64/config-default 和 target/linux/x86/config-3.18,文件末尾添加:
1 2 3 4 5 6 7 8 |
# CONFIG_HYPERV is not set # CONFIG_HYPERV_BALLOON is not set # CONFIG_HYPERV_NET is not set # CONFIG_HYPERV_STORAGE is not set # CONFIG_HYPERV_UTILS is not set # CONFIG_FB_HYPERV is not set # CONFIG_HID_HYPERV_MOUSE is not set # CONFIG_HYPERV_KEYBOARD is not set |
这就可以了,原教程后面有修改 MakeFile,但我跟着做了 4 次,都是说 MakeFile 文件出错,原因不明,后来我就决定不改。
更新源:
1 |
./scripts/feeds update -a |
安装组件(不然没有 luci):
1 |
./scripts/feeds install -a |
执行:
1 |
make menuconfig |
配置:
Target System 选 x86,subtarget 选 Generic,Target Images 不改,由于没有修改 MakeFile 部分,所以不支持直接输出 Hyper-V 的 VHD 格式,不过没关系,可以用 qemu 转换。
勾选 Hyper-V 选项:
这个应该是最关键的一步,Kernel modules 里的 Virtualization Support 要全部勾选。
替换 Dnsmasq 为 Dnsmasq-Full:
这步也很关键,我刚开始没选,然后安装的时候提示内核不兼容,所以还是一开始就编译上比较稳妥。
其他的就是仁者见仁智者见智了,我不太会改,就基本保持原样。
开始编译:
大概需要一个小时,为了避免 ssh 断线,用 screen 新建了一个会话:
1 2 |
screen -S openwrt make V=s |
因为 VPS 是单核,所以就没加多核的参数。
解决 libiconv 报错:
1 2 3 |
cd build_dir/host/pkg-config-0.29/glib ./configure --enable-iconv=no --with-libiconv=gnu make |
然后回到主目录,重新编译即可通过,似乎是由于有多个 libiconv 导致报错。
解压固件:
编译好的固件,找了半天,原来在这里:
1 2 |
cd bin/x86 gunzip openwrt-x86-generic-Generic-rootfs.tar.gz |
转换为 Hyper-V 镜像:
1 2 |
apt-get install qemu-utils qemu-img convert -f raw -O vpc openwrt-x86-generic-combined-ext4.img openwrt-x86-generic-combined-ext4.vhd |
最后把得到的 vhd 下载下来就可以了,这里就不公开放出来了。
设置 Hyper-V:
Hyper-V 的教程很多,这里就不多啰嗦,主要讲讲网卡的配置吧,点开右侧的虚拟交换机管理器。
新建 WAN:
去掉默认勾选的 “允许管理操作系统共享此网络适配器”。
效果就是:虽然连上了 Wifi,但是会显示无 Internet,这样 HTPC 就不会通过这张网卡来上网,让 Hyper-V 独享这张网卡。
新建 LAN:
同样的,去掉允许操作系统共享的勾。
OK,大功告成,其他就是按照自己的需要进行配置,硬盘镜像选上刚才编译好的,就能进 openwrt。
修改 network:
进入 openwrt 之后,会显示一堆内核日志,要按一下回车,才能出现命令行界面。我刚开始以为是启动失败,汗……
然后这时还上不了网,要修改一下/etc/config/network。
表示 nano 党真的适应不了 vim 的快捷键,我一直记不清到底是 wq 保存退出还是 qw。
把 bridge 注释掉,然后修改 IP 到 2.1 网段,lan 用 eth1,wan 用 eth0,确认 wan 是 DHCP,lan 是 static 就可以了。我不太记得原始文件是怎样的。
1 |
/etc/init.d/network restart |
重启 network,然后分别 ifconfig eth0,ifconfig eth1:
大概是这样子就对了,如果获取不到 IP 地址,说明你还有哪里没设置对,要么是 network 文件,要么是前面的虚拟网卡。
修改 opkg 源:
在/etc/opkg/distfeeds.conf 中,默认除了第一行都是被注释掉的:
把注释全部去掉之后,就可以装 nano 了,可以装 nano 了,可以装 nano 了,重要的事情说三遍!
剩下的就是折腾安装 ss,pdnsd,ipset,dnscrypt-proxy,可以参考我以前写的那篇,基本差不多,pdnsd 在 14.07 的 oldpackages 里可以找到。
最后折腾 luci,我不明白为什么之前编译的时候看不到 luci 的选项,可能是我哪里没有修改导致编译菜单里没有增加 luci。
opkg 安装好 luci 之后,总是不停让我登陆,登陆之后显示 collecting data,然后一直出不来。
最后我尝试重装了 luci-theme-base、luci-lib-ip、libubus-lua,才弄好。
大概就是这些了,目前整体运行状况良好,很期待能稳定运行多久。
就是电费要多交一点,功率 30w 的 HTPC,1 个月大概 1 度电吧。冬天会更省一点,因为根本不用开机箱风扇。
现在是低风速,CPU 大概 55 度上下,已经很不错了,毕竟 CPU 是被动散热的。夏天如果不开风扇,高负荷就是 60 度的样子。很期待冬天不开风扇是不是可以到 40 度哈哈。
最后上一张 Overview 的截图,我分配了 1G 内存,不过只能认 900M 左右。