0%

用iPXE+软路由打造自己的网络引导方案——netboot.lan

什么是iPXE? iPXE是一款强大的开源网络引导固件。支持通过刷固件的方式替换掉网卡原有的PXE ROM,也可以通过UEFI或者BIOS从编译好的二进制文件引导。https://ipxe.org

基于iPXE,netboot.xyz已经做出了完整的一套网络引导菜单,但是一方面要求客户端要有Internet访问,另一方面由于启动镜像需要从Internet上面下载,启动速度往往不够快。

于是想到仿(抄)照(袭)netboot.xyz在软路由上搭建一个netboot.lan,把自己常用的启动镜像预先下载好放在软路由的web服务器上,这样内网设备直接从路由器上下载启动镜像就会快很多。不常用的还是由netboot.xyz来提供就好了(可以通过在ipxe脚本里增加一个菜单,选中后执行chain --autofree http://boot.netboot.xyz/ 就能实现)

安利我的个人源

如果你实在是太懒,不想打包,可以从我的个人源安装上述软件包(x
配置方法见 https://edward_p.keybase.pub/website

效果展示

启动Arch ISO

启动某增强版PE,挂载samba,挂载iso,然后安装Windows 10

该PE镜像由aioboot.com提供,下载链接:Google Drive, Yandex Disk, Mega, Fshare

加载 netboot.xyz

Note:当前菜单里面是直接chain http://boot.netboot.xyz,所以使用的iPXE仍然是我们自己编译的iPXE,所以没有netboot.xyz的证书,无法使用签名验证,使用时需要关掉签名验证; 或者是通过iPXE Shell执行chain https://boot.netboot.xyz/ipxe/netboot.xyz.efi 加载netboot.xyz编译的二进制,这样就能使用签名验证了。回到netboot.lan需执行chain --autofree http://netboot.lan/menu.ipxe

通过PXE引导iPXE

细心的你可能发现了,上面三次引导都是先启动PXE,由PXE引导iPXE,then boom! 因为只有部分网卡(大多数为台式机网卡)支持刷iPXE固件,如果把ipxe二进制文件写进磁盘或者U盘进行引导又好像失去了网络引导的初心。

编译带有内嵌脚本的iPXE

如果你用过netboot.xyz编译给你的iPXE,你就知道在执行完dhcp之后,iPXE就自动加载netboot.xyz的引导菜单了。这就要用到iPXE提供的内嵌脚本功能,也就是在make时加上EMBED=/path/to/script.ipxe 参考链接
这要就能把你的脚本编译成内嵌脚本,在iPXE加载时会自动执行。

我的设想是,将下面这样的内嵌脚本编译进iPXE

1
2
3
4
#!ipxe

dhcp || shell
chain --autofree http://netboot.lan/menu.ipxe || shell

这样每次加载ipxe之后就会自动去执行脚本http://netboot.lan/menu.ipxe

然后我们把菜单放到web服务器上,也便于后期的维护和修改,就像netboot.xyz做的那样。netboot.lan是一个本地域名,用你的dnsmasq把它解析到你路由器的LAN IP就好了

你说啥?PKGBUILD?

写一个dnsmasq配置用于PXE加载iPXE

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
/etc/dnsmasq.d/10-tftpboot.conf
---
# Enable tftp
enable-tftp
tftp-root=/srv/tftp

# Disable re-use of the DHCP servername and filename fields as extra
# option space. That's to avoid confusing some old or broken DHCP clients.
dhcp-no-override

# Log lots of extra information about DHCP transactions.
log-dhcp

# Inspect the PXEClient Type and set the tag
# Acording to [RFC4578]:
# Type Architecture Name
# ---- -----------------
# 0 Intel x86PC
# 1 NEC/PC98
# 2 EFI Itanium
# 3 DEC Alpha
# 4 Arc x86
# 5 Intel Lean Client
# 6 EFI IA32
# 7 EFI BC
# 8 EFI Xscale
# 9 EFI x86-64

# Match platform & Set tags to client
dhcp-match=set:ipxe,175 #match iPXE to break PXE loop
dhcp-match=set:bios,option:client-arch,0
dhcp-match=set:efibc,option:client-arch,7
dhcp-match=set:efi-ia32,option:client-arch,6
dhcp-match=set:efi-x86_64,option:client-arch,9

# Set boot file by tags
dhcp-boot=tag:!ipxe,tag:bios,boot/ipxe-netboot.lan.pxe
dhcp-boot=tag:!ipxe,tag:efibc,boot/ipxe-netboot.lan-x86_64.efi
dhcp-boot=tag:!ipxe,tag:efi-ia32,boot/ipxe-netboot.lan-i386.efi
dhcp-boot=tag:!ipxe,tag:efi-x86_64,boot/ipxe-netboot.lan-x86_64.efi

# Set netboot.lan to 192.168.123.1
# Because our default chain is http://netboot.lan/menu.ipxe
address=/netboot.lan/192.168.123.1

没错,PXE加载引导文件是通过tftp协议的,太垃圾了,不过没关系,一旦iPXE加载了,就爽了。

上述配置用dnsmasq开启了一个tftp服务器,根目录为/srv/tftp; 指定了域名netboot.lan解析到192.168.123.1; 然后根据匹配的客户端类型指定不同的引导文件。(只匹配了常见架构而已。因为ipxe也兼容PXE,匹配ipxe是为了防止iPXE无限循环加载)

既然已经打包安装了ipxe-git-netboot.lan,那么就把ipxe引导文件通过软链接弄到/srv/tftp/boot下面吧:

1
2
3
mkdir /srv/tftp/boot
cd /srv/tftp/boot
ln -s /usr/lib/ipxe-netboot.lan/* .

搭建netboot.lan的Web服务器

我个人是比较喜欢nginx啦:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/etc/nginx/sites-enabled/netboot.lan
---
server {
listen 80;
server_name netboot.lan;

#access_log logs/host.access.log main;

autoindex on;

location / {
root /srv/http/netboot.lan;
index index.html index.htm;
location ~ .*\.ipxe$ {
add_header Content-Type text/plain;
}
}

}

然后剩下的工作就是在/srv/http/netboot.lan下面写ipxe脚本啦。

可以用我这套模板,仅实现了上面的展示内容(欢迎PR?):

1
2
git clone https://github.com/archwrt/netboot.lan.git /srv/http/netboot.lan
cd /srv/http/netboot.lan

你可能看到目录下还有wimbootshellx64_v2.efi

  • 其中 wimboot 是启动WinPE的wim镜像必须要用到的工具,可以从AUR安装wimboot-git 解决
  • shellx64_v2.efi 则是我自己想要而已(可选)可从AUR安装efi-shell-git

获取Arch Linux启动镜像

通过rsync从tuna源拉取最新的Arch Linux启动镜像,我写了个脚本放在archlinux目录下面,所以可以直接:

1
2
cd /srv/http/netboot.lan/archlinux
./sync

关于Windows PE

上面已经说了你需要wimboot,然后你还需要:

  • boot/bcd
  • boot/boot.sdi
  • bootmgr
  • sources/boot.wim (废话?)

目录大概长这样:

1
2
3
4
5
6
7
8
9
10
11
/srv/http/netboot.lan/windows
├── Win10_1809_English_x64.iso
└── winpe
└── win10
└── $arch (x64 or x86)
├── boot
│   ├── bcd
│   └── boot.sdi
├── bootmgr
└── sources
└── boot.wim

上述文件结构在引导的时候设置LOCATIONwindows/winpe/win10即可,架构$arch是ipxe脚本自动检测的。

然后安装镜像iso也可以放这里,但是你必须把/srv/http/netboot.lan/windows这个目录通过samba共享出来,PE只支持samba,垃圾!samba服务器的配置参考ArchWiki,这里就不赘述了。

PE引导之后,执行完wpeinit之后,应该就有网络了,然后参考上面的视频吧,不想多说了?

需要注意的是,如果是从windows安装盘里面取出来的PE,应该是不能挂载ISO的,更没有explorer++这种东西了(更垃圾)

感谢

感谢iPXE提供这么强大的引导工具。

感谢netboot.xyz提供脚本和菜单抄?(大雾