UPDATE
After further reading, it seems to me that what I have found is an issue with certain PXE clients and not Mikrotik’s DHCP server implementation. Marking an end code with “FF” is done according to spec as per RFC 2132 section 3.2 and my proposed workaround might cause problems, as every option is properly formatted with its length preceeding the option (RFC 2132 section 2) which, after implementing my workaround, is incorrect.
UPDATE END
Hello,
I would like to post a bugreport as well as workaround for an issue I found in Mikrotik RouterOS. It seems that DHCP server injects additional characters when using “DHCP Options” making certain systems unable to boot using PXE. I will forward this post to Mikrotik support, but I want to make it public for everyone, so if someone is facing similar issue, they will be able to apply my workaround.
Environment
I created a setup for PXE boot using my Mikrotik RB5009UPr+S+ running latest RouterOS 7.16.2. I want to boot legacy BIOS and UEFI machines and I do want to host boot assets on my home NAS running Ubuntu Server 24.04.1 with tftpd-hpa. I used this blog post as a reference: https://dimitrije.website/posts/2024-03-25-homelab-netboot.html
Here is my config:
/ip dhcp-server
add address-pool=<snap>_POOL interface=<snap>_VLAN lease-time=4w2d name=<snap>_DHCP
/ip dhcp-server option
add code=67 name=boot-file-pxe-bios value=s'pxelinux.0'
add code=67 name=boot-file-pxe-uefi value=s'grubnetx64.efi'
/ip dhcp-server option sets
add name=boot-pxe-uefi options=boot-file-pxe-uefi
add name=boot-pxe-bios options=boot-file-pxe-bios
/ip dhcp-server matcher
add address-pool=<snap>_POOL code=60 matching-type=substring name=if-client-arch-is-legacy-then-boot-bios option-set=boot-pxe-bios server=<snap>_DHCP value=\
PXEClient:Arch:00000
/ip dhcp-server network
add address=<snap>.0/24 comment=defconf dhcp-option=boot-file-pxe-uefi dns-server=<snap>.2 domain=pmrlan gateway=<snap>.128 next-server=\
<snap>.69
Some options were cut due to privacy concerns. Careful reader might also notice, that I am using a little different method for detecting BIOS/UEFI boot than described in the blog post, as solution described there didn’t work for me.
Testing
Now, the config above seems to work on most devices, but not all, as there are certain systems that refuse to boot. Here are the results of my testing (all of this is using integrated NICs unless stated otherwise):
- Asus P4C800-E Deluxe - ok
- Asus P8Z77-V legacy - ok
- Dell Precision 3571 UEFI - ok
- VirtualBox BIOS - ok
- VirtualBox UEFI - ok
- Gigabyte H97N-WiFi UEFI - fail (the same result on both integrated NICs)
- Asus B650E-E legacy with chinese Fenvi AQC113 NIC - fail
Problem
After some investigation using Wireshark, it turns out that RouterOS adds “ff” to every payload when using DHCP Options. When using Boot File Name to define boot filename, the same behavior is not observed and it makes B650E-E boot properly, but also doesn’t allow for flexibility of booting both UEFI and legacy BIOS devices.
Workaround
As for the workaround. According to Mikrotik’s documentation, it’s possible to use pure hex values in DHCP Options. By using hex values and appending “00” to hex representing the filename in DHCP, it pushes the “ff” by one octet and makes affected system boot with DHCP Options used and, as such, allows to keep possibility to boot UEFI and legacy BIOS devices.
add code=67 name=boot-file-pxe-bios value=0x7078656c696e75782e3000
add code=67 name=boot-file-pxe-uefi value=0x677275626E65747836342E65666900
Resulting boot packet:
As you can see, “ff” is still there despite using hex values, so without “00” appended, I’ve seen the same behavior as when using strings.
The good thing is, that this workaround should be permanent. Whenever Mikrotik fixes this bug, I assume the config with workaround applied should keep working just fine, but obviously I have no way of verifying that.
Additional note: it’s not required to use Option Matcher which I am using to boot both UEFI and BIOS devices. It’s enough to just switch from “Boot File Name” to “DHCP Options” or “DHCP Options Set” to trigger this bug.
I hope that someone will find this post useful.