NetBoot Over OpenVPN

February 1, 2011

NetBooting over VPN isn’t anything new or that complicated - just set up a tunnel and use bless with the slightly more elaborate arguments to set the boot parameters, as in Mr. Bombich’s example:

sudo bless --netboot --booter tftp://server.apple.edu/NetBoot/NetBootSP0/NetInstall.nbi/i386/booter \\
--kernel tftp://server.apple.edu/NetBoot/NetBootSP0/NetInstall.nbi/i386/mach.macosx \\
--options "rp=nfs:server.apple.edu:/private/tftpboot/NetBoot/NetBootSP0:NetInstall.nbi/NetInstall-Restore.dmg"

Where the IP of server.apple.edu would be at the other end of the tunnel. The problem is, this requires a working system and isn’t particularly “user firendly”.

Our goal was to give our reseller partners the opportunity to run Apple Service Toolkit. AST is a completely EFI-based system so the amount of data transfered is relatively tiny. An entire MRI session is perhaps a few dozen megabytes, so I knew it should not only be possible, but might actually work quite well.

The only question was how do we make the whole experience seamless - to have customer simply start up the Mac with the N-key and have it work as if on the same subnet as the AST server. The whole solution would consist of:

  • A pfSense (1.2.3) system at both ends. We happened to have a few spare PC Engines Alix.2 boxes so we used those.
  • OpenVPN (2.0.6) as the VPN software (included in pfSense)
  • A Mac mini running 10.6.5 server and AST 1.0.5.

OpenVPN bridging

For DHCP broadcasts to work, we need to bridge the local and remote networks. There’s quite a lot of information on this out there, but I found that most instructions dealt with bridging a specific client to the remote network. What we needed, was a bridged site-to-site connection. Setting it up turned out to be quite a bit easier than I thought, here’s how I did it:

1.

I set up a static IP on the WAN

2.

Configure a new OpenVPN server (VPN > OpenVPN > Server > Add).

  • Protocol: TCP
  • Address pool: to my understanding, this is meaningless in this case, but it made sense to set it to something within the NetBoot server’s subnet, but outside the internal DHCP range.
  • Enable “Use static IPs”. Presumably because we want the internal DHCP server to assign IPs.
  • Authentication method: PKI. This is a prerequisite to “Use static IPs”.
  • Under “Custom options” add “dev tap0”

The other fields should be set according to your own requirements.

When you save all that, pfSense will try to start up the newly configured OpenVPN server. Assuming everything was kosher, this will create a new network interface on the box, called tap0. This is the interface that your VPN clients will connect to and works just like a physical interface.

All that remains is to bridge this new interface with the LAN, where your DHCP and NetBoot live. You could do this through the WebGUI (Interfaces > Assign, etc) and it would work, but only until you reboot the VPN box. This is because pfSense’s start up sequence tries to assign bridges before starting the OpenVPN server. Fortunately, we can circumvent this quite easily.

In WebGUI, open Diagnostics > Edit File and load up /conf/config.xml. Append the following to the <system> element:

<earlyshellcmd>ifconfig bridge0 create</earlyshellcmd>
<earlyshellcmd>ifconfig bridge0 addm vr0 up</earlyshellcmd>
<shellcmd>ifconfig bridge0 addm tap0</shellcmd>

That looks a bit weird at first, but it makes sense, knowing that OpenVPN is initialised between <earlyshellcmd> and <shellcmd>. Save the file and reboot the box to make sure tap0 and bridge0 are still there. vr0 is the LAN port on the Alix.2 board. This concludes our server part of the program.

3.

Over on the client side, it’s almost a mirror image of the server, only a bit more simplified. VPN > OpenVPN > Client > Add:

  • Protocol: TCP
  • Server address: WAN IP of server
  • Server address: empty
  • Interface IP: empty
  • Authentication method: PKI

Once you save that, the tunnel should be up, but broadcasts shouldn’t work yet since we haven’t defined the LAN/TAP bridge. Load up conf/config.xml and do the exact same change as on the server side. Reboot to verify it’s working. The last thing I had to do, was to make sure the IP of the VPN client’s LAN port was within the server-side network. Without this, broadcasts would work, but I couldn’t actually connect to anything on the remote network.

Oh, and make sure you’ve disabled the DHCP server on the LAN port.

4.

After the reboot, connect a machine to the LAN port. You should get an IP on the (now) remote network. Startup Disk should see the NetBoot server on the remote network (the AST NBI in our case). Booting up the machine with the Alt-key should also list the NetBoot server (with recent enough firmware). Booting with the N-key should boot the machine over the VPN connection.

Finishing touches

For extra style points, you can have OpenVPN flash the LED’s on your client (the Alix.2 board in my case), by using the “up” and “down” parameters to OpenVPN (Custom Options field in pfSense), for instance:

up "echo 1 > /dev/led/led2"; down "echo 0 > /dev/led/led2"; up-restart"

The “up-restart” option will run the commands for VPN restarts as well.