Howto: Inserting an USB-Stick triggers a call of the encryption-program on an active ssh-connection

Ich habe mir einen hardwareverschlüsselten USB-Stick gekauft und besitze einen Homerserver, auf dem Debian läuft, er routet und dient auch als Fileserver. Manche Daten sind sensibel, deshalb sind sie mit LUKS/cryptsetup und einem KeyFile, was damals auf einem softwareverschlüsselten USB-Stick lag, verschlüsselt.

Jetzt möchte ich natürlich meinen neuen USB-Stick möglichst komfortabel als Schlüsselablage verwenden, da es auch eine (nicht supportete, da beta) Firmware für Linux gibt.

Ziel

Wenn in den Server ein bestimmter, hardwareverschlüsselter USB-Stick gesteckt wird, wird auf einer gleichzeitig aktiven SSH-Verbindung automatisch der Befehl zum Entschlüsseln aufgerufen, so dass der User sofort sein Passwort eingeben kann.

Howto

Automatisches Mounten

udev

Ersteinmal muss dafür gesorgt werden, dass der Stick automatisch gemountet wird. Dafür habe ich folgende udev-Regeln in /etc/udev/rules.d/50-safestick.rules angelegt.

# Mount the SafeStick Login Partition
ACTION=="add", PROGRAM=="/sbin/blkid -o value -s TYPE %N", RESULT=="iso9660", ATTRS{product}=="SafeStick BE", ATTRS{serial}=="070007A70AXXXXXXXXXX", RUN="/bin/mkdir -p '/mnt/SafeStick Login'", RUN+="/bin/mount '/mnt/SafeStick Login'", RUN+="/root/cryptstick/sendUnlockCommandToTTY /dev/ttyp1 '/mnt/SafeStick\ Login/safestick'"

# When unlocked, mount the SafeStick partition under /mnt/cryptsafestick
ACTION=="add", PROGRAM=="/sbin/blkid -o value -s UUID %N", RESULT=="958E-XXXX", ATTRS{product}=="SafeStick BE", ATTRS{serial}=="070007A70AXXXXXXXXXX", RUN="/bin/mkdir -p /mnt/cryptsafestick", RUN+="/bin/mount /mnt/cryptsafestick"

# When the encrypted part is locked, unmount (if possible) and remove dir
ACTION=="remove", ENV{ID_SERIAL_SHORT}=="070007A70AXXXXXXXXXX", ENV{ID_FS_UUID}=="958E-XXXX", RUN="/bin/umount -l '/mnt/cryptsafestick'", RUN+="/bin/rmdir /mnt/cryptsafestick", RUN+="/usr/bin/touch /tmp/wanttoumountcryptsafestick"

# When the disk is locked again, unmount and remove dir
ACTION=="remove", ENV{ID_MODEL}=="SafeStick_BE", ENV{ID_SERIAL}=="BM_SafeStick_BE_070007A70AXXXXXXXXXX", RUN+="/bin/umount -l '/mnt/SafeStick Login'", RUN+="/bin/rmdir '/mnt/SafeStick Login'", RUN+="/usr/bin/touch /tmp/wanttoumountsafesticklogin"

Vorher musste ich natürlich die entsprechenden Werte für ATTRS{serial} etc. herausfinden. Das geht leicht mit dem Befehl udevadm monitor –udev –environment. Steckt man das Gerät an, sieht man etliche Einträge, für mich hat immer der letzte Abschnitt gereicht. Beim Entfernen passiert das Gleiche.

Die Ausgabe ist zum Beispiel folgende:

...

UDEV  [1282423118.665737] remove   /devices/pci0000:00/0000:00:03.3/usb1/1-1 (usb)
UDEV_LOG=3
ACTION=remove
DEVPATH=/devices/pci0000:00/0000:00:03.3/usb1/1-1
SUBSYSTEM=usb
DEVTYPE=usb_device
DEVICE=/proc/bus/usb/001/054
PRODUCT=1dfa/3327/110
TYPE=0/0/0
BUSNUM=001
DEVNUM=054
SEQNUM=49420
DEVNAME=/dev/bus/usb/001/054
ID_VENDOR=BM
ID_VENDOR_ENC=BM
ID_VENDOR_ID=1dfa
ID_MODEL=SafeStick_BE
ID_MODEL_ENC=SafeStick\x20BE
ID_MODEL_ID=3327
ID_REVISION=0110
ID_SERIAL=BM_SafeStick_BE_070007A70AXXXXXXXXXX
ID_SERIAL_SHORT=070007A70AXXXXXXXXXX
ID_BUS=usb
ID_USB_INTERFACES=:080650:
MAJOR=189
MINOR=53
DEVLINKS=/dev/char/189:53

Wie man sieht, sind hier alle Werte enthalten, die man ENV{ID_SERIAL}, ENV{ID_MODEL}, ENV{ID_FS_UUID} benötigt. Man kann natürlich auch die etwas udev-üblicheren ATTRS-Attribute benutzen, allerdings habe ich festgestellt, dass einige davon beim Entfernen nicht gesetzt werden und daher nicht als Entscheidungskriterium um welches Gerät es sich nun handelt, benutzt werden können. Deshalb habe ich mich für die in den obigen Regeln entschieden.

  • ATTRS{serial} und ENV{ID_SERIAL_SHORT} enthalten die Seriennummer des Gerätes.
  • ENV{ID_SERIAL} enthält die Seriennummer, sowie den Hersteller.
  • ENV{ID_FS_UUID} ist die UUID des entschlüsselten Devices.
  • /sbin/blkid -o value -s UUID %N gibt auch die UUID des entschlüsselten Devices zurück. Weißt man diesen Befehl PROGRAM zu, kann mit RESULT==”958E-XXXX” überprüft werden, ob es sich um das erwartete Gerät handelt.
  • Analog funktioniert die Abfrage, ob es sich um ein ISO9660 Dateisystem handelt. Das ist der Fall bei dem nicht verschlüsselten Teil des USB-Sticks, auf dem sich unter anderem das Programm zum Entschlüsseln befindet.
  • Wichtig: Der Pfad zur Konsole auf der sich eingeloggt wird – hier /dev/ttyp1 – muss möglicherweise auf die jeweilige Umgebung angepasst werden. Man findet ihn heraus, in dem man sich per SSH auf seinem Server einloggt und dann tty eintippt. Möchte man den Safestick in den USB-Port stecken, sollte nur eine gleichzeitige SSH-Verbindung zum Server existieren, nur so ist eindeutig, auf welcher Konsole das Programm geöffnet wird.
  • Weitere Werte sollten selbsterklärend sein, ich beantworte natürlich auch gerne weitere Fragen. 🙂

fstab

Damit in den udev-Regeln mount <mountpoint> ohne <device> klappt, muss auch /etc/fstab um folgende Einträge ergänzt werden:

/dev/disk/by-label/SafeStick\x20Login   /mnt/SafeStick\040Login auto    defaults,noauto 0 0
/dev/disk/by-uuid/958E-07FD     /mnt/cryptsafestick     auto    defaults,noauto,sync,umask=077,ro       0 0

Wichtig ist vor allem, dass das Leerzeichen im Label des SafeSticks durch \x20 ersetzt wird, bzw. das des Mountpoints durch \040. Die anderen Werte können je nach Geschmack gesetzt werden, ich möchte zum Beispiel, dass das verschlüsselte Verzeichnis nur von root lesbar ist und readonly gemountet wird. Wie man sieht, benötigt man in der zweiten Zeile die UUID der verschlüsselten SafeStick-Partition.

Start der Passwortabfrage

Um die Passwortabfrage auf dem entfernten Rechner zu starten, habe ich folgendes c-Programm geschrieben.

/* Sends the command in the second argument to
 * the terminal listening on the first argument to unlock the
 * safestick.
 * 2010/08/20, Sebastian Koettinger, http://blog.veltrus.de
*/

#include 
#include <sys/ioctl.h>
#include 
#include 
#include 

int errno;

int main(int argc, char *argv[])
{

 /*
 * Edit this to variables
 */
 /*char * pathToBinary = "/mnt/SafeStick\\ Login/safestick";
 char * pathToTty = "/dev/ttyp0";
*/

 /*
 * Please do not change something
 * in the following code if you do not know
 * what you do
 */
 int f;
 char *c;

 if (argc > 3)
 {
 fprintf(stderr, "Usage: %s  \n", argv[0]);
 exit(1);
 }
 if ((f = open(argv[1], O_RDWR)) == -1)
 {
 perror("open");
 exit(errno);
 }
 for (c=argv[2]; *c; c++) /* Sends the command char by char to tty */
 if (ioctl(f, TIOCSTI, c) == -1)
 {
 perror("ioctl");
 exit(errno);
 }
 if (ioctl(f, TIOCSTI, "\n") == -1) /* Execute by sending newline */
 {
 perror("newline ioctl");
 exit(errno);
 }

 exit(0);
}

Das kann einfach mit gcc openSafestickLoginInTTY.c -o sendUnlockCommandToTTY kompiliert und in /root/cryptstick/sendUnlockCommandToTTY kopiert werden.

Fertig

Nun sollte immer, wenn man den SafeStick in den USB-Port des Servers steckt, der Befehl zum Entschlüsseln an die derzeit aktive SSH-Verbindung geschickt werden, das Passwort muss dann natürlich noch manuell eingegeben werden. 😉

Das Programm und die Regeln gibt es hier zum Download:

Fragen beantworte ich gern,
viel Spaß beim Ausprobieren!

  1. No comments yet.

  1. No trackbacks yet.

 

Durch die weitere Nutzung der Seite stimmst du der Datenschutzerklärung,
dem Haftungsausschluss und der Verwendung von Cookies zu. Weitere Informationen

Die Cookie-Einstellungen auf dieser Website sind auf "Cookies zulassen" eingestellt, um das beste Surferlebnis zu ermöglichen. Wenn du diese Website ohne Änderung der Cookie-Einstellungen verwendest oder auf "Akzeptieren" klickst, erklärst du sich damit einverstanden.

Schließen