Hoe de veerkracht van OpenBSD tegen stroomuitval te vergroten
Deze laatste systemen hebben een grote kans op 'unclean shutdowns' door onverwachte stroomuitval. Dit vergroot de waarschijnlijkheid dat het systeem niet meer kan opstarten zonder menselijke tussenkomst. Dit artikel beschrijft stappen om een OpenBSD-systeem veerkrachtiger te maken tegen onverwachte stroomuitval door de kans op inconsistente bestandssystemen te minimaliseren. Dit wordt bereikt door alle diskpartities in read-only modus te mounten. Bestandssystemen die schrijfbare toegang vereisen — /var, /dev en /tmp — worden gemount als writable memory file systems (MFS).
Een waarschuwing vooraf
Dit is een "werkt voor mij"-tutorial. Hoewel ik deze configuratie op meer dan 30 productiesystemen gebruik, betekent dit niet dat het per se voor elk doel geschikt is. Het hoofddoel van dit artikel is om lezers te informeren over minder bekende functionaliteiten van OpenBSD en hun begrip van de onderliggende componenten te verdiepen.
Houd er rekening mee dat wanneer je afwijkt van standaard templates, je grotendeels op jezelf bent aangewezen als er iets misgaat met het ontwerp. Het houden van /var in een memory file system is door Theo de Raadt, oprichter en leider van OpenBSD, getypeerd als een "weird tweak". Hij gaf aan dat zij geen software schrijven voor "crazy tweaks".
Sommige OpenBSD-ontwikkelaars zijn ondersteunend aan niet-standaard configuraties. Zo is een melding over tcpdump(8) die niet kon starten met een read-only / filesystem geïdentificeerd als een unveil(2) bug, wat leidde tot een kernelpatch in OpenBSD 6.6. Andere ontwikkelaars zijn minder ondersteunend; zo gaf de maker van syspatch(8) aan dat hij de controle zou aanscherpen zodat syspatch direct faalt bij een MFS-gemounte /var.
Denk daarom goed na voordat je OpenBSD-ontwikkelaars om hulp vraagt bij het gebruik van deze setup. De groep gebruikers die read-only / en /var op mfs gebruikt is insignificant. Problemen die je tegenkomt, liggen waarschijnlijk aan de manier waarop je OpenBSD gebruikt, en niet aan OpenBSD zelf. Mocht je toch vragen stellen op mailinglijsten, dan is het eerlijk om te verklaren welke bestandssystemen je read-only houdt en welke als memory file systems zijn gemount.
Gebruikte hardware en software
Ik gebruik een PC Engines apu4c4 routerboard vanwege de volgende kenmerken:
- Het heeft 4 GbE-poorten, ideaal voor filiaalvestigingen (twee poorten voor verschillende ISP's, een derde voor het lokale LAN en een vierde voor de
pfsync(4)interface in high availability setups metcarp(4)). - De CPU (1 GHz quad Jaguar core met 64-bit en AES-NI support) presteert goed bij het versleutelen van IPSEC-flows.
- Het heeft 4 GB RAM, wat voldoende is voor basis routing, firewalling en memory file systems.
Voor de lokale SD-kaartopslag gebruik ik een 32 GB SanDisk Extreme PRO. Experimenten met goedkopere kaarten resulteerden in langdurige downtime en kostbare reizen naar afgelegen locaties, wat uiteindelijk duurder uitviel dan de kaart zelf.
Ik maak verbinding met de seriële interface van de apu4c4 via een ThinkPad T440 met een DIGITUS USB 2.0 seriële adapter. De laptop draait FreeBSD 12.1-RELEASE als hoofd-OS, met Xfce als desktopomgeving en GNU Screen voor de consoleverbinding.
Ik gebruik dd om install68.img op een USB-stick te zetten. De ethernetpoort em0 wordt aangesloten op mijn LAN-switch om via een ISC DHCP-server IP-parameters te verkrijgen. Vanaf OpenBSD 6.6 heb ik geen third-party pakketten nodig, aangezien ik openrsync(1) gebruik om het memory-based /var bestandssysteem periodiek te synchroniseren met de UFS-geformatteerde diskpartitie /altvar.
Installatie
Bij de installatie is een handmatige partitionering cruciaal voor deze read-only setup. Kies bij de vraag over schijfallocatie voor (C)ustom layout en partitioneer als volgt:
| Label | Mountpoint | Grootte |
|---|---|---|
| a | / | 1g |
| b | <none> (swap) | 1g |
| d | /var | 1g |
| e | /usr | 2g |
| f | /usr/X11R6 | 1g |
| g | /usr/local | 1g |
| h | /home | 4g |
| i | /var/syspatch | 1g |
Controleer met p m of de partitionering correct is voordat je de wijzigingen opslaat met w en afsluit met q.
Vervolgens installeer ik alle sets. Voorheen installeerde ik alleen de basis- en man-sets om ruimte te besparen en het aanvalsoppervlak te verkleinen. Echter, ik ontdekte dat sommige handleidingen (zoals die van sendsyslog(2)) in compXX.tgz staan en niet in manXX.tgz. Om verwarring en problemen met ontbrekende documentatie te voorkomen, installeer ik nu alle sets.
Eerste opstarten (nog standaard)
Na de eerste boot kunnen we de mountpoints en schijfruimte bekijken:
robsd66# mount
/dev/sd0a on / type ffs (local)
/dev/sd0h on /home type ffs (local, nodev, nosuid)
/dev/sd0e on /usr type ffs (local, nodev)
/dev/sd0f on /usr/X11R6 type ffs (local, nodev)
/dev/sd0g on /usr/local type ffs (local, nodev, wxallowed)
/dev/sd0d on /var type ffs (local, nodev, nosuid)
/dev/sd0i on /var/syspatch type ffs (local, nodev, nosuid)
robsd66# df -h
Filesystem Size Used Avail Capacity Mounted on
/dev/sd0a 1008M 96.3M 862M 10% /
/dev/sd0h 3.9G 18.0K 3.7G 0% /home
/dev/sd0e 2.0G 955M 964M 50% /usr
/dev/sd0f 1008M 202M 756M 21% /usr/X11R6
/dev/sd0g 1008M 218K 958M 0% /usr/local
/dev/sd0d 1008M 5.9M 952M 1% /var
/dev/sd0i 1008M 2.0K 958M 0% /var/syspatch
Op dit moment is het systeem vrijwel identiek aan een automatische installatie, behalve dat /tmp, /usr/obj en /usr/src ontbreken (we compileren niets uit broncode) en er een aparte /var/syspatch partitie is toegevoegd om het RAM-geheugen niet te vervuilen met binary patches.
De weg naar waanzin
We beginnen nu met de configuratie om het systeem veerkrachtiger te maken. Eerst maken we een map die dient als mountpoint voor de on-disk /altvar partitie:
robsd66# mkdir /altvar
Nu passen we fstab aan zodat de UFS-partitie die oorspronkelijk onder /var stond, nu onder /altvar wordt gemount. Daarnaast introduceren we drie memory file systems: /var, /dev en /tmp. De mappen /var en /dev worden gevuld vanuit respectievelijk /altvar en de root-partitie /.
Maak eerst een back-up van de originele fstab:
# cp /etc/fstab ~/fstab.ORIG
Hieronder volgt het voorbeeld van de aangepaste fstab. Let op: Kopieer de DUUID's niet, deze zijn uniek voor mijn systeem. De volgorde is belangrijk; declareer sub-mountpoints (zoals /var/syspatch) nooit boven het mountpoint waarin ze vallen (zoals /var).
2a250ffa1d19cd07.a / ffs rw 1 1
2a250ffa1d19cd07.b none swap sw
2a250ffa1d19cd07.d /altvar ffs rw,nodev,nosuid 1 2
2a250ffa1d19cd07.e /usr ffs rw,nodev 1 2
2a250ffa1d19cd07.f /usr/X11R6 ffs rw,nodev 1 2
2a250ffa1d19cd07.g /usr/local ffs rw,wxallowed,nodev 1 2
2a250ffa1d19cd07.h /home ffs rw,nodev,nosuid 1 2
swap /var mfs rw,nodev,nosuid,-s512m,-P=/altvar 0 0
swap /dev mfs rw,nosuid,noexec,-s4m,-P=/dev,-i128 0 0
swap /tmp mfs rw,nodev,noexec,nosuid,-s512m 0 0
2a250ffa1d19cd07.i /var/syspatch ffs rw,nodev,nosuid 1 2
Herstart het systeem om de MFS-partities te activeren.
Dieper in het konijnenhol
Na de herstart zien we dat /var, /dev en /tmp nu als mfs worden weergegeven. Omdat /var nu vluchtig is, verliezen we alle wijzigingen bij een reboot of stroomuitval. Bovendien zijn de on-disk UFS systemen nog steeds writable.
We lossen dit op door periodiek te synchroniseren. Let bij het gebruik van openrsync goed op de slashes (/) om te voorkomen dat je /var synchroniseert naar /altvar/var in plaats van de inhoud te spiegelen.
Handmatige initiële synchronisatie:
# /usr/bin/openrsync --rsync-path=/usr/bin/openrsync -avx --delete /var/ /altvar
Sommige bestanden in /var zijn cruciaal, zoals db/kernel.SHA256 (belangrijk voor kernel reordering) en de backups/ directory. Om dit te automatiseren maken we een script: /root/syncvar.sh.
Dit script doet het volgende:
- Mount alle on-disk partities tijdelijk als writable (
rw). - Update het
random.seedbestand voor betere entropie en beveiliging. - Synchroniseert de inhoud van
/varnaar/altvar. - Mount alle on-disk partities weer als read-only (
ro).
Inhoud van /root/syncvar.sh:
#!/bin/sh
/sbin/mount -uwA -t nomfs
dd if=/var/db/host.random of=/dev/random bs=65536 count=1 status=none
chmod 600 /var/db/host.random
dd if=/dev/random of=/var/db/host.random bs=65536 count=1 status=none
dd if=/dev/random of=/etc/random.seed bs=512 count=1 status=none
chmod 600 /etc/random.seed
/usr/bin/openrsync --rsync-path=/usr/bin/openrsync -avx --delete /var/ /altvar
/sbin/mount -urA -t nomfs
Maak het script uitvoerbaar:
robsd66# chmod 755 /root/syncvar.sh
Planning en Automatisering
Het script moet periodiek draaien, maar niet té vaak om slijtage van de SD-kaart te voorkomen. Een dagelijkse uitvoering via cron is voldoende:
@daily /root/syncvar.sh >/dev/null 2>&1
Maak daarnaast een /etc/rc.shutdown bestand aan met de volgende inhoud om synchronisatie bij het afsluiten af te dwingen:
#!/bin/sh
/root/syncvar.sh
Ten slotte voegen we een custom functie toe aan rc.local. Deze wacht tot de kernel reordering is voltooid, synchroniseert daarna /var naar /altvar en zet de disk-bestandssystemen in read-only modus:
mount_ro() {
while sleep 5; ([ -n "$(pgrep -f 'reorder_kernel')" ]); do done
/usr/bin/openrsync --rsync-path=/usr/bin/openrsync -avx --delete /var/ /altvar
/sbin/mount -urA -t nomfs
}
mount_ro &
Na een laatste reboot is het systeem veerkrachtiger tegen stroomuitval. Als je wijzigingen aan disk-bestanden moet aanbrengen, gebruik dan: mount -uwA -t nomfs. Zet ze daarna weer terug met: mount -urA -t nomfs.
syspatch en sysupgrade
Om het systeem te patchen of upgraden met syspatch(8) en sysupgrade, moet je tijdelijk terugkeren naar een "vanilla" installatie.
- Activeer de originele fstab en verplaats de scripts uit
/etc:
``bash # cp /etc/fstab ~/fstab.MFS # cp ~/fstab.ORIG /etc/fstab # mv /etc/rc.shutdown ~/ # mv /etc/rc.local ~/ ``
- Herstart het systeem. De partities zijn nu writable en de synchronisatie is uitgeschakeld. Voer de updates uit zoals gebruikelijk.
- Na de update (en eventuele reboot voor kernel-patches), maak je het systeem weer veerkrachtig in twee fasen:
Fase 1: Activeer de MFS fstab en reboot. ``bash # cp ~/fstab.MFS /etc/fstab # reboot ``
Fase 2: Herstel de scripts en reboot opnieuw. ``bash # cp ~/rc.shutdown /etc/ # cp ~/rc.local /etc/ # reboot ``
Na deze stappen is het systeem weer volledig veerkrachtig geconfigureerd.
Groetjes,