shell auf Home Assistant und ssh

Bei meinen ersten Versuchen mit Home Assistant stieß ich immer wieder auf Anleitungen, die neue Software installiert haben. Für die Installation ist aber eine root-Shell notwendig. Für alle, die wie ich danach gesucht haben, gibt es nun diesen kleinen Artikel.

Mein Home Assistant läuft als VM unter Proxmox. Dieser gewährt einem Zugriff auf die Console. Dort läuft allerdings „nur“ die Home Assistant Kommandozeile. Diese erlaubt aber nur einen eingeschränkten Befehlsumfang und erst recht keine Softwareinstallationen. Ein „help“ (oder „ha help“) zeigt verfügbare Befehle. Dieser Befehl zeigt aber nicht alle Befehle an.

Einer der Befehle, die nicht aufgeführt werden, ist der „login“ Befehl. Dieser öffnet eine root-Shell, in meiner Installation eine ash. Aber leider leider ist diese Webshell noVNC alles andere als komfortabel.

  • das Tastaturlayout ist auf US eingestellt
  • kein Copy und Paste möglich
  • wirkt träge

Allein deswegen lohnt sich schon einen ssh-Zugang einzurichten. Es gibt den einfachen Weg über das Add-on „Advanced SSH & Web Terminal“. Es spricht nicht viel dagegen, es zu benutzen, aber es ist halt ein Add-on, sollte Home Assistant mal nicht starten, stehen die Chancen gut, dass es auch nicht startet. Der etwas härtere Weg ist den bereits vorhandenen dropbear-SSH-Server zu aktivieren. Der ist eigentlich für Entwickler gedacht.

Also Obacht, nach dem Einrichten habt Ihr eine root-Shell, die direkt auf das System geht. Damit könnt ihr allerhand kaputt machen. Für weitere Informationen siehe den Artikel Debugging the Home Assistant Operating System. Seid gewarnt.

Eigentlich geht das recht schnell

  1. Schlüsselpaar erzeugen
  2. Die Datei .ssh/authorized_keys auf Home Assistant erzeugen
  3. dropbear starten

Schüsselpaar erzeugen

Unter Windows bietet sich putty an. Zur Sammlung gehört das Werkezug PuTTYgen um ein Schlüsselpaar zu erzeugen. FÜr Linux verweise ich auf meinen Blogartikel über ssh.

Die Datei .ssh/authorized_keys auf Home Assistant erzeugen

Der Task klingt easy, vielleicht ist er das auch, aber nicht für mich. Die oben erwähnte Anleitung geht davon aus, dass wir eine echte Maschine haben, in der wir einen speziellen USB-Stick stecken können. Auf diesen kopiert man den öffentlichen Schlüssel in Form der „authorized_keys“ Datei. Über „ha os import“ importiert Home Assistant dann den Schlüssel.

Nun ja, ich habe keinen USB-Stick, keine echte Maschine, sondern einen Proxmox-Server. Vermutlich könnte man den USB-Stick an den Proxmox Rechner stecken und diesen dann durchreichen. Vielleicht. Keine Ahnung. Vielleicht ginge es auch erst das erwähnte Add-on zu installieren. EIgentlich will ich ja nur knapp 400 Byte auf die Maschine kopieren.

Da Copy und Paste nicht funktioniert, kam ich auf die glorreiche Idee, einen Makrorekorder zu verwenden, der den Schlüssel Zeichen für Zeichen überträgt. Meine Wahl fiel auf AutoHotkey. Das klappt tatsächlich hat aber einige Fallstricke.

Erwähnte ich schon, dass die Webshell träge ist? 400 Byte einfach rüberpusten ist nicht. Also immer schön in Häppchen rüberschicken.

Erwähnte ich schon, dass das Tastaturlayout nicht deutsch ist? Hat euer Public Key ein „z“ wird daraus ein „y“ und umgekehrt. Hat euer Schlüssel ein „+“ solltet ihr ein „`“ schicken. Damit AutoHotkey das auch verschickt, braucht man zwei davon. Für mehr Spaß schaut hier.

Die Makrodatei sah dann so aus

Sleep 3000
Send „sshßrsa AAAA“
Sleep 1000
Send „yy„“

Die Wartezeiten sind notwendig, um die Webshell nicht zu überlasten, die ersten 3 Sekunden, damit man noch Zeit hat, in das richtige Fenster zu wechseln.

dropbear starten

Ist die Datei erstmal an Ort und Stelle, muss dropbear nur noch davon unterrichtet werden.

# systemctl start dropbear

Danach steht ein ssh-Server auf Port 22222 zur Verfügung.

Partition verschlüsseln unter Linux

ubuntu bietet bei der Installation an, sein Heimatverzeichnis verschlüsseln zu lassen. Das klappt schon gut, hat aber auch einige Nachteile. So werden die Dateien dateiweise verschlüsselt. Ein Angreifer sieht so zumindest die Anzahl der Dateien und kann Rückschlüsse auf die Größe von Dateien ziehen. Änderungen an Dateien bekommt er ebenfalls mit und beobachtet er die Dateiveränderungen lange genug, kann er Rückschlüsse auf die Art der Datei ziehen. Der Inhalt bleibt ihm zwar verborgen, aber er bekommt doch mehr Informationen, als einen lieb und bewusst sein mag.
dm-crypt verschlüsselt Partions- oder Festplattenweise. Was auf der Platte tatsächlich gespeichert ist, bleibt einem Angreifer verborgen. Er sieht zwar auch Änderungen in der Partition, kann diese aber nicht einzelnen Dateien zuordnen. Er kann nicht sagen, ob Daten hinzu, geändert oder gelöscht worden sind. Mehr noch: Er kann nicht einmal sagen, ob die Partition verschlüsselt ist oder nur Datenmüll enthält. Ein wichtiger Unterschied zum dateiweisen Verschlüsseln.

dm-crypt ermöglicht es, unter Linux ganze Partitionen zu verschlüsseln. Dabei erzeugt dm-crypt eine Schicht zwischen ursprünglichem Gerät und dem neu erstellten Mapping-Gerät. Es entsteht also quasi ein neues Gerät, welches für den Rest des Systems transparent genutzt werden kann. Sprich der Benutzer sieht ein ganz normales Dateisystem, nur das eben alle Daten verschlüsselt abgelegt sind.
Die Einrichtung ist schön einfach. Als Beispiel sei hier mein Ubuntu 12.04 gewählt. Das benötigte Paket cryptsetup sollte schon installiert sein. Letzter Hinweis, bevor es wirklich losgeht. Als Gerätename verwende ich /dev/sdX. Das sollte auf keinem Rechner existieren und ist durch das richtige Gerät zu ersetzen, z.B. /dev/sda1. Da viele Leute einfach copy und paste die Kommandos übernehmen, könnte das böse Folgen haben. Zur Sicherheit daher: Macht ein Backup 🙂 …

Cryptgerät erzeugen

Ich will dm-crypt in Reinkultur, d.h. ohne luks oder dergleichen verwenden. Luks schreibt einen Header am Anfang der Partition. Der verrät die verschlüsselten Daten. Vielleicht ein wenig Paranoia. Die dazu verwendeten Schlüssel speichere ich in einer Schlüsseldatei.

tocs@client:~$ dd if=/dev/random of=secret.key bs=1c count=512
tocs@client:~$ sudo cryptsetup create --key-file secret.key secdevice /dev/sdX
tocs@client:~$ ls -l /dev/mapper/
crw------- 1 root root 10, 236 Aug 24 19:40 control
lrwxrwxrwx 1 root root 7 Aug 24 22:15 secdevice -> ../dm-0
tocs@client:~$ sudo mkfs.ext4 -m 0 -L secret /dev/mapper/secdevice
...
tocs@client:~$ sudo mount /dev/mapper/secdevice /mnt

Das dd-Kommando erzeugt den eigentlichen Schlüssel. sudo cryptsetup create erzeugt ein verschlüsseltes Gerät unter /dev/mapper. Das wars eigentlich schon. Das neue Gerät kann jetzt ganz normal benutzt werden, z.B. mit einem Dateisystem formatiert werden und anschließend eingebunden werden.
Die Sicherheit steckt natürlich im verwendeten Schlüssel. Gerät sie in falsche Hände, sind alle Daten ungeschützt. Geht sie verloren, sind alle Daten weg.
Die Datei liegt ungesichert rum. Sucht also einen sicheren Ort dafür.

Informationen anzeigen lassen

tocs@client:~$ sudo cryptsetup status secdevice
  type:    PLAIN
  cipher:  aes-cbc-essiv:sha256
  keysize: 256 bits
  device:  /dev/sdX
  offset:  XXXXX sectors
  size:    XXXXX sectors
  mode:    read/write

Cryptgerät aushängen

tocs@client:~$ sudo umount /dev/mapper/secdevice
tocs@client:~$ sudo cryptsetup remove secdevice

Um es später wieder einzuhängen, muss es wieder erzeugt werden

tocs@client:~$ sudo cryptsetup create --key-file secret.key secdevice /dev/sdX

Public Key Verfahren mit ssh

ssh ist ein extrem hilfreiches Programm, um entfernte Rechner zu administrieren. Mit Benutzernamen und Passwort bekommt man eine shell auf dem Zielsystem. Passwörter haben jedoch immer das Problem, das sie zu einfach sind und deswegen erraten werden können oder zu kompliziert, dass sie sich keiner, nicht mal der legitime Nutzer, merken kann. Um ohne Passwort aber dennoch sicher, sogar sicherer als mit Passwort, auf den gewünschten Rechner zu kommen, bietet ssh das Public-Key-Verfahren an.

Die Einrichtung des Public Key Verfahrens habe ich auf meiner Seite über ssh erklärt. In Verbindung mit dem ssh-agent muss sich nur noch ein Passwort gemerkt werden, welches auch nur noch einmal eingegeben werden muss. Und dann ist alles ganz einfach.

tocs@client:~$ ssh 'root@server'
Welcome to server :)

Ich kann nur noch mal davor warnen, dem privaten Schlüssel keine bzw. eine leere Passphrase zu vergeben. Aus Komfortsicht ist natürlich erstmal nichts gewonnen. Ob man nun für den privaten Schlüssel eine Passphrase oder für den Benutzer ein Passwort eingeben muss, ist für den Anwender das Gleiche. Das stimmt, aber es ist ein zusätzlicher Sicherheitsgewinn. Der private Schlüssel gilt quasi als Berechtigungskarte, mit der jeder, der im Besitz dieser Datei ist, Zugang zum Server erhält. Geht diese verloren ist der Server offen. Mit einer zusätzlichen Passphrase ist der Schlüssel erstmal geschützt. Mit Hilfe des ssh-agents kann der Komfort deutlich gesteigert werden. Die Einrichtung ist ebenfalls auf meiner ssh-Seite beschrieben.

ssh-agent und kde

Die Schlüssel müssen bei jedem Anmelden dem ssh-agent erneut übergeben werden. Das geht prima manuell, Konsole auf, ssh-add, Passphrase eingeben und Konsole wieder schliessen. Soll dies dann doch lieber automatisch geschehen, kann im Autostart von kde ein Skript hinterlegt werden, welches bei jedem Anmelden durchlaufen wird. ssh-add würde dann aber auf der Konsole, die schwer erreichbar ist, nach der Passphrase fragen. Für dieses Problem gibt es ksshaskpass, welches ein Fenster öffnet und nach der Passphrase fragt. Außerdem könnte man die Passphrase auch gleich im kwallet speichern, so dass man die Passphrase nur ein einziges Mal eingeben muss. Aber das machen wir ja nicht 🙂

#!/bin/bash
export SSH_ASKPASS=/usr/bin/ksshaskpass
/usr/bin/ssh-add

Die Datei legen wir unter .kde/Autostart/ssh-add.sh an. Je nach Distribution kann das Verzeichnis auch .kde4 heißen. Auf jeden Fall sollte sie aber ausführbar sein.

ssh und sudo

Der ssh-agent ist schon eine große Hilfe beim Umgang mit ssh-Schlüsseln. Mit diesem kann mein aktueller Benutzer auf andere Rechner zugreifen. Benötigt ein Programm erweiterte Rechte so kann dies unter Ubuntu per sudo ausgeführt werden und erhält so kurzfristig root-Rechte. Aus Sicherheitsgründen kann dieses Programm erstmal nicht mit dem ssh-agemt kommunizieren und erhält damit keinen Zugriff auf die Schlüssel.
Zum Glück kann ja fast alles unter Linux konfiguriert werden. sudo setzt sämtliche Umgebungsvariablen des Benutzers zurück, unter anderm auch die Variable SSH_AUTH_SOCK. Diese teilt ssh mit, wo der Socket zum ssh-agent zu finden ist. Die Lösung ist daher, diese Variable ausnahmsweise weiterzugeben. Die Änderungen an der Datei /etc/sudoers sind gering.

Defaults env_reset
Defaults!DIRVISH env_keep+="SSH_AUTH_SOCK"
# Defaults env_keep+="SSH_AUTH_SOCK"
# Cmnd alias specification
Cmnd_Alias DIRVISH = /usr/sbin/dirvish, /usr/sbin/dirvish-runall

In dieser Konfiguration wird für die Kommandos /usr/sbin/dirvish und /usr/sbin/dirvish−runall (und zwar nur für diese beiden) zusätzlich die Variable SSH_AUTH_SOCK übergeben. Möchte man für alle Kommandos diese Variable weitergeben, kommentiert man die zweite Defaults-Zeile wieder ein.
Diese Lösung funktioniert nur bei einem sudo um root-Rechte zu erlangen. Der Socket des ssh-agent hat nämlich eine 600 als Rechtemaske. Somit kommt nur root und der Besitzer an diesen Socket.

ssh

Die SecureSHell (ssh) eignet sich hervorragend um entfernte Rechner, z.B. Server, zu administrieren. ssh besteht aus zwei Komponenten, dem Client ssh und dem Server sshd. Dazu gesellen sich viele kleine Helfertools.

Public Key Verfahren

Bei dem Public Key Verfahren authentifiziert sich der Benutzer nicht mit seinem Namen und Passwort, sondern es wird ein asymmetrische Verschlüsselungsverfahren genutzt. Der Benutzer erzeugt für jeden Client einen eigenes Schlüsselpaar, bestehend aus privaten und öffentlichen Schlüssel. Der private Schlüssel dient dann als Berechtigung gegenüber dem Serversystem.

Schlüssel erzeugen

Zunächst muss der Benutzer die Schlüssel auf dem Clientrechner erzeugen. Dazu dient das Programm ssh-keygen. Das Programm fragt nach einen Dateinamen für den erzeugten Schlüssel. Dieser kann im allgemeinen bestätigt werden, es sei denn man möchte mehrere Schlüssel für unterschiedliche Server erstellen. Die Passphrase schützt den privaten Schlüssel vor Missbrauch, sie sollte daher nicht leer sein. Sie muss bei jeder Benutzung eingegeben werden. Später werde ich ergänzen, wie man das umgehen kann 🙂

tocs@client:~$ ssh-keygen -t rsa 
Generating public/private rsa key pair. 
Enter file in which to save the key (/home/tocs/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/tocs/.ssh/id_rsa. 
Your public key has been saved in /home/tocs/.ssh/id_rsa.pub. 
The key fingerprint is: 38:0e:0a:fe:6f:f3:e1:7e:90:e5:5e:37:3f:dc:6f:51 tocs@client 
The key's randomart image is: 
+--[ RSA 2048]----+
|                 |
|                 |
|                 |
|       . .      E|
|.   . o S       .|
|.. . o + . . o . |
| ..   ..o . . + o|
|  .  o. .o     +o|
|   .o.++.      .+|
+-----------------+

Öffentlichen Schlüssel verteilen

Der private Schlüssel verbleibt immer auf dem Client. Den öffentlichen darf bzw. muss man verteilen. Dabei hilft das Programm ssh-copy-id.

tocs@client:~$ ssh-copy-id -i ~/.ssh/id_rsa.pub root@server
root@server's password:
Now try logging into the machine, with "ssh 'root@server'", and check in:
  ~/.ssh/authorized_keys
to make sure we haven't added extra keys that you weren't expecting.

Testen des Public Key Verfahren

ssh-copy-id legt nahe, man solle die Verbindung nun testen und den Inhalt von ~/.ssh/authorized_keys prüfen. Dieser sollte identisch mit der Datei .ssh/id_rsa.pub auf dem Client sein.

tocs@client:~$ ssh 'root@server'
Enter passphrase for key '/home/tocs/.ssh/id_rsa':
Welcome to server :)
root@server:~# cat .ssh/authorized_keys

Verwaltung vereinfachen

tocs@endor:~$ ssh-add -l
The agent has no identities.
tocs@endor:~$ ssh-add
Enter passphrase for /home/tocs/.ssh/id_rsa:
Identity added: /home/tocs/.ssh/id_rsa (/home/tocs/.ssh/id_rsa)

Noch mehr vereinfachen

.kde/Autostart/ssh-add.sh
#!/bin/bash
export SSH_ASKPASS=/usr/bin/ksshaskpass
/usr/bin/ssh-add
WordPress Cookie Hinweis von Real Cookie Banner