|
19. Ramdisk Router1.1 HintergrundHardware Plattformen wie Soekris net6501-30 stellen mit 512MB RAM genügend Memory zur Verfügung, um Linuxrouter in einer Ramdisk zu betreiben. Die Vorteile liegen auf der Hand, bei Verdacht auf ein korrumpiertes System genügt ein Reboot um den Router in seinen Ausgangszustand zurückzuführen. ( Um dann die nötigen Schritte einzuleiten, damit ein erfolgreicher Angriff nicht wiederholt werden kann. ) Linuxrouter wird auch in seiner Ramdisk Version als standalone Maschine betrieben, da sonst ein separater Bootserver bereitgestellt werden müsste, der das System zur Verfügung stellt. Mit anderen Worten, es handelt sich nicht um eine «diskless» Maschine. 19.2 Systembau
Der Aufbau des Ramdisk Systems erfordert die folgenden Schritte:
-Linuxrouter wird in die Partition 19.3 SystemträgerAls Systemträger wurde eine 120GB SSD ( Solid State Disk ) mit folgendem Aufbau verwendet.
Erklärung: 19.4 Kernel Konfiguration
Kernel 2.6.39 muss mit
19.5
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
# /etc/fstab.std /dev/sda1 / ext2 defaults 1 1 /dev/sdb1 /media/usb vfat,ext2,ext3,iso9660 rw,noauto,user,exec 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 proc /proc proc defaults 0 0 usbfs /proc/bus/usb usbfs defaults 0 0 sysfs /sys sysfs defaults 0 0 tmpfs /dev/shm tmpfs nodev,nosuid,noexec 0 0 # /etc/fstab.ramboot none / tmpfs defaults 0 0 /dev/sdb1 /media/usb vfat,ext2,ext3,iso9660 rw,noauto,user,exec 0 0 devpts /dev/pts devpts gid=5,mode=620 0 0 proc /proc proc defaults 0 0 usbfs /proc/bus/usb usbfs defaults 0 0 sysfs /sys sysfs defaults 0 0 tmpfs /dev/shm tmpfs nodev,nosuid,noexec 0 0 |
Anschliessend wird ein Softlink auf /etc/fstab.std angelegt.
( Beim Kopieren des Systems wird der Link umgeschrieben, so dass das
Ramdisk System mit der /etc/fstab.ramboot startet. )
|
# cd /etc # ln -s fstab.std fstab |
/etc/rc.d/rc.S anpassen
Bei «normalen» Bootups wird das Root Filesystem des Systems
mittels e2fschck auf Fehler untersucht.
Wenn in eine Ramdisk gebootet wird, ist diese Überprüfung überflüssige und erzeugt lediglich die Fehlermeldung:
ERROR: Root partition has already been mounted read-write. Cannot check!
Daher muss das Startscript /etc/rc.d/rc.S ebenfalls modifiziert
werden − zugegebenermassen ein «ugly hack», Vorschläge,
wie dieser vermieden werden kann, sind willkommen.
/etc/rc.d/rc.S wird somit ebenfalls in zwei Versionen geführt,
/etc/rc.d/rc.S.std und /etc/rc.d/rc.S.ramboot.
Slackware 11.0 /etc/rc.d/rc.S verzichtet auf eine Überprüfung des
Filesystems, wenn dieses vom Typ umsdos ist. Für
/etc/rc.d/rc.S.ramboot genügt es somit, an zwei Stellen
«umsdos» durch «tmpfs» zu ersetzen.
Damit wird auf die Überprüfung der Ramdisk verzichtet.
# /etc/rc.d/rc.S.ramboot
# lines 140ff
...
echo "Testing root filesystem status: read-write filesystem"
#if cat /etc/fstab | grep ' / ' | grep -wq umsdos ; then
# ROOTTYPE="umsdos"
#fi
#if [ ! "$ROOTTYPE" = "umsdos" ]; then # no warn for UMSDOS
if cat /etc/fstab | grep ' / ' | grep -wq tmpfs ; then
ROOTTYPE="tmpfs"
fi
if [ ! "$ROOTTYPE" = "tmpfs" ]; then # no warn for tmpfs
...
|
Anschliessend wird ein Softlink auf /etc/rc.d/rc.S.std angelegt.
|
# cd /etc/rc.d # ln -s rc.S.std rc.S |
Der Bootmanager muss den Router via initrd starten.
Linuxrouter v0.50 verwendet lilo, die zugehörige
lilo.conf benötigt somit die folgenden Einträge.
# /etc/lilo.conf
# 2016-01-12
#
# Comment the following two entries out after the first install on the development machine.
#disk=/dev/sdd bios=0x80 # Overrides BIOS' harddisk order, makes BIOS see sdd as sda.
#boot=/dev/sdd # Where lilo installs its boot block.
boot=/dev/sda
map=/boot/map
install=text
default=ramboot
lba32
read-only
prompt
timeout=50
# LILO bootable partitions config
image=/boot/linux
label=linux
root=/dev/sda1
append="console=tty0 console=ttyS0,9600n8r"
image=/boot/linux
label=ramboot
root=/dev/sda1
initrd=/boot/initrd.gz
append="console=tty0 console=ttyS0,9600n8r"
|
initrd-tree anpassen
Die Vorlage für das Minimalfilesystem, das von /usr/sbin/mkintrd
auf die initrd kopiert wird, befindet sich im Tarfile
/usr/share/mkinitrd/initrd-tree.tar.gz.
Unix Systembefehle wie cp, mount, etc., die
darin enthalten sind, werden via BusyBox bereitgestellt.
Leider ist die BusyBox, die im initrd-tree von
Slackware 11.0 zur Anwendung kommt, ohne tar Support kompiliert.
Somit kann das System Archiv /boot/sysimg.tar beim Booten
nicht in die Ramdisk entpackt werden.
Da die BusyBox statisch gelinkt ist, ist Abhilfe jedoch recht
einfach. Wir benützen das Archiv /usr/share/mkinitrd/initrd-tree.tar.gz
eines neueren Systems, beispielsweise von Slackware 13.0. Das Vorgehen ist
wie folgt:
Den initrd-tree eines Slackware 13.0 Systems auf den Router
kopieren und im /tmp Verzeichnis entpacken.
|
# mkdir /tmp/slack13 # cp initrd-tree_slack13_orig.tar.gz /tmp/slack13 # cd /tmp/slack13 # tar -xzvf initrd-tree_slack13_orig.tar.gz # rm initrd-tree_slack13_orig.tar.gz |
Den initrd-tree von Linuxrouter sichern und ebenfalls im /tmp
Verzeichnis entpacken.
|
# mv /usr/share/mkinitrd/initrd-tree.tar.gz /usr/share/mkinitrd/initrd-tree_slack11.tar.gz # mkdir /tmp/slack11 # cp /usr/share/mkinitrd/initrd-tree_slack11.tar.gz /tmp/slack11 # cd /tmp/slack11 # tar -xzvf initrd-tree_slack11.tar.gz |
Den initrd-tree von Slackware 13.0 an die Gegebenheiten
von Slackware 11.0 anpassen.
|
# cd /tmp/slack13 # mkdir ramboot # rm init # cp ../slack11/linuxrc . # cp ../slack11/linuxrc linuxrc00 # cd bin # ln -s busybox chroot # ln -s busybox insmod # ln -s busybox pivot_root |
Die Konfigurationsdatei /tmp/slack11/linuxrc derart anpassen,
dass beim Booten des Systems via initrd eine funktionsfähige
Ramdisk erstellt wird. Die folgenden Anpassungen sind notwendig.
# linuxrc ... # Mount root filesystem on rootdev to /mnt #mount -o ro -t $ROOTFS $ROOTDEV /mnt mount -o ro -t ext2 /dev/sda1 /mnt # Create root ramdisk mount -t tmpfs -o size=256M /dev/ram2 /ramboot # Copy your sysimg.tar file over to the ramdisk cd /ramboot tar xf /mnt/boot/sysimg.tar umount /mnt ## Uncomment for debugging #echo "list /ramboot content" #ls /ramboot #echo "show mounted devices" #mount ... # OK, in case there's no initrd directory: # ( NOTE: The directory for the old root must exist before calling pivot_root. ) if [ ! -d /ramboot/initrd ]; then mkdir -p /ramboot/initrd fi # bye now echo "/boot/initrd.gz: exiting" pivot_root . initrd exit 0 |
Damit kann der initrd-tree neu gepackt werden.
|
# cd /tmp/slack13 # tar czvf /usr/share/mkinitrd/initrd-tree_slack13_custom.tar.gz . |
Die neu angelegten Verzeichnisse in /tmp werden nicht
mehr benötigt.
|
# cd /tmp # rm -rf slack11 # rm -rf slack13 |
Das neu erstellte Archiv /usr/share/mkinitrd/initrd-tree_slack13_custom.tar.gz
mittels Softlink systemkonform benennen.
|
# cd /usr/share/mkinitrd/ # ln -s initrd-tree_slack13_custom.tar.gz initrd-tree.tar.gz |
Als letztes muss das Script /usr/sbin/mkintrd gesichert
und wie folgt angepasst werden.
|
# cd /usr/sbin # cp mkinitrd mkinitrd00 |
# /usr/sbin/mkintrd # line 87 ... # PAD=98 PAD=1536 ... |
initrd anlegen
Mit Hilfe des angepassten Archivs initrd-tree.tar.gz kann nun eine
initrd für den Ramdisk Router angelegt werden.
Der Aufruf von /usr/sbin/mkintrd mit Parametern bewirkt:
-dass das File /boot/initrd.gz angelegt wird,
-dass das Verzeichnis /boot/initrd-tree/ angelegt wird.
Der Aufruf von /usr/sbin/mkintrd ohne Parametern bewirkt:
-dass ein neues File /boot/initrd.gz angelegt wird, das
den Inhalt von /boot/initrd-tree übernimmt.
Mit anderen Worten: Wenn die /boot/initrd.gz erstmalig
erzeugt wird, werden die relevanten Parameter angegeben:
# mkinitrd -c -f ext2 -r /dev/sda1 -c : Clear the existing initrd tree /boot/initrd-tree -f : Specify the filesystem to use for the root partition. Use together with -r -r : Specify the device to be used as the root partition -k : Use kernel modules from the specified version -o : The file to write the initrd to, this is /boot/initrd.gz by default |
( In der hier diskutierten Konfiguration ist der Aufruf von «-f»
und «-r» nicht wirklich nötig, da die entsprechenden
Werte bereits in die Konfigurationsdatei /boot/initrd-tree/linuxrc
geschrieben wurden. )
Wenn anderseits nachträgliche Anpassungen am File /boot/initrd-tree/linuxrc
vorgenommen werden, dann muss die neue /boot/initrd.gz
mit dem folgenden Kommando erstellt werden ( ansonsten /boot/initrd-tree/
ebenfalls neu erstellt und damit überschrieben wird ):
|
# mkinitrd |
Es ist somit keine schlechte Idee, das File /boot/initrd-tree/linuxrc
nach Änderungen zumindest lokal zu sichern!
|
# cp /boot/initrd-tree/linuxrc /boot/linuxrc_current |
Hinweis: Immer wenn das /boot/initrd.gz File neu angelegt wird, muss
anschliessend lilo aufgerufen werden, damit /boot/initrd.gz
beim Booten erkannt wird.
|
# lilo |
Damit ist das System derart vorbereitet, dass es kopiert und ins Archivfile
/boot/sysimg.tar geschrieben werden kann, das dann seinerseits
beim Booten in die Ramdisk entpackt wird.
Dafür steht das folgende Script /boot/create_rtr05_bootimg.sh
zur Verfügung.
Anmerkung: Die Kopieroption -x (--one-file-system) bewirkt, dass der Kopiervorgang
nur innerhalb des lokalen Filesystems stattfindet, und dass gemountete
Filesysteme nicht kopiert werden. Damit werden die Pseudofilesysteme
/proc und /sys nicht kopiert und es wird auch
vermieden, dass cp versucht, das kopierte System rekursiv
erneut zu kopieren, denn die Kopie wird in eine Ramdisk geschrieben und
diese besitzt ein tmpfs. Es ist somit möglich, ein
laufendes System korrekt und vollständig zu kopieren (eine
nützliche Erkenntnis, denn damit ist es auch möglich ein
beliebiges System, beispielsweise einen Server, im laufenden Betrieb
zu sichern).
#!/bin/sh
#
# /boot/create_rtr05_bootimg.sh
#
# First completed 2015-12-26
# Last changed 2016-02-24
#
# rolf.burkart@linuxrouter.ch
#
# Description:
# Script takes an OS snapshot, and writes it to /boot/sysimg.tar
#
# Usage:
# Run script as root to create a tar archive of your current
# router OS. Run this script again after making changes to
# the parent OS to update the ramdisk system as well.
#
# ==============================================
# User variables
# ==============================================
#
FSTAB_STD="/etc/fstab.std"
FSTAB_RAMBOOT="/etc/fstab.ramboot"
RC6_STD="/etc/rc.d/rc.S.std"
RC6_RAMBOOT="/etc/rc.d/rc.S.ramboot"
BOOT="/boot"
RAMDISK="/mnt/ramdisk"
RAMDISK_SIZE="256M"
SYSIMG="sysimg.tar"
SHELLSCRIPT_PATH="/boot/create_rtr05_bootimg.sh"
LOG_PATH="/var/log"
#
# ==============================================
# Code section
# ==============================================
#
# Check if fstab files exist.
if [ ! -f ${FSTAB_STD} ]; then
echo "File ${FSTAB_STD} does not exist. Aborting... "
exit 1
fi
if [ ! -f ${FSTAB_RAMBOOT} ]; then
echo "File ${FSTAB_RAMBOOT} does not exist. Aborting... "
exit 1
fi
# Check if rc.S files exist.
if [ ! -f ${RC6_STD} ]; then
echo "File ${RC6_STD} does not exist. Aborting... "
exit 1
fi
if [ ! -f ${RC6_RAMBOOT} ]; then
echo "File ${RC6_RAMBOOT} does not exist. Aborting... "
exit 1
fi
# Check for leftovers from previous runs.
if [ -f ${BOOT}/${SYSIMG} ]; then
echo "Removing old ${BOOT}/${SYSIMG}... "
rm ${BOOT}/${SYSIMG}
fi
# Clear logfiles of parent system.
cat /dev/null > ${LOG_PATH}/cron
cat /dev/null > ${LOG_PATH}/debug
cat /dev/null > ${LOG_PATH}/lastlog
cat /dev/null > ${LOG_PATH}/messages
cat /dev/null > ${LOG_PATH}/ntp.log
cat /dev/null > ${LOG_PATH}/secure
cat /dev/null > ${LOG_PATH}/syslog
cat /dev/null > ${LOG_PATH}/wtmp
# Create mountpoint for ramdisk if it does not exist.
if [ ! -d ${RAMDISK} ]; then
mkdir ${RAMDISK}
echo "Ramdisk mountpoint ${RAMDISK} created."
fi
echo "Switching fstab to fstab.ramboot... "
ln -sf ${FSTAB_RAMBOOT} /etc/fstab
echo "Switching rc.S to rc.S.ramboot... "
ln -sf ${RC6_RAMBOOT} /etc/rc.d/rc.S
echo "Mounting ramdisk on ${RAMDISK}... "
mount -t tmpfs -o size=${RAMDISK_SIZE} tmpfs ${RAMDISK}
echo "Copying system to ${BOOT}/${SYSIMG} ... "
exec 3>&1
exec 1>/dev/null
cd /
# The --one-file-system option 'x' ask the cp command not
# to cross mount points and stay in local file system when copying
# files and directories. So "/sys, /proc, /mnt/ramdisk" will not be copied.
cp -vax /. ${RAMDISK}/.
cp -vax /dev/. ${RAMDISK}/dev/.
rm ${RAMDISK}/${SHELLSCRIPT_PATH}
cd ${RAMDISK}
tar -cf ${BOOT}/${SYSIMG} ./
cd /
exec 1>&3
echo "Switching fstab and rc.S back to std... "
ln -sf ${FSTAB_STD} /etc/fstab
ln -sf ${RC6_STD} /etc/rc.d/rc.S
echo "Umounting ramdisk... "
umount ${RAMDISK}
echo "done"
exit 0
|
/boot/sysimg.tar erzeugen und Ramdisk Router booten.
|
# cd /boot # chmod 0770 create_rtr05_bootimg.sh # ./create_rtr05_bootimg.sh # telinit 6 |
Eine Systemsicherung des Ramdisk Routers lässt sich dank der SSD sehr
einfach durchführen. Den Router in die Ramdisk booten, anschliessend
kann das Grundsystem problemlos auf eine freie Partition − beispielsweise
nach /dev/sda6 − oder auf einen USB Stick kopiert werden.
Vorgehen:
Grundsystem und freie Partition mounten.
|
# mount /dev/sda1 /mnt # mkdir /vol_b # mount /dev/sda6 /vol_b |
/mnt/boot/sysimg.tar braucht nur Platz und muss nicht gesichert werden.
|
# mv /mnt/boot/sysimg.tar /vol_b |
Wenn der Backup nicht auf der SSD des Routers verbleiben soll, einen USB Stick mounten.
|
# mount /dev/sdb1 /media/usb |
System kopieren.
|
# cd /mnt # tar -czSpv --numeric-owner --atime-preserve -f /media/usb/slack11_lnxrtr_v05_2019-01-02.tar.gz ./ |
sysimg.tar an seinen Platz zurückkopieren und /dev/sda1 umounten.
|
# mv /vol_b/sysimg.tar /mnt/boot # umount /mnt |
Ausgangszustand wiederherstellen, vol_b wird nicht mehr gebraucht. USB Stick umounten.
|
# umount /vol_b # rmdir /vol_b # umount /media/usb |
Den Backup im feuer- und erdbebensicheren Panzerschrank verwahren.
;-)
| Prev | Home | |
| IPv6 Router | Content | That's all folks |