Netzwerk-bootfähiger Client zur Integration ins Schulsystem

Zielsetzung

Das Ziel der Entwicklung dieses Systems ist ein Diskless-Client1), der über das Netzwerk startet und alle Programme lokal ausführt, sodass vorhandene Rechenleistung weiter verwendet wird und keine neue Hardware angeschafft werden muss. Weiterhin soll dieses System bequem verwalt- und konfigurierbar sein und sich leicht in eine Paed-/OpenML-Lösung integrieren lassen. Hierbei ist auch eine gewisse Distributions-Unabhängigkeit wünschenswert.
Besonders wichtig soll die Sicherheit des Systems sein, dass die Endbenutzer keine Veränderungen an kritischen Eigenschaften des Systems vornehmen können (Vandalismus2)-Vorbeugung).
Wünschenswert ist eine gewisse Geschwindigkeit3).

Realisierung: Theorie

Die Grundlage des Systems ist ein debootstrap 4) -tes Debian-System.
Dieses wird auf dem Server erzeugt und konfiguriert.
Danach wird das System nur lese-berechtigt in das Netzwerk mit NFS5) freigegeben6) und mit PXE 7) gebootet.
Es sind also Eingriffe am DHCP-Server nötig.
Ebenso muss ein TFTP-Dämon auf einem Host installiert werden und eine NFS-Freigabe des Systems erstellt werden.

Realisierung: Praxis

Anfänge: Grundkonfiguration (undatiert)

Client

Irgendwann im August anno 2011 begann thoto ein debootstraptes Debian zu erstellen 8) mit:

debootstrap stable ./ http://ftp.de.debian.org/debian

Nach der Installation konnte die grundlegende Konfiguration 9) des Systems vorgenommen werden.
Das Netzwerk sollte so eingerichtet werden, dass das normale Interface, über das gebootet wird und
das die Verbindung zum NFS-Server aufrecht erhält, keine Konfiguration bekommt, sondern nur das
Loopback-Interface konfiguriert 10) wird. Dies wird für einige Anwendungen benötigt.
Das System bootete schliesslich in einer virtuellen Maschine11).
Zur Arbeit mit dem System wird jedoch KEINE virtuelle Maschine verwendet, sondern eine chroot-ed-Umgebung:

chroot ./ /bin/sh

Hierbei ist zu beachten, dass man sich dabei an der Dateisystem-Wurzel12) des debootstrap-Systems befinden muss.
Hier kann das System den eigenen Wünschen angepasst werden unter anderem muss das Paket aufs-tools installiert werden.

apt-get install aufs-tools

Um das System NFS-Rootfähig zu machen verwendet man das in eigener Produktion entstandene Skript nfsroot.sh in Anhang A. Dieses installiert man über:

cp nfsroot.sh /etc/init.d/nfsroot.sh
insserv /etc/init.d/nfsroot.sh
/etc/init.d/nfsroot.sh install

Danach modifiziert man die Datei /etc/fstab, sodass dort auch folgende Zeilen stehen:

none    /aufs-tmp/home  tmpfs   auto,defaults           0       0
none    /home           aufs    auto,defaults,br:/aufs-tmp/home=rw:/home=ro,rw 00

Diese Zeilen erzeugen eine schreibbare Home-Parition, die in einem RAM-Dateisystem13) liegen. Das Dateisystem AUFS 14) ermöglicht
hier „ein Schreiben“ auf ein Dateisystem ohne Schreibmöglichkeit, indem es ein Dateisystem zum Lesen der Daten verwendet und ein weiteres zum Schreiben der Daten.
AUFS ermöglicht auch mehrere andere interessante Aktionen, z.B. ein gleichmäßiges Verteilen von Daten über mehrere Dateisysteme und einiges mehr 15).

Nachdem wir nun das System zu einem festplattenlosen Bootvorgang vorbereitet haben, können wir uns dem Kernel zuwenden. Hierbei
muss die Initrd 16), modifiziert werden, damit z.B. der NFS-Kernel-Client integriert wird. Bei einem Debian-System ändert/editiert man einfach die Datei
/etc/initramfs-tools/initramfs.conf folgendermaßen 17):

MODULES=netboot
BOOT=nfs
NFSROOT=auto

Damit wäre18) der Client Netzwerk-bootfähig.

Server

Die Einrichtung des Servers verläuft ähnlich unkompliziert:
Bei dem Testsystem handelt es sich entweder um ein Arch-Linux-System (Testsystem) oder OpenML-Debian.
Dadurch variieren die Paketnamen etwas:

Komponente Arch-Linux Debian OpenML Anmerkung
NFS-Server nfs-utils nfs-kernel-server Empfehlenswert ist der Kernel-Server
NFS-Client nfs-utils nfs-common
DHCP-Server dhcpd isc-dhcpd Empfehlenswert ist der ISC-DHCPd
TFTP-Server tftp-hpa tftpd-hpa HPA
Test-VM kvm / qemu kvm / qemu Nur zum Test! Bitte keine Verwendung in Produktivsystem!

Paket-Installation mittels pacman -S oder apt-get.

Konfiguration:

NFS-Server

Der NFS-Server muss so konfiguriert werden, dass er das Verzeichnis (im Beispiel /srv/nfsroot) an
den Client (im Beispiel mit der IP 10.16.1.106) exportiert. Der Client darf jedoch nicht auf den Server Schreiben (Flag ro) und
alle Berechtigungen sollen einfach übertragen werden, ohne bestimmte User-Berechtigungen des Users root (auf dem Client)
auf den User nobody zu übertragen (Flags no_root_squash und no_all_squash).
Das Flag no_subtree_check wird eigentlich nur bei Debian benötigt.
Es ist empfehlenswert die Freigaben fest vorzunehmen, sodass diese bei jedem Booten auch wieder erscheinen. Dazu dient folgender Eintrag in /etc/exports, :

/srv/nfsroot    10.16.1.106(ro,no_root_squash,no_all_squash,no_subtree_check)

Nach wie vor kann auch ohne Veränderung der /etc/exports das NFS-Wurzel-Dateisystem exportiert werden durch:

exportfs -o ro,no_root_squash,no_all_squash 10.16.1.106:/srv/nfsroot
DHCP-Server

Anmerkung: Bitte ERST lesen, DANN ausprobieren.
Der ISC-DHCPd sollte folgende Zeilen in ähnlicher Form in der Konfigurationsdatei19) enthalten:

subnet 10.16.1.0 netmask 255.255.255.000 {
  range 10.16.1.10 10.16.1.20;
  option broadcast-address 10.16.1.255;
  option routers 10.16.1.1;
}

group netterms{
  filename "pxelinux.0";
  next-server 10.16.1.1;
  
  host netterm1{
    hardware ethernet 00:50:56:12:00:60;
    fixed-address 10.16.1.101;
  }
}

Die Umgebung subnet sorgt hier für eine allgemeine Adressverteilung und das Setzen einiger Parameter, sowie dafür, dass DHCPd überhaupt
auf dem Interface 20) lauscht, das eine IP im angegebenen Subnetz hat.
„group netterms“ gruppiert alle Netzwerk-Bootrechner in einer Gruppe. Diese werden in einer Host-Umgebung angegeben und sollten eindeutig
über ihre MAC-Adresse identifiziert und ihnen eine eindeutige IP-Adresse zugewiesen werden.
Ebenso werden gruppenweit die Parameter filename und next-server übergeben,
die die Lage des TFTP-Servers und den Dateinamen des Boot-Loaders auf diesem definieren.
In OpenML ist hier die Konfiguration einfacher:
Einfach über die Schulkonsole (https:/ /<openml-server>:242/) eine neue LINBO-Gruppe anlegen und unter Hosts
dem entsprechenden Rechner diese Gruppe zuweisen. Die pxelinux-Konfigurationsdatei lautet dann dementsprechend nicht mehr default,
sondern liegt unter anderem Dateinamen (Arno meint nach Blick in /etc/dhcp3/dhcpd.conf-linuxmuster: clientnet)in diesem Verzeichnis. Also /var/linbo/pxelinux.cfg/clientnet

TFTP-Konfiguration

Die Einrichtung des TFTPd ist trivial: TFTPd-HPA hat ein beim Starten des Dämon als Argument übergebenes Verzeichnis, aus dem er seine Dateien freigibt.
Die automatischen Startskripts unter Arch-Linux ermöglichen einen einfachen Start. Die Konfiguration des Dämon liegt hierbei in
/etc/conf.d/tftpd. In dieser Datei wird die Variable TFTPD_ARGS gesetzt, der alle Parameter enthält, die der TFTPd auf der Kommandozeile übergeben bekommt. Beispiel:

TFTPD_ARGS="-l -s /usr/local/tftpboot"

Debian's TFTP-Konfiguration liegt in /etc/default/tftpd-hpa
Bei OpenML sollte man nichts umkonfigurieren, da LINBO sonst nicht startet. Hier verwendet man den vorgegebenen Pfad /var/tftproot. FIXME

pxelinux-Konfiguration (alias Syslinux)

PXELINUX ist ein auf SYSLINUX 21) aufbauender Bootloader für PXE. Er wird vom Boot-ROM der Netzwerkkarte aus dem Netzwerk via TFTP in den RAM geladen und ausgeführt. PXELINUX holt sich dann via TFTP seine eigene Konfiguration aus dem Netz, die im Verzeichnis pxelinux.cfg im selben TFTP-Verzeichnis liegt, soweit nicht anders via DHCP angegeben.
PXELINUX sucht hier zunächst nach Dateien, die seine MAC- oder IP22)-Adresse im Dateinamen haben, oder, wenn diese Option23) vom DHCP-Server übergeben wurde nach einer bestimmten Datei. Als letzte Möglichkeit nimmt er die Datei default in diesem Verzeichnis. Danach lädt er den ersten Fund herunter und parst diese Konfiguration.
Aufgrund seiner Herkunft sieht die PXELINUX-Konfiguration eine SYSLINUX-Konfiguration sehr ähnlich:
Datei: pxelinux.cfg/default

default foo
label foo 
    kernel term/vmlinuz
    append vga=normal initrd=term/initrd.img root=/dev/nfs nfsroot=10.16.1.1:/srv/nfsroot/ ip=dhcp noprompt ro -- quit

Diese Konfiguration ist natürlich noch anzupassen:
Zunächst einmal sollte man einen eigenen Ordner im TFTP-Root erschaffen, soweit nicht bereits24) geschehen. Dort kopiert man den Kernel und das Initrd aus dem debootstrap-ten System hinein. Danach passt man die Pfade in oberer Konfiguration an (term/vmlinuz ist der Kernel, term/initrd.img ist die Init-RAM-Disk) und verändert auch die Parameter für den NFS-Server.
Natürlich muss auch pxelinux.0 im TFTP-Verzeichnis vorhanden sein. Einstellbar ist der Ort der Datei über die DHCP-Konfiguration(s.o.) mit dem Parameter filename. Der DHCP-Konfigurationsparameter next-server sollte die IP des TFTP-Servers enthalten.

KVM-Test-VM

Nun sollten alle Dämonen gestartet werden (DHCP, TFTP und NFS) und ein erster Test gestartet werden. Dazu ist es sehr empfehlenswert KVM zu verwenden. Hierbei sollte aber noch der TUN-/TAP-Support für Netzwerkinterfaces nachinstalliert werden:

pacman -S uml_utilities

bzw.

apt-get install uml-utilities

Danach kann man25) ein TAP-Interface mit Berechtigungen für unseren testenden Benutzer26) erstellen und eine IP an dieses vergeben,
das später eine direkte Verbindung zur VM herstellt:

tunctl -u user -g kvm -t tap0
ifconfig tap0 10.16.1.1 up

Erst danach sollte man den DHCPd27) starten, damit er auch garantiert auf dieses Interface lauscht. Dazu ist natürlich auch nötig, dass der DHCPd auf dem Host installiert ist, auf dem die Tests stattfinden. Der TFTP-Server und NFS-Server können auch auf einem anderen Host liegen, jedoch muss dann IP-Forwarding im Linux-Kernel aktiviert28) werden.
Danach kann die KVM gestartet durch folgendes gestartet werden:

 kvm -net nic,vlan=0,macaddr=00:50:56:12:00:60 -net tap,vlan=0,ifname=tap0 -monitor stdio -boot n 

Wichtig: Bitte nicht in einem Produktivsystem Tests durchführen!

Starten aller Dämonen im Testsystem (Arch-Linux)

Noch ein kleines Skript, das alle wichtigen Komponenten auf dem Testsystem startet:

tunctl -u <username!> -g kvm -t tap0
ifconfig tap0 10.16.1.1 up
/etc/rc.d/dhcp4 start
/etc/rc.d/tftpd start
/etc/rc.d/nfs-server start
exportfs -o no_root_squash,no_all_squash,ro 10.16.1.\*:/srv/nfsroot/

Erste Einbettung in OpenLML, 2011-08-17

Die erste Einbettung des oben beschriebenen Systems in OpenLML lief relativ flüssig. Zwar musste der NFS-Server noch installiert werden und die Schulkonsole ein wenig ausgetrickst werden jedoch lief es unerwartet schnell, sehr gut. Das Austricksen bezieht sich auf folgendes:
Es kann leider nur LINBO als Netzwerkboot-Image verwendet werden. So musste eine neue LINBO-Umgebung erstellt werden29) und die PXE-Konfiguration umgebogen werden30).
Um ein hübsches Vorzeige-System zu erstellen sollten X11 und ein billiger, für nicht-Linuxer leicht zu bedienender Window-Manager installiert werden, also wurde IceWM ausgewählt. Somit installierten wir also bequem über die change-root-Umgebung icewm, mussten aber noch /proc in die Umgebung31) einbinden. Wir installierten um das Image klein zu halten nur den radeon- Treiber32).
Die X-Konfiguratin war etwas umständlicher, da wir erst das Verzeichnis /root33) schreibbar machen mussten, was wir durch das temporäre Mounten eines auf dem Server via NFS schreibbar freigegebenen Ordners erreichten, der via AUFS über das Verzeichnis /root übermountet wurde. So konnten wir eine Konfiguration erzeugen34), testen35) und einsetzen36).
Danach stellten wir fest, dass wir mit unserem Test-Benutzer anmelden konnten und X via xinit starten konnten, jedoch uns slim, den wir zur Steigerung der Benutzerfreundlichkeit als Display-Manager einsetzten37), nach einem Login direkt wieder hinauswarf. Nach Betrachtung der Log-Dateien wurde schnell klar, dass das Problem bei xauth lag, das gerne ~/.Xauthority angelegt hätte. Theoretisch hätte man xauth mit -file oder der Umgebungsvariable $XAUTHORITY eine andere Position der Datei mitgeben können, jedoch verhindete dies slim, der auf irgendeine Weise hart-kodiert den Pfad zu dieser Datei festgeschrieben hatte und der auch nicht xauth mit User-Berechtigung38) lief.
Somit mounteten wir erneut ein AUFS über /home und schrieben in ein TMPFS hinein. Damit dies persistent bleibt, modifizierten wir die Datei /etc/fstab (s.o.) und änderten das Installationsskript (s.u.).
Danach installierten wir noch chromium (Die Basis von Chrome) als schnellen Browser.

NFS durch die Firewall, 2011-08-31

Das OpenLML-System hat leider einen Schutz durch einen IP-Filter 39) realisiert. Dadurch wird es von Außen erschwert auf unbekannte Dienste des Schulservers zuzugreifen.
Da NFS nachgerüstet wurde, ist dies auch hier der Fall: Man muss die Firewall wegnehmen40) um den Client mit NFS-Root starten zu können.
Da dies natürlich unpraktisch und unsicher ist, müssen neue Firewallregeln geschrieben werden. Hierzu könnte man ein Skript erstellen, was dies selber vornimmt oder die bestehenden Skripte modifizieren. Die Linux-Musterlösung verfügt hierbei über eine Methode, bei der man einfach UDP- und TCP-Ports in eine Art Liste schreiben braucht, und das Init-Skript linuxmuster-base erzeugt daraus automatisch Firewall-Regeln.
Leider erzeugt jedoch NFS bei jedem Start mithilfe von Portmap neue Ports für seine Dienste. Aus diesem Grund müssen diese festgeschrieben werden. Einige kann man in den entsprechenden Dateien /etc/default/nfs-* anpassen. Hierbei müssen den Dämonen mountd und statd der Parameter –port übergeben werden, was sich über diese Dateien definieren lässt.
Hierzu verwendet man den in der Default-Konfiguration bereits existierenden aber leeren Parameter STATDOPTS, für statd, der auch zusätzlich den Parameter –outgoing-port benötigt um außerhalb des Rechners kommunizieren zu können. Hierbei muss es sich scheinbar (FIXME) um einen anderen Port als über –port handeln.
Der NFS-Server wird in der Datei /etc/default/nfs-kernel-server über die Variable RPCMOUNTDOPTS mit dem Parameter –port angepasst.
nfs callback und lockd, die für die Sperrung von Dateien sowie für eine Rückverbindung verantwortlich sind, sind jedoch (scheinbar FIXME) kernelseitig und müssen daher direkt in der Initram-Disk des Schulservers angepasst werden. Dazu erstellt man eine beliebige Datei in /etc/modprobe.d/, die man mit den entsprechenden Konfigurationsdaten füllt:

 options lockd nlm_udpport=32768 nlm_tcpport=32768
 options nfs callback_tcpport=32764

Andere Dämonen werden nicht benötigt.
Die Ports müssen nachher in der Firewall hinzugefügt werden, indem man die Open-LML-Firewall-Konfiguration in /etc/linuxmuster-base/allowed_ports bearbeitet.
Quelle: Debian Wiki
Die aktuellen Firewallregeln kann man sich über iptables -L -v anzeigen lassen.

FIXME — WORK IN PROGRESS — WIRD FORD-GESETZT — TO BE CONTINUED — FIXME

Anhang A

nfsroot.sh

Ort: /etc/init.d/
Installation:

insserv /etc/init.d/nfsroot.sh
# insserv aktiviert installierte Init-Skripte, in dem es die passenden Links
#         in den Runlevel-Verzeichnissen (/etc/init.d/rcn.d) setzt. ))
/etc/init.d/nfsroot.sh install


Skript:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          nfsroot
# Required-Start:    checkroot
# Required-Stop:
# Default-Start:     S
# Default-Stop:
# X-Start-Before:    mtab ifupdown
# Short-Description: Provides mechanisms for running from ro-rootfs
# Description:       Provides mechanisms for running from ro-rootfs
### END INIT INFO
 
# nfsboot.sh, init-script supplied by MODUL NFSBOOT, PROJEKT SCHULSYSTEM
# (Autor: thoto)
# Installation: insserver nfsroot.sh
# !!! Unvollständige Version.  !!!
 
PATH=/sbin:/bin
#. /lib/init/vars.sh
. /lib/init/mount-functions.sh
. /lib/lsb/init-functions
 
makelink(){ # $1:file $2:linked file $3:DIR?
        if [ ! -e $1 -o ! -L $1 -o "$(readlink $1)" != "$2" ] ; then 
                echo "Creating link $1 to $2"
                # remove file if it exists
                [ -e $1 ] && rm $1
                # create linked file/directory if it is not there yet
                if $3 ; then 
                        [ -d $2 ] || mkdir $2
                else 
                        [ -f $2 ] || touch $2 
                fi
                # finally create the link
                [ ! -L $1 -o "$(readlink $1)" != "$2" ] && ln -s $2 $1
        fi
}
 
case "$1" in
  install) 
        [ -d /var-rw ] || mkdir /var-rw
        [ -d /aufs-tmp ] || mkdir /aufs-tmp
        [ -d /aufs-tmp/home ] || mkdir /aufs-tmp/home
 
        #makelink "/etc/mtab" "/var/run/mtab" false
        makelink "/etc/mtab" "/proc/mounts" false
        makelink "/etc/network/run" "/var/run/ifstate" true
        ;;
  start|"")
        log_daemon_msg "Making readonly NFS-root usable" "nfsboot"
        modprobe aufs
        domount tmpfs "" /var-rw none "-n -odefaults"
        domount aufs  "" /var    none \
                        "-orw,br:/var-rw=rw:/var=ro,nodev"
        log_end_msg 0
        ;;
  restart|reload|force-reload)
        # nop
        ;;
  stop)
        # nop
        ;;
  *)
        echo "Usage: nfsroot.sh [start|stop]" >&2
        exit 3
        ;;
esac
1) obwohl theoretisch festplattenlos, soll eine vorhandene Platte dennoch zur Installation von User-eigenen Programmen und Speicherung größerer Datenmengen verwendbar sein
2) Die Freiheit des Nutzers soll hierbei möglichst wenig angetastet werden!
3) dies hat sich bisher als unaufwendig erwiesen, die Systeme booten in wenigens Sekunden: Schneller als gewissen proprietäre Systeme von Festplatte…
4) debootstrap im Debian-Wiki
6) Linux hat im Kernel einen NFS-Client integriert und kann somit eine NFS-Freigabe als Root-FS (/) verwenden
7) eine detaillierte Übersicht bei Wikipedia, die man nicht vollständig verstehen muss und die auch der Autor (thoto) nur überflogen hat. Standards halt….
8) Vorsicht mit dem „stable“-Repo,(besser Versionsnamen) und bitte einen anderen als den HauptMirror verwenden!
10)
 auto lo 
 iface lo inet loopback
 
11) verwendet wird hier aus Bequemlichkeit qemu/kvm; mehr hierzu unten
12) Verzeichnis: /
13) tmpfs
14) Another Union File System AUFS-Website
15) Siehe AUFS-Handbuchseite unter ''AUFS''-Website oder mit
man aufs
16) Die RAM-Disk, die Daten, die für den Systemstart vor einbinden der Dateisysteme benötigt werden, enthält
17) Scheinbar kann man hiermit auch einfach eine Datei in /etc/initramfs-tools/conf.d verwenden. DIES WURDE ABER NOCH NICHT GETESTET!
18) man korrigiere, wenn nicht
19) Die Konfigurations-Datei liegt an verschiedenen Orten: mal in /etc/dhcpd.conf, mal in /etc/dhcp/dhcpd.conf mal in /etc/dhcp3/dhcpd.conf … Viel Spass beim Suchen! ;-)
20) In der Testumgebunt tap0
22) IPv4-Adresse in hexadezimaler Notation ohne Punkte, auch Teile vom Anfang
23) option 209, pxelinux.configfile
24) von OpenML: Name der Klasse
25) als Root!
26) Schalter -u mit nachfolgendem Benutzernamen
27) Unter Arch-Linux angenehmerweise /etc/rc.d/dhcp4
28)
echo -n "1">/proc/sys/net/ipv4/ip_forward
29) was natürlich auch Overhead erzeugt
30) Ehrlich? Ich hatte was schlimmeres erwartet!
31) aus welchen Gründen auch immer
33) Home-Verzeichnis von User root
34)
 X -configure 
35)
X -config /root/xorg.conf.new
36)
cp /root/xorg.conf.new /etc/X11/xorg.conf
37) Persönlich nutzt thoto keinen DM
38) Geht das eigentlich?
39) iptables
40) Durch /etc/init.d/linuxmuster-base stop, das Gegenteil wird durch … start bewirkt
 
schulsystem/netclient.txt · Zuletzt geändert: 2011/09/14 21:45 von arno
 
Recent changes RSS feed Creative Commons License Donate Powered by PHP Valid XHTML 1.0 Valid CSS Debian Driven by DokuWiki