¿Cómo puedo detectar si el shell está controlado desde SSH?

69

Quiero detectar desde un script de shell (más específicamente .zshrc) si se controla a través de SSH. Probé la variable HOST pero siempre es el nombre de la computadora que ejecuta el shell. ¿Puedo acceder al nombre de host de donde proviene la sesión SSH? Comparar los dos resolvería mi problema.

Cada vez que inicio sesión hay un mensaje que indica la última hora de inicio de sesión y el host:

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

Esto significa que el servidor tiene esta información.

Stribika
fuente

Respuestas:

90

Aquí están los criterios que uso en mi ~/.profile:

  • Si se define una de las variables SSH_CLIENTo SSH_TTY, es una sesión ssh.
  • Si el nombre del proceso principal del shell de inicio de sesión es sshd, es una sesión 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

(¿Por qué querría probar esto en su configuración de shell en lugar de en el inicio de su sesión?)

Gilles 'SO- deja de ser malvado'
fuente
3
Funcionó genial gracias! github.com/balupton/dotfiles/commit/…
balupton
1
es posible que desee hacer esto en su configuración de shell si desea habilitar el reenvío de agente ssh desde su shell remoto (ya que los vars de entorno deben establecerse en cada shell desde el que desea reenviar) a menos que me falte algo.
Underrun
@underrun No entiendo tu punto. Si ejecuta otro shell en la misma sesión, hereda las variables de entorno establecidas por .profile. ¿Y qué tiene esto que ver con el reenvío de agentes?
Gilles 'SO- deja de ser malvado'
1
@underrun Si desea probar la presencia de reenvío de agente SSH, pruebe la SSH_AUTH_SOCKvariable. Pero, ¿por qué ejecutarías un agente SSH en ese caso? ¿Quiso decir iniciar un agente si ha iniciado sesión sin reenvío de agente? ¿Por qué no iniciar un agente si aún no hay uno ( [ -n "$SSH_AUTH_SOCK" ] || eval $(ssh-agent))?
Gilles 'SO- deja de ser malvado'
1
@Praxeolitic Las SSH_*variables también se configuran en subprocesos de un shell que está al frente de una sesión SSH, por ejemplo, si inicia una sesión de pantalla sobre SSH (si lo desea, debe desactivar las variables antes de comenzar la sesión). Creo que la razón para probar el proceso padre es que comencé a hacerlo antes de que sshd definiera las variables de entorno.
Gilles 'SO- deja de ser malvado'
21

Usted debe ser capaz de verificar a través de los SSH_TTY, SSH_CONNECTIONo SSH_CLIENTvariables.

Cakemox
fuente
1
También añadir estos a env_keepen sudoershacer que funcione a través de sucomandos :)
Thomas G.
10

Acabo de tener el mismo problema en Linux, usando Bash. Primero usé la variable de entorno SSH_CONNECTION, pero luego me di cuenta de que no está configurada si usted su -.

La última solución de registro anterior no funcionó ni después suni su -.

Finalmente, estoy usando who am i, que muestra la IP remota (o el nombre de host) al final si es una conexión SSH. También funciona después de su.

Usando expresiones regulares de Bash, esto funciona:

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

Si zsh no admite expresiones regulares, lo mismo se puede lograr de muchas maneras diferentes con grep, cut, sed o lo que sea.

Para los curiosos, a continuación es para lo que uso esto, en el .bashrc de la raíz:

    # 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

Una alternativa que también funciona susería buscar de forma recursiva a sshdtravés de los procesos principales:

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

Si la función se agrega a .bashrc, se puede usar como if is_ssh; then ...

mivk
fuente
1
no funciona en tmuxsesiones remotas y también tiene problemas si inicia sesión a través de IPv6 y no existe un nombre inverso de DNS.
bene
@bene: ¿qué no funciona? ¿La expresión regular o who am ino muestra su dirección IPv6?
mivk
1) who am ino devuelve nada en una tmuxsesión remota . 2) La dirección IPv6 puede contener dos puntos que su expresión regular no permite. Esto puede ser complicado ya que who am icontiene (:0.0)X sesiones para mí (xterm).
bene
@bene: la solución alternativa que acabo de agregar también debería funcionar con IPv6. No sé acerca de tmux, pero también funciona screen.
mivk
7

Creo que las respuestas de Gilles y Cakemox son buenas, pero solo para completar ...

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

proviene de pam_lastlog1 .

Puede imprimir pam_lastloginformación con el comando lastlog2 , p. Ej.

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

para un inicio de sesión local, en comparación con

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

para un inicio de sesión SSH.

En mi sistema, esto funciona para extraerlo

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

lasty wpodría ser útil también, por ejemplo

$ 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 documentación de Linux / FreeBSD para pam_lastlog.
2 páginas de manual de Linux / FreeBSD lastlog(8) .

Mikel
fuente
1

Comience por observar su entorno y encontrar la opción correcta

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

Puede conectar muchas de estas variables de entorno para activar acciones específicas en función de su presencia.

lfender6445
fuente
-1

Esto es para verificar todas las conexiones establecidas de otro usuario usando SSH

netstat | grep ssh
ARD
fuente
Esto no es del todo confiable.
DannyNiu