Wie kann ich erkennen, ob die Shell über SSH gesteuert wird?

69

Ich möchte anhand eines Shell-Skripts (genauer gesagt .zshrc) erkennen, ob es über SSH gesteuert wird. Ich habe die Variable HOST ausprobiert, aber es ist immer der Name des Computers, auf dem die Shell ausgeführt wird. Kann ich auf den Hostnamen zugreifen, von dem die SSH-Sitzung stammt? Ein Vergleich der beiden würde mein Problem lösen.

Jedes Mal, wenn ich mich anmelde, erscheint eine Meldung, die die letzte Anmeldezeit und den Host angibt:

Last login: Fri Mar 18 23:07:28 CET 2011 from max on pts/1
Last login: Fri Mar 18 23:11:56 2011 from max

Dies bedeutet, dass der Server über diese Informationen verfügt.

stribika
quelle

Antworten:

90

Hier sind die Kriterien, die ich in meinem verwende ~/.profile:

  • Wenn eine der Variablen SSH_CLIENToder SSH_TTYdefiniert ist, handelt es sich um eine SSH-Sitzung.
  • Wenn der übergeordnete Prozessname der Anmeldeshell lautet sshd, handelt es sich um eine SSH-Sitzung.
if [ -n "$SSH_CLIENT" ] || [ -n "$SSH_TTY" ]; then
  SESSION_TYPE=remote/ssh
# many other tests omitted
else
  case $(ps -o comm= -p $PPID) in
    sshd|*/sshd) SESSION_TYPE=remote/ssh;;
  esac
fi

(Warum sollten Sie dies in Ihrer Shell-Konfiguration und nicht in Ihrem Sitzungsstart testen?)

Gilles
quelle
3
Hat super funktioniert danke! github.com/balupton/dotfiles/commit/…
balupton
1
Möglicherweise möchten Sie dies in Ihrer Shell-Konfiguration tun, wenn Sie die Weiterleitung von ssh-Agenten von Ihrer Remote-Shell aus aktivieren möchten (da die Umgebungsvariablen in jeder Shell festgelegt werden müssen, von der Sie weiterleiten möchten), es sei denn, mir fehlt etwas?
Unterschreitung
@underrun Ich verstehe deinen Punkt nicht. Wenn Sie eine andere Shell in derselben Sitzung ausführen, übernimmt sie die Umgebungsvariablen, die von festgelegt wurden .profile. Und was hat das mit der Agentenweiterleitung zu tun?
Gilles
1
@underrun Wenn Sie überprüfen möchten, ob eine SSH-Agentenweiterleitung vorhanden ist, überprüfen Sie die SSH_AUTH_SOCKVariable. Aber warum sollten Sie in diesem Fall einen SSH-Agenten ausführen? Meinten Sie einen Agenten starten, wenn Sie ohne Agentenweiterleitung angemeldet sind? Warum nicht einen Agenten starten, wenn es noch keinen gibt ( [ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))?
Gilles
1
@Praxeolitic Die SSH_*Variablen werden auch in Unterprozessen einer Shell festgelegt, die sich am Anfang einer SSH-Sitzung befindet. Wenn Sie beispielsweise eine Bildschirmsitzung über SSH starten, sollten Sie die Variablen deaktivieren, bevor Sie die Sitzung starten. Ich denke, der Grund für das Testen des übergeordneten Prozesses ist, dass ich damit begonnen habe, bevor sshd Umgebungsvariablen definiert hat.
Gilles
21

Sie sollten über die überprüfen können SSH_TTY, SSH_CONNECTIONoder SSH_CLIENTVariablen.

Cakemox
quelle
1
Fügen Sie diese auch zu env_keepin hinzu sudoers, damit es subefehlsübergreifend funktioniert :)
Thomas G.
10

Ich hatte gerade das gleiche Problem in Linux mit Bash. Ich habe zuerst die Umgebungsvariable SSH_CONNECTION verwendet, dann aber festgestellt, dass sie bei Ihnen nicht gesetzt ist su -.

Die letzte Lösung funktionierte weder nach sunoch nach su -.

Schließlich verwende ich who am i, die die entfernte IP (oder den Hostnamen) am Ende zeigt, wenn es eine SSH-Verbindung ist. Es funktioniert auch nach su.

Mit regulären Bash-Ausdrücken funktioniert Folgendes:

if [[ $(who am i) =~ \([-a-zA-Z0-9\.]+\)$ ]] ; then echo SSH; else echo no; fi

Wenn zsh keine regulären Ausdrücke unterstützt, kann dasselbe auf viele verschiedene Arten mit grep, cut, sed oder was auch immer erreicht werden.

Für die Neugierigen ist unten, wofür ich dies benutze, in root's .bashrc:

    # We don't allow root login over ssh.
    # To enable root X forwarding if we are logged in over SSH, 
    # use the .Xauthority file of the user who did su

    w=$(who am i)
    if [[ $w =~ \([-a-zA-Z0-9\.]+\)$ ]] ; then
        olduser=${w/ .*/}
        oldhome=$(getent passwd $olduser | cut -d: -f 6)
        [ -f "$oldhome/.Xauthority" ] \
          && export XAUTHORITY=$oldhome/.Xauthority
    fi

Eine Alternative, die auch funktioniert, suwäre, rekursiv sshddurch die übergeordneten Prozesse zu suchen :

#!/bin/bash

function is_ssh() {
  p=${1:-$PPID}
  read pid name x ppid y < <( cat /proc/$p/stat )
  # or: read pid name ppid < <(ps -o pid= -o comm= -o ppid= -p $p) 
  [[ "$name" =~ sshd ]] && { echo "Is SSH : $pid $name"; return 0; }
  [ "$ppid" -le 1 ]     && { echo "Adam is $pid $name";  return 1; }
  is_ssh $ppid
}

is_ssh $PPID
exit $?

Wenn die Funktion zu .bashrc hinzugefügt wird, kann sie als verwendet werden if is_ssh; then ...

mivk
quelle
1
Funktioniert nicht in tmuxRemotesitzungen und weist auch Probleme auf, wenn Sie über IPv6 angemeldet sind und kein DNS-Reverse-Name vorhanden ist.
bene
@bene: was geht nicht Der reguläre Ausdruck oder who am izeigt Ihre IPv6-Adresse nicht an?
mivk
1) who am igibt in einer Remote- tmuxSitzung nichts zurück . 2) Die IPv6-Adresse enthält möglicherweise Doppelpunkte, die Ihr regulärer Ausdruck nicht zulässt. Dies könnte schwierig sein , da who am ienthält (:0.0)in X - Sitzungen für mich (xterm).
bene
@bene: Die gerade hinzugefügte alternative Lösung sollte auch mit IPv6 funktionieren. Ich weiß nichts über tmux, aber es funktioniert auch in screen.
Mivk
7

Ich denke, die Antworten von Gilles und Cakemox sind gut, aber nur der Vollständigkeit halber ...

Last login: Fri Mar 18 23:07:28 CET 2011 from max on pts/1

kommt von pam_lastlog1 .

Sie können pam_lastlogInformationen mit dem Befehl lastlog2 drucken , z

$ lastlog -u mikel  
Username         Port     From             Latest
mikel            tty1                      Fri Jan 28 10:58:10 +1100 2011

für ein lokales Login im Vergleich zu

Username         Port     From             Latest
mikel            pts/9    mikel-laptop     Sat Mar 19 11:11:58 +1100 2011

für ein SSH-Login.

Auf meinem System funktioniert dies, um es zu extrahieren

$ lastlog -u mikel | sed -ne '2{p;q}' | cut -c 27-42
mikel-laptop 

lastund wkönnte zum Beispiel auch hilfreich sein

$ TTY=$(tty)
$ last -n 1 ${TTY#/dev/} | sed -ne '1{p;q}'
mikel    pts/12       :0.0             Sat Mar 19 11:29   still logged in 


1 Linux / FreeBSD- Dokumentation für pam_lastlog.
2 Linux / FreeBSD- lastlog(8) Manpages.

Mikel
quelle
1

Sehen Sie sich zunächst Ihre Umgebung an und finden Sie die richtige Option

printenv|grep SSH
SSH_CLIENT=192.168.1.xxx
SSH_CONNECTION=192.168.1.xxx
SSH_TTY=/dev/ttys021

Sie können sich in viele dieser Umgebungsvariablen einklinken, um bestimmte Aktionen basierend auf deren Vorhandensein auszulösen.

lfender6445
quelle
-1

Hiermit können Sie alle Verbindungen anderer Benutzer mit SSH überprüfen

netstat | grep ssh
ARD
quelle
Dies ist überhaupt nicht zuverlässig.
DannyNiu