Dnsmasq - PXE boot using Netboot.xyz

I'm trying to set configure dnsmasq to point dhcp clients to a PXE server running on another machine. Specifically, the PXE server is running Netboot.xyz as a container within docker. The intention is to have the ability to load different bootloaders based on the architecture used by the client.

Example:
legacy 32bit bios = load netboot.xyz.kpxe
UEFI 32/64bit = load netboot.xyz.efi

I found [THIS] regarding Architecture detection within PXE, which explains what integers specify what architecture

the creator of this container has some documentation [HERE] on how to set this up with OpenWRT but their uci commands do not produce the intended results.

uci set dhcp.@dnsmasq[0].dhcp_match=set:bios,60,PXEClient:Arch:00000
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:bios,netboot.xyz.kpxe,,YOURSERVERIP
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi32,60,PXEClient:Arch:00002
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi32,netboot.xyz.efi,,YOURSERVERIP
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi32-1,60,PXEClient:Arch:00006
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi32-1,netboot.xyz.efi,,YOURSERVERIP
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi64,60,PXEClient:Arch:00007
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi64,netboot.xyz.efi,,YOURSERVERIP
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi64-1,60,PXEClient:Arch:00008
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi64-1,netboot.xyz.efi,,YOURSERVERIP
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi64-2,60,PXEClient:Arch:00009
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi64-2,netboot.xyz.efi,,YOURSERVERIP
uci commit
/etc/init.d/dnsmasq restart

It looks like the each pair of commands simply overwrites the previous dhcp_match= and dhcp_boot= settings rather than add to the list. so I just edited /etc/config/dhcp and added the lines manually. (would this be the proper time to use "uci add_list ... "?)

When I attempt to boot a client machine (Virtualbox PXE Client) it just sits at the screen where it's contacting the dhcp server and does nothing.

I'm not sure what other information i should provide. Let me know.

1 Like

It doesn't look right. I would increase the @dnsmasq[x] by 1 for each case.

Not sure if you found the answer but here is what you need.

tee -a /etc/dnsmasq.conf << EOF
dhcp-match=set:ipxeclient,60,IPXEClient*
dhcp-match=set:bios,60,PXEClient:Arch:00000
dhcp-boot=tag:bios,netboot.xyz.kpxe,,192.168.8.1
dhcp-match=set:efi32,60,PXEClient:Arch:00002
dhcp-boot=tag:efi32,netboot.xyz.efi,,192.168.8.1
dhcp-match=set:efi32-1,60,PXEClient:Arch:00006
dhcp-boot=tag:efi32-1,netboot.xyz.efi,,192.168.8.1
dhcp-match=set:efi64,60,PXEClient:Arch:00007
dhcp-boot=tag:efi64,netboot.xyz.efi,,192.168.8.1
dhcp-match=set:efi64-1,60,PXEClient:Arch:00008
dhcp-boot=tag:efi64-1,netboot.xyz.efi,,192.168.8.1
dhcp-match=set:efi64-2,60,PXEClient:Arch:00009
dhcp-boot=tag:efi64-2,netboot.xyz.efi,,192.168.8.1

EOF
uci set dhcp.@dnsmasq[0].dhcp_match=set:bios,60,PXEClient:Arch:00000
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:bios,ipxe/netboot.xyz.kpxe,,192.168.8.1
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi32,60,PXEClient:Arch:00002
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi32,ipxe/netboot.xyz.efi,,192.168.8.1
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi32-1,60,PXEClient:Arch:00006
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi32-1,ipxe/netboot.xyz.efi,,192.168.8.1
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi64,60,PXEClient:Arch:00007
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi64,ipxe/netboot.xyz.efi,,192.168.8.1
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi64-1,60,PXEClient:Arch:00008
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi64-1,ipxe/netboot.xyz.efi,,192.168.8.1
uci set dhcp.@dnsmasq[0].dhcp_match=set:efi64-2,60,PXEClient:Arch:00009
uci set dhcp.@dnsmasq[0].dhcp_boot=tag:efi64-2,ipxe/netboot.xyz.efi,,192.168.8.1
uci commit
/etc/init.d/dnsmasq restart

Change the IP to what your server is.

I was also having the same issue described by OP when setting multiple dhcp-match / dhcp-boot options via uci commands, so I decided to take full control and edit /etc/dnsmasq.conf directly (see https://openwrt.org/docs/guide-user/base-system/dhcp.dnsmasq#etcdnsmasqconf)

I ended up adding this uncomplicated block in there:

###################################
# TFTP Server custom configutation
####################################
enable-tftp
#tftp-root=/root/tftp

# Set tags based on client arch
dhcp-match=set:bios,option:client-arch,0
#dhcp-match=set:efi-i32,option:client-arch,2
#dhcp-match=set:efi-i32,option:client-arch,6
#dhcp-match=set:efi-i64,option:client-arch,7
#dhcp-match=set:efi-i64,option:client-arch,8
#dhcp-match=set:efi-i64,option:client-arch,9
#dhcp-match=set:efi-a32,option:client-arch,10
#dhcp-match=set:efi-a64,option:client-arch,11

# Use kpxe file for legacy bios clients
dhcp-boot=tag:bios,http://boot.netboot.xyz/ipxe/netboot.xyz.kpxe

# Use efi file for anything else (ie: efi clients).
# Notice the negated 'bios' tag
dhcp-boot=tag:!bios,http://boot.netboot.xyz/ipxe/netboot.xyz.efi

That block allows legacy bios clients to boot from http://boot.netboot.xyz/ipxe/netboot.xyz.kpxe and any other non legacy bios clients -UEFI clients basically- to boot from http://boot.netboot.xyz/ipxe/netboot.xyz.efi.

Since the boot files are pulled from the netboot.xyz project via http, I didn't even need to set the tftp-root setting in my dnsmasq.conf.

You can definitely have more fine grained control on which dhcp-boot files get assigned to which client arch tags. In my example above I'm only using the bios tag and its negated form !bios to discriminate, but you could uncomment the other dhcp-match entries and add new dhcp-boot lines to suit your needs.

Please note that if you configure TFTP settings via /etc/dnsmasq.conf then make sure you disable the TFTP settings in LUCI (or its underlying config file /etc/config/dhcp) so there's no conflict between them.

Finally to apply the changes, run:

/etc/init.d/dnsmasq restart

3 Likes

This threw me off at first, but I figured that the second part is not necessary. Editing /etc/dnsmasq.conf is sufficient. Thanks.