X-Server
xauth - Starten von X-Programmen als root auf dem Desktop des angemeldeten Benutzers
« zurück (Gesammelte Anleitungen)
Alt: Host-basierte Authentifizierung
Alle aktuellen Linux Distributionen haben bei einer Standardinstallation den X-Server so konfiguriert, dass dieser nicht auf einem TCP-Socket lauscht.
Konkret geschiet das durch den Start des X-Server mit der Option -nolisten tcp
. Diese Sicherheitsmaßnahme hat einen
unkomfortablen Nebeneffekt: Die Host-basierte Authentifizierung via xhost à la
$ xhost +oder auch restriktiver (nur für den host
remotepc
)
$ xhost remotepc
des aktuell am X-Windows angemeldeten Benutzers reicht nicht mehr aus, um entfernte X-Anwendungen auf dem lokalen Display zu starten. Da dieser Mechanismus aus Sicherheitsgründen nicht mehr verwendet wird, gehe ich hier nicht weiter darauf ein.
Die Freigabe eines X-Displays erfolgt nun über eine Art Passwort, dass in dem X-Cookie (Keks) gespeichert ist. Ist man im Besitz des passenden
Kekses in seiner Datei ${HOME}/.Xauthority
, erhält man Zugriff auf das entsprechende X-Display. Die Steuerung mit dem
Kommando xauth
steht weiter unten beispielhaft beschrieben.
Aufbau der X-Displays
Die Bezeichnung eines X-Displays, bekannt aus der Umgebungsvariable DISPLAY
, folgt dem Schema
DISPLAY={Hostname}:{Nummer des X-Servers}.{Subdisplay}
Somit ist z.B.
DISPLAY=localhost:0.0 DISPLAY=:0.0
der erste laufende X-Server. Ist der Hostname leer, handelt es sich auch um localhost.
Wird ein weiterer X-Server (z.B. mit xinit) gestartet, bekommt dieser dann die Nummer 1:
localhost:1.0
Werden von einem X-Server mehrere Monitore verwendet (Xinerama), sind die Monitore als Subdisplays konfiguriert, die wiederum durchnummeriert werden:
localhost:2.0 # 3. laufender X-Server, linker Bildschirm localhost:2.1 # 3. laufender X-Server, rechter Bildschirm
Möchte man nun eine X-Anwendung auf einem anderen Rechner starten, kann man die Umgebungsvariable DISPLAY
entsprechend
setzen:
export DISPLAY=remotepc:0.0
Damit werden alle aus dieser Shell gestarteten X-Anwendungen, die Berechtigung vorausgesetzt, auf dem ersten X-Server von dem Rechner remotepc dargestellt. Diese Übertragung ist aber komplett unverschlüsselt und somit nur in vertrauenswürdigen Netzen zu empfehlen. Eine einfache und sichere Möglichkeit, entfernte Anwendungen auf dem lokalen Rechner zu starten, stellt SSH bereit, das im Folgenden beschrieben wird.
X-Forwarding mit SSH
Möchte ein Anwender nun auf einem entfernten Rechner einzelne X-Anwendungen nutzen, ohne sich über XDMCP oder via VNC dort anzumelden, kann sich dieser über einen Shellzugang via SSH die Anwendungen auf sein lokales Display holen. Hierbei wird bei dem Öffnen der SSH-Sitzung, die Option -X verwendet, die ein neues Display definiert, dass durch die verschlüsselte Verbindung getunnelt wird und auf der anderen Seite an das lokale Display weitergereicht wird. Somit findet die gesammte Kommunikation durch einen verschlüsselten Kanal statt.
Ein Beispiel mit Bild sagt mehr als 1000 Worte...
Auf der rechten Seite sind zwei vernetzte PCs dargestellt. Die X-Displays sind als farbige Punkte dargestellt. Der Benutzer hat jeweils einen Shell-Zugang
auf dem Arbeits- und dem Remote-PC. Auf dem lokalen Arbeits-PC läuft eine X-Sitzung (z.B. KDE). Jetzt loggt der Benutzer
sich in einem Terminalfenster via SSH und aktivem X-Forwarding (Option -X) auf dem Remote-PC ein, wobei ein neues X-Display
geöffnet wird. Ferner gibt es noch eine laufende X-Sitzung auf dem Remote-PC, die hier nicht weiter betrachtet wird.
Der Benutzer hat die Berechtigung, X-Anwendungen auf dem lokalen X-Display zu starten und durch den SSH-Tunnel können Programme auf dem Remote-PC gestartet und auf den lokalen X-Server umgeleitet werden. Die Übertragung zwischen den beiden PCs findet verschlüsselt statt.
root: Zugriff verweigert
Der Superuser root stößt selten an Berechtigungsgrenzen, aber in diesem Falle heißt es aber auch für ihn: Draußen bleiben!
Wenn der Benutzer nun auf dem Remote-PC via su
zum root-User wechselt und eine eine X-Anwendung als root starten will, geht das
so ohne Weiteres nicht:
$ su password: ***** # echo $DISPLAY localhost:10.0 # xterm X11 connection rejected because of wrong authentication. X connection to localhost:10.0 broken (explicit kill or server shutdown).
Der Benutzer root hat zwar eine gesetzte Variable DISPLAY
, darf aber keine Anwendungen auf der laufenden
X-Sitzung des Benutzers starten, da er nicht den passenden Keks der laufenden Sitzung in seiner Keksdose
(/root/.Xauthority
) hat.
Aber root kann sich den Keks für die laufende Sitzung aus der Keksdose des Benutzers (/home/benutzer/.Xauthority
), auf die
er immer Zugriff hat, exportieren und seiner eigenen hinzufügen. Hierfür sind die folgenden Kommandos notwendig:
# xauth list xauth: creating new authority file /root/.Xauthority # xauth -f /home/benutzer/.Xauthority extract /tmp/keks.txt :10 # xauth merge /tmp/keks.txt xauth: creating new authority file /root/.Xauthority # xauth list remotepc/unix:10 MIT-MAGIC-COOKIE-1 12345678901234567890123456789012
Ziemlich umständlich, dass alles im Kopf zu behalten und für lokale Displays müsste man das Display :0 anstelle von :10 nehmen. Solche Entscheidungen möchte man natürlich automatisieren...
Automatischer Keksklau durch den root-User (nicht notwendig!)
Das folgende Skript ist nicht notwendig, da es wie so oft bereits eine funktionierende Lösung gibt.
Überholter Teil ausgeblendet
(+) drücken, um diesen Teil einzublenden
Im folgenden eine Hilfsfunktion, die diese Entscheidung lokal oder SSH abnimmt und z.B. in die .bashrc
von root eingebunden
werden kann:
# /etc/helper-functions.sh # ...weitere Funktionen... function root_merge_x_cookie_from_actual_user() { # paramters: none, DISPLAY must be set # return values: # 0 - ok # 1 - not root user # 2 - DISPLAY not set # 3 - no X-cookie file found # if [ $( id -u ) -eq 0 ]; then if [ ! -z "${DISPLAY}" ]; then # remove hostname hf_display=${DISPLAY##*:} # remove subdisplay hf_display=${hf_display%%.*} if [ -z "${SSH_CLIENT}" ]; then # we are local hf_xcookies=$( awk -F: /^$( who | grep " :${hf_display} " | head -1 | awk '{ print $1 }' ):/'{ print $6 }' /etc/passwd )/.Xauthority else # we are in a ssh session # tcp port of X-Server is 6000+${DISPLAY} (keep it simple) hf_xport=$(( 6000 + ${hf_display} )) # id of X-user hf_user_id=$( netstat -teln | grep ":${hf_xport} " | awk '{ print $7}' ) hf_xcookies=$( awk -F: /^[^:]*:x:${hf_user_id}:/'{ print $6 }' /etc/passwd )/.Xauthority unset hf_user_id unset hf_xport fi if [ -f "${hf_xcookies}" ]; then hf_temp="/tmp/X${hf_display}_cookie_$$.txt" xauth -f "${hf_xcookies}" extract "${hf_temp}" ":${hf_display}" if [ -r "${hf_temp}" ]; then xauth merge "${hf_temp}" rm -f "${hf_temp}" fi unset hf_temp else unset hf_display unset hf_xcookies return 3 # no cookie file fi unset hf_display unset hf_xcookies else return 2 # DISPLAY not set fi return 0 # ok else return 1 # not root user fi }
Diese Funktion ist mit sicherheit nicht perfekt und deckt nicht jeden Fall ab, sollte aber zumindest für die beiden erwähnten Fälle "su (lokal)" und "su nach SSH" funktionieren. Für Verbesserungsvorschläge bin ich natürlich dankbar.
Eingebunden in /root/.bashrc
wird die Funktion dann so:
# /root/.bashrc # ...andere Eintraege... # Hilfsfunktionen einbinden . /etc/helper-functions.sh # call function to get X cookie root_merge_x_cookie_from_actual_user # ...weitere Eintraege...
Sollte eine Anwendung mal doch nicht starten, wäre mal ein Blick auf die Variable DISPLAY
ein erster Ansatz.
# set | grep DISPLAY DISPLAY=:0.0 #
Ist die obige Ausgabe leer, gibt es keine bekannte X-Sitzung und somit kann auch kein Keks dafür ermittelt werden.
Automatischer Keksklau beim Benutzerwechsel mit sux
Es gibt ein Programm, was beim Benutzerwechsel die Authentifizierungsdaten für den X-Server automatisch mitzieht: sux
.
Einfach dieses Shell-Skript installieren und genauso verwenden, wie man es von su
gewohnt ist.
$ sux
password: *****
# echo $DISPLAY
localhost:10.0
# xterm &
(xterm Fenster wird geöffnet)