Sunday 7 October 2012

Netbooting NetBSD in KVM

So, I feel the need to netboot various OSes again. Because I can.

Output to serial is most convenient, my MIPS box is serial only, and besides I have no space for a bunch of extra monitors.

In the IA32 case, the (very very nice, though old) Diskless NetBSD howto directs me to use "pxeboot_ia32_com0.bin".

Problem #1: since NetBSD 4 or so, this isn't in base.tgz anymore.

David Laight points out that it can be created like so using the netbsd installboot(8) command. Though I have no NetBSD yet.

Ah well. I'll boot a more normal NetBSD on KVM and create that, then. Quick DHCPD setup:

subnet 10.50.1.0 netmask 255.255.255.0 {
    range 10.50.1.200 10.50.1.250;
}
host kvm-netbsd-ia32 {
  hardware ethernet 22:22:22:22:00:00;
  next-server 10.50.1.1;                        # TFTP / NFS host
  filename "/netbsd-5/pxeboot_ia32.bin";        # Path on TFTP server

  option root-path "/storage/nfs/ia32/netbsd-5.1.2/root"; # Path on NFS server
                                                          # FreeBSD pxe can use IP:path here, I believe, NetBSD just uses next-server.
}

... not so fast.

ISC DHCPD, current KVM's iPXE netboot firmware and NetBSD's pxeboot doesn't like each other.

* iPXE sends a DHCP request with dhcp_client_identifier (option 61) set to 01-ethernet mac address, loads pxeboot_ia32.bin from tftp and runs it.
* pxeboot_ia32.bin sends a simpler DHCP request without dhcp_client_identifier via PXE_UDP_WRITE. pxeboot_ia32.bin takes care to use the lease it knows about from the PXE environment as source IP, it just wants to ask for some more options.
* ISC DHCPD wants to assign a new address, since this apparently is another client (no dhcp_client_identifier), and assigns that as unicast destination.
* iPXE ignores the return unicast packet apparently sent to somebody else entirely.
* pxeboot_ia32.bin gets no response and gives up.

ISC DHCPD has a special case for BOOTP clients, and will give out an old lease if the hardware address matches even though they don't send any client-id. But we aren't BOOTP, we're just fragile followup-DHCP-in-PXE.

The least icky way out here seems to be patching DHCPD to ignore dhcp_client_identifier mismatches. (CMU DHCPD has a runtime option for it, btw) But oh, the tentacles, ISC source isn't known for its sanity...

hack for isc dhcp 4.2.4

So at this point I'm doing a traditional
  pxe rom (iPXE 1.0 as shipped with modern qemu/kvm, or whatever PXE rom my old VIA Mini-ITX is running)
  => tftp loads pxeboot second stage
  => pxeboot loads kernel via simplified nfs
  => kernel boots a nfsroot system

The smart & modern way is of course to load the netbsd kernel directly from iPXE. But I'm betting that's too easy to be any fun.


Anyway, qemu-kvm in ubuntu precise has fun bugs that doesn't let the NetBSD kernel find any PCI devices. Like, for instance, the network card. So the boot stops with netboot interface not found.

Fixed in current debian and upstream qemu. A rebuild of QEMU seems to be in order.

apt-get source qemu-kvm
apt-get build-dep qemu-kvm
cd qemu-kvm-1.0+noroms/debian/patches
wget -O 'pci-fix-corrupted-pci-conf-index-register-by-unaligned-write.patch' "http://git.qemu.org/?p=qemu.git;a=commitdiff_plain;h=cdde6ffc27517bdf069734fbc5693ce2b14edc75"
echo pci-fix-corrupted-pci-conf-index-register-by-unaligned-write.patch >> series
cd ..
dch -i
cd ..
dpkg-buildpackage -b -uc
cd ..
dpkg -i qemu-kvm_1.0+noroms-0ubuntu14.2eib1_amd64.deb qemu-utils_1.0+noroms-0ubuntu14.2eib1_amd64.deb qemu-common_1.0+noroms-0ubuntu14.2eib1_all.deb

et voila!

Whee, I have a working NetBSD!
Current invocation: kvm -boot n -localtime -net nic,vlan=0,macaddr=22:22:22:22:00:00 -net tap,vlan=0,ifname=tap0,script=no,downscript=no

Now then, in netbsd (After changing root's shell to /bin/sh instead of the traditonal csh abomination)

cd /usr/mdec
cp ./pxeboot_ia32.bin ./pxeboot_ia32_com0.bin
installboot -e -oconsole=com0 -ospeed=0 ./pxeboot_ia32_com0.bin

So far, so good. Drop our new binary in, and boot kvm with no VGA and a serial console:

kvm -boot n -localtime -net nic,vlan=0,macaddr=22:22:22:22:00:00 -net tap,vlan=0,ifname=tap0,script=no,downscript=no -vga none -nographic

knan@sarevok:/storage/current/netboot$ ./kvm-ia32-netbsd.sh

>> NetBSD/x86 PXE Boot, Revision 5.1 (from NetBSD 5.1.2)
>> Memory: 623/391904 k
Press return to boot now, any other key for boot menu
Starting in 0 seconds.    
PXE BIOS Version 2.1
Using PCI device at bus 0 device 2 function 0
Ethernet address 22:22:22:22:00:00
10090076+518916+618576 [521184+509293]=0xbb2988
Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    2006, 2007, 2008, 2009, 2010, 2011, 2012
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 5.1.2 (GENERIC) #0: Thu Feb  2 17:22:10 UTC 2012
    builds@b6.netbsd.org:/home/builds/ab/netbsd-5-1-2-RELEASE/i386/201202021012Z-obj/home/builds/ab/netbsd-5-1-2-RELEASE/src/sys/arch/i386/compile/GENERIC
[...]
Sun Oct  7 15:54:24 UTC 2012

NetBSD/i386 (netbsd5) (console)

login: root

Yay!

(Todo: train creaky old pxeboot_ia32.bin to retry DHCP via broadcast if unicast fails.)


Thursday 26 April 2012

FreeRADIUS and CRLs

Deploying FreeRADIUS, you may want to use a Certificate Revocation List (CRL) to revoke access to users that has been issued a valid certificate at some point.

How to actually do this isn't completely self-evident. Less so if you use multiple sub-CAs.

FreeRADIUS basically uses OpenSSL's routines and options for this. And OpenSSL doesn't currently refresh CRLs in a running process, so after updating a CRL you need to restart the freeradius daemon (easily scripted).

The important point in freeradius is in /etc/freeradius/eap.conf, specifically check_crl and CA_path in the tls section. Also, comment out CA_file, since CA_path and CA_file are intended for the same purposes, but CRLs only work with the CA_path method.
   #  Check the Certificate Revocation List
   #
   #  1) Copy CA certificates and CRLs to same directory.
   #  2) Execute 'c_rehash '.
   #    'c_rehash' is OpenSSL's command.
   #  3) uncomment the line below.
   #  5) Restart radiusd
   check_crl = yes
   CA_path = /etc/freeradius/certs/CA/
Be sure not to concatenate certificates in your CA_path. One CA, one file. Then, after the c_rehash, your directory should look something like this:
root@radius:~# ls -l /etc/freeradius/certs/CA/
lrwxrwxrwx 1 root freerad    9 2012-04-26 03:15 12345678.0 -> local-sub-ca-1.pem
lrwxrwxrwx 1 root freerad   13 2012-04-26 03:15 12345678.r0 -> sub-ca-1-crl.pem
lrwxrwxrwx 1 root freerad   11 2012-04-26 03:15 23456789.0 -> local-root-ca.pem
lrwxrwxrwx 1 root freerad    8 2012-04-26 03:15 3456789a.0 -> local-sub-ca-2.pem
lrwxrwxrwx 1 root freerad   12 2012-04-26 03:15 3456789a.r0 -> sub-ca-2-crl.pem
-rw-r--r-- 1 root freerad 1360 2012-04-24 15:04 local-root-ca.pem
-rw-r--r-- 1 root freerad 1360 2012-04-24 15:06 local-sub-ca-1.pem
-rw-r--r-- 1 root freerad 1384 2012-04-24 14:58 local-sub-ca-2.pem
-rw-r--r-- 1 root freerad 1251 2012-04-26 03:15 sub-ca-1-crl.pem
-rw-r--r-- 1 root freerad  739 2012-04-26 03:15 sub-ca-2-crl.pem
Thanks to Yasuhiro ABE for pointing me in the right direction. ありがとうございました、あべさん!それはよかったよ!

Monday 6 February 2012

dnstool - curses-based DNS zone administration

Out now! Get it while the bits are still hot!

https://github.com/Redpill-Linpro/dnstool

The Fine Manual is plain text and even has screenshots, perfect for the old-school lynx enthusiast ;)

If your dns server supports RFC2136 dynamic updates, you might want to look at this. BIND9 does.

Patches always welcome!