Rogue DHCP Server

- 4 mins read

It’s the early 2000s. Someone brought their home laptop to work, but there’s only one ethernet port in their office. No problem, they also brought their brand new white plastic Netgear router. Just unplug the desktop, plug it into the router, and… bam, bring down half the network.

Why the Network Died

Computers plugged into the work network get assigned an IP address from the network’s DHCP server. But that little Netgear router? It’s running its own DHCP server. Now when a computer starts up and says:

“Hey, I need an address!”

The Netgear answers first and hands out a completely wrong one. Devices can’t talk to each other, printers vanish, drives don’t mount, and Bob in Accounting can’t check Myspace.

The Rogue in Rogue DHCP

Rogue DHCP servers (and network loops) were the scourge of 2000s small business networks. So I always thought it would be funny to set up an actual Rogue DHCP server, one that used PXE to network boot computers straight into Rogue.

Demonstration of a PXE boot: a VM downloads an image over the network and launches the game Rogue in a terminal.

Steps

Build a Minimal Root Filesystem

Alpine Linux is a great minimal starting point because it’s tiny and fast. You can create a rootfs with just enough to boot and run Rogue:

apk --update --root /root/rogue-init/rootfs --initdb add alpine-base ncurses

Then drop in the Rogue binary (either a statically linked version or one compiled inside a chroot with Alpine’s build-base installed).

Add Rogue as Init

Replace /root/rogue-init/rootfs/init with a script like:

#!/bin/sh
exec /usr/local/bin/rogue

Make sure it’s executable, this runs on boot so the system will start straight into Rogue.

Build the Image

You’ll need to make an initramfs.gz from your custom rootfs:

cd /root/rogue-init/rootfs
find . | cpio -o -H newc | gzip > /srv/tftp/initramfs.gz

You can use your host’s kernel (/boot/vmlinuz) or download one from Alpine.

PXE Setup with dnsmasq

I used dnsmasq with pxelinux with a minimal config:

interface=eth0
port=0
dhcp-range=192.168.2.50,192.168.2.150,12h
dhcp-boot=pxelinux.0
enable-tftp
tftp-root=/srv/tftp

Place pxelinux.0, ldlinux.c32, vmlinuz, and initramfs.gz into /srv/tftp, and create a pxelinux.cfg/default:

DEFAULT rogue
LABEL rogue
 KERNEL vmlinuz
 APPEND initrd=initramfs.gz console=tty1

Boot a VM or Real Machine

Point your test client at the PXE server. You will need to be using legacy BIOS If you wanted to set this up to work with UEFI, you’ll need to switch to bootx64.efi.

Exiting Rogue causes a kernel panic since the kernel sees the init script end with no fallback.

The Dungeon of Debugging

I ran into a few issues along the way getting this setup. First, Alpine only had Rogue in the testing repo, but it was BrogueCE, a modern fork using SDL. Debugging was tricky, as I didn’t initially realize BRogueCE was even running until it gave an error about terminal size.

BrogueCE did have a deprecated text mode, but even after getting an old version compiled it didn’t display on BIOS VGA 80x25. I tried framebuffer vga=791 (and several others), but the SeaBIOS for the VM didn’t support it and I got a black screen.

Eventually, I compiled the latest version of the original Rogue which does fit into the standard 80 columns for VGA text mode. I did have to make some small changes to Rogue’s source to account for changes in more recent ncurses and make sure ncurses was available inside the initrd.

Conclusion

Would plugging this into a modern work place network really unleash chaos and drop everyone into an ASCII dungeon?

It’s unlikely, MAC address filtering will probably prevent the network from even talking to the Rogue DHCP Server. But even if it did, you will need a computer thats already configured to boot from the network with PXE and that can still fallback to a BIOS compatibility.

But it could be cool to put on the network at a LAN party. You could add some other classic text mode games or maybe even a minimal x server and DosBox and some slightly newer stuff.