Skip to content

Instantly share code, notes, and snippets.

@sudocurse
Last active May 12, 2020 12:40
Show Gist options
  • Save sudocurse/2cd343a2125c4bc69b618ae7fcad536c to your computer and use it in GitHub Desktop.
Save sudocurse/2cd343a2125c4bc69b618ae7fcad536c to your computer and use it in GitHub Desktop.
pxe + webproc without fucking up your local dhcp
#!/bin/bash
# Sets up a standalone proxyDHCP server, to PXE netboot, as a container made
# from https://github.com/jpillora/webproc to get a web ui on port 8080 to edit
# conf + monitor logs. You could probably swap out the container and the config
# and most of this script would still be good.
#
# The actual container used is https://hub.docker.com/r/jpillora/dnsmasq
# There's a screenshot on that page.
#
# Notes:
# * This assumes firewalls and network configs are all fine-- same physical network,
# or VM in bridge mode, etc
# * i should note that i really don't understand chainloading or ipxe yet so no idea if that works
# * It's host-networked so it'll be running on http://host:8080. Between that and the basicauth,
# probably not great for production use?
# * Could probably do more work to link it up as a systemctl service.
# * You can exec to /bin/ash (it's alpine base), strace in a separate container, whatever other docker tricks
# parameters
bios_file=/FULL/PATH/TO/undionly.kpxe
uefi_file=/FULL/PATH/TO/ipxe.efi
chainload=/FULL/PATH/TO/something.img
proxy_if=YOUR_INTERFACE_HERE
# creds for the web wrapper for logs and config
web_user=USERNAME
web_pass=PASSWORD
#where config and files will be copied to
main_dir=/opt
# create files to be mounted
mkdir -p $main_dir/tftpboot
cp $bios_file $main_dir/tftpboot/
cp $uefi_file $main_dir/tftpboot/
cp $chainload $main_dir/tftpboot/
mkdir -p $main_dir
#write config file
gw=$(route -n | grep 'UG[ \t]' | awk '{print $2}')
cat << EOF > $main_dir/dnsmasq.conf
#turn off dns
port=0
#probably doesn't matter
no-resolv
#set dhcp server to proxyDHCP mode
dhcp-range=$gw,proxy
pxe-prompt=" "
# DHCP offer doesnt give IP but points to tftp
# and boot file
enable-tftp
tftp-root=/var/lib/tftpboot
# Check architecture so we know whether to send legacy or UEFI
dhcp-vendorclass=set:bios,PXEClient:Arch:00000:UNDI:002001
dhcp-boot=tag:bios,$(basename bios_file)
dhcp-vendorclass=set:efi,PXEClient:Arch:00007:UNDI:003016
dhcp-boot=tag:efi,$(basename uefi_file)
# Setup a secondary boot file- once iPXE has booted
# it'll look for another file to chainload
dhcp-userclass=set:ipxe,iPXE
dhcp-match=set:ipxe,175
dhcp-boot=tag:ipxe,$(basename $chainload)
log-queries
log-async
log-dhcp
EOF
docker pull jpillora/dnsmasq
echo "Asking for root to start server as a privileged container"
sudo docker run --name dnsmasq \
-d --privileged --net=host \
-v $main_dir/tftpboot:/var/lib/tftpboot \
-v $main_dir/dnsmasq.conf:/etc/dnsmasq.conf \
-e HTTP_USER=$web_user -e HTTP_PASS=$web_pass \
--restart always jpillora/dnsmasq
@sudocurse
Copy link
Author

sudocurse commented Apr 19, 2020

In theory, you should be able to remove --net=host if you can do the following:

  • put the host's ip address into the dhcp-boot field as the server-name parameter (if this is done dynamically you'll have to restart the dnsmasq daemon)
  • Set up a user-defined bridge, setup the forwarding for broadcast, port 4011 for proxyDHCP, and 69 for TFTP. As far as I know you can't tell the client to use alternate ports (although TFTP does have alternate port ranges for post-initial connections).

@sudocurse
Copy link
Author

sudocurse commented May 12, 2020

fyi this doesn't work on macos using docker for mac because of the way networking is set up (in a VM with a separate ip with the mac daemon doing NAT work). if you can get host networking to work with it somehow you just need to change a couple things (route -n becomes netstat -rn, and some clever grepping in the rest of that line (i think you could get away with grep UG | grep $proxy_if)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment