X-Server

xauth - Starten von X-Programmen als root auf dem Desktop des angemeldeten Benutzers

« zurück (X-Server)

« 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.

« nach oben

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... ;-)

X-Display via SSH-tunnel (Übersicht) 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...

« nach oben

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.

« nach oben

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)

« nach oben

« zurück (Gesammelte Anleitungen)