Jak mogę wykryć, czy powłoka jest kontrolowana z SSH?

69

Chcę wykryć ze skryptu powłoki (dokładniej .zshrc), czy jest on kontrolowany przez SSH. Próbowałem zmiennej HOST, ale zawsze jest to nazwa komputera, na którym działa powłoka. Czy mogę uzyskać dostęp do nazwy hosta, z której pochodzi sesja SSH? Porównanie tych dwóch rozwiązałoby mój problem.

Przy każdym logowaniu pojawia się komunikat informujący o czasie ostatniego logowania i hoście:

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

Oznacza to, że serwer ma te informacje.

stribika
źródło

Odpowiedzi:

90

Oto kryteria, których używam w moim ~/.profile:

  • Jeśli jedna ze zmiennych SSH_CLIENTlub SSH_TTYjest zdefiniowana, jest to sesja ssh.
  • Jeśli nazwa procesu nadrzędnego powłoki logowania to sshd, jest to sesja ssh.
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

(Dlaczego chcesz to przetestować w konfiguracji powłoki zamiast uruchamiania sesji?)

Gilles
źródło
3
Działa świetnie dzięki! github.com/balupton/dotfiles/commit/…
balupton
1
możesz to zrobić w konfiguracji powłoki, jeśli chcesz włączyć przekazywanie agenta ssh ze zdalnej powłoki (ponieważ zmienne środowiskowe muszą być ustawione w każdej powłoce, z której chcesz przekazywać dalej), chyba że czegoś brakuje?
underrun
@underrun Nie rozumiem, o co ci chodzi. Jeśli uruchomisz inną powłokę w tej samej sesji, odziedziczy ona zmienne środowiskowe ustawione przez .profile. A co to ma wspólnego z przekazywaniem agentów?
Gilles
1
@underrun Jeśli chcesz sprawdzić obecność przekazywania agenta SSH, sprawdź SSH_AUTH_SOCKzmienną. Ale dlaczego miałbyś w takim przypadku uruchomić agenta SSH? Czy miałeś na myśli uruchomienie agenta, jeśli jesteś zalogowany bez przekazywania agenta? Dlaczego nie uruchomić agenta, jeśli jeszcze go nie ma ( [ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))?
Gilles
1
@Praxeolitic SSH_*Zmienne są również ustawiane w podprocesach powłoki znajdującej się na czele sesji SSH, na przykład, jeśli rozpoczynasz sesję screen over SSH (jeśli to ważne, należy rozbroić zmienne przed rozpoczęciem sesji). Myślę, że powodem przetestowania procesu nadrzędnego jest to, że zacząłem to robić, zanim sshd zdefiniował jakiekolwiek zmienne środowiskowe.
Gilles,
21

Powinieneś być w stanie sprawdzić za pośrednictwem SSH_TTY, SSH_CONNECTIONlub SSH_CLIENTzmiennych.

Cakemox
źródło
1
Również dodać je do env_keepw sudoers, aby pracować w poprzek supolecenia :)
Thomas G.
10

Właśnie miałem ten sam problem w Linuksie, używając Bash. Najpierw użyłem zmiennej środowiskowej SSH_CONNECTION, ale potem zdałem sobie sprawę, że nie jest ustawiona, jeśli ty su -.

Powyższe rozwiązanie ostatniego logowania nie działało ani po, suani su -.

Wreszcie używam who am i, który pokazuje zdalny adres IP (lub nazwę hosta) na końcu, jeśli jest to połączenie SSH. Działa również po su.

Używając wyrażeń regularnych Bash, działa to:

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

Jeśli zsh nie obsługuje wyrażeń regularnych, to samo można osiągnąć na wiele różnych sposobów za pomocą grep, cut, sed lub cokolwiek innego.

Dla ciekawskich, poniżej jest to, do czego używam, w katalogu root .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

Alternatywą, która również działa, subyłoby rekurencyjne wyszukiwanie za sshdpośrednictwem procesów nadrzędnych:

#!/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 $?

Jeśli funkcja zostanie dodana do .bashrc, może być używana jako if is_ssh; then ...

mivk
źródło
1
nie działa w tmuxsesjach zdalnych i ma również problemy, jeśli jest zalogowany przez IPv6 i nie istnieje odwrotna nazwa DNS.
bene
@bene: co nie działa? Wyrażenie regularne, czy who am inie pokazuje twojego adresu IPv6?
mivk
1) who am inie zwraca niczego w tmuxsesji zdalnej . 2) Adres IPv6 może zawierać dwukropki, na które nie pozwala wyrażenie regularne. Może to być trudne, ponieważ who am izawiera (:0.0)dla mnie sesje X (xterm).
bene
@bene: Alternatywne rozwiązanie, które właśnie dodałem, powinno również działać z IPv6. Nie wiem o tmuxie, ale to też działa screen.
mivk
7

Myślę, że odpowiedzi Gillesa i Cakemoxa są dobre, ale tylko dla kompletności ...

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

pochodzi z pam_lastlog1 .

Możesz wydrukować pam_lastloginformacje za pomocą polecenia lastlog2 , np

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

dla lokalnego logowania, w porównaniu do

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

do logowania SSH.

W moim systemie działa to w celu wyodrębnienia go

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

lasti wmoże być na przykład pomocny

$ 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 dokumentacja Linux / FreeBSD dla pam_lastlog.
2 strony podręcznika Linux / FreeBSD lastlog(8) .

Mikel
źródło
1

Zacznij od spojrzenia na swoje środowisko i znalezienia właściwej opcji

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

Możesz podłączyć wiele z tych zmiennych środowiskowych, aby wywoływać określone działania na podstawie ich obecności.

lfender6445
źródło
-1

Ma to na celu sprawdzenie wszystkich ustanowionych połączeń od innych użytkowników korzystających z SSH

netstat | grep ssh
ARD
źródło
To wcale nie jest wiarygodne.
DannyNiu