¿Cómo se consigue que la pantalla se conecte automáticamente al agente ssh actual cuando se vuelve a conectar a una pantalla existente?

48

Si inicia una sesión de pantalla mientras se está ejecutando ssh-agent (desde el reenvío de ssh -A agent), acceder a ssh-agent funciona bien. Sin embargo, si se desconecta de esa sesión, cierre sesión, vuelva a iniciar sesión (con reenvío de agente ssh) y vuelva a adjuntarla a su sesión de pantalla, el acceso de agente ssh no funciona.

¿Cómo se puede arreglar esto?

Der Hochstapler
fuente

Respuestas:

41

1) En su script SSH rc (~ / .ssh / rc) configurará un enlace simbólico desde una ubicación canónica al SSH_AUTH_SOCK "actual". Así es como lo hago en bash (contenido de ~ / .ssh / rc):

#!/bin/bash
if test "$SSH_AUTH_SOCK" ; then
    ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi

(y asegúrese de chmod 755 ~ / .ssh / rc). La "prueba" es solo para evitar que se muestre un error si no está ejecutando ssh-agent (es decir, ssh sin -A). La segunda mitad de ese comando configura un enlace simbólico en una ubicación canónica que se actualiza a sí mismo al SSH_AUTH_SOCK "real" en el momento del inicio de sesión. Esto es independiente de usar un shell en ssh o llamar a un comando directamente, también funciona con "ssh -t screen -RRD".

Nota: la existencia de ~ / .ssh / rc cambia el comportamiento de sshd. Notablemente, no llamará a xauth. Consulte man sshd para obtener más información y cómo solucionarlo.

Además, no debe usar "-v" con ln tan pronto como rompa rsync-over-ssh con los siguientes diagnósticos:

$ rsync -n addr.maps.dev.yandex.net: .
protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(173) [Receiver=3.0.7]

2) En su .screenrc, solo necesita anular SSH_AUTH_SOCK a la ubicación canónica:

setenv SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock

Tenga en cuenta que usa setenv sin importar qué shell use; Creo que setenv es la sintaxis de la pantalla, no el shell.

Solución originalmente adaptada de esta publicación , que no funciona, pero tiene la idea correcta.

apinstein
fuente
Esto supone que primero inicias sesión y luego inicias la pantalla. ¿Derecho?
innaM
1
¿Cómo puede ser de otra manera? ¿Cómo iniciarías la pantalla sin iniciar sesión?
1
Tienes razón. La pregunta fue formulada de una manera estúpida. ¿Pero necesita iniciar sesión, iniciar un shell y desde allí iniciar la pantalla? A menudo hago algo como "ssh -t some.machine screen -R".
innaM
1
Ah ok Bueno, acabo de probar esto y no funciona (es decir, ssh-agent no está conectado). Supongo que ssh no configura los enchufes apropiados cuando se usa de esta manera. ¿Quizás algún argumento más podría limpiar eso?
SSH configura los sockets, simplemente nunca inicia el shell. Pero este consejo es tan útil que creo que podría cambiar mis hábitos.
innaM
23

Creo que esto funciona como una simplificación de la respuesta de @ sandip-bhattacharya. Ponga esto en su ~/.bashrcarchivo y ejecute el comando de exportación en cualquier sesión de pantalla que se esté ejecutando actualmente.

if [ -S "$SSH_AUTH_SOCK" ] && [ ! -h "$SSH_AUTH_SOCK" ]; then
    ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock

Que dice "si $SSH_AUTH_SOCKes un socket ( -S) y no un enlace simbólico ( ! -h), cree un nuevo enlace simbólico en la ruta conocida. En todos los casos, redefina SSH_AUTH_SOCKpara señalar la ruta conocida.

Los ! -hevita crear una referencia circular si ejecuta esto varias veces.

Además, si lo usa byobu, lo hace automáticamente, sin necesidad de editar ningún archivo de configuración.

El único error que he encontrado en esto ( byobutambién lo tiene) es que si abres un segundo ssh -Ao una ForwardAgentconexión, sobrescribirá el primer socket, y si cierras la segunda conexión antes que la primera, perderás tu único socket bueno.

Collin Anderson
fuente
1
Esto también funciona para tmux.
Dag Høidahl
Funciona muy bien, pero se rompe cuando se usan carpetas de inicio montadas de forma remota. En ese caso, ~/.ssh/ssh_auth_sock_"$(hostname)"úsalo para tu enlace simbólico. Mantendrá sockets de autenticación separados para cada host.
Kibber
4

"ssh -t some.machine screen -R" no ejecutará bash y, por lo tanto, no ejecutará el script .bash_profile donde se crea el enlace simbólico.

Puede intentar: ssh -t some.machine bash -c "screen -R"

(suponiendo que está usando bash como su caparazón, por supuesto)

Editar: Esa "respuesta" es en realidad un comentario sobre la primera respuesta dada anteriormente :)

Comunidad
fuente
"La primera respuesta dada anteriormente" no significa nada, ya que las respuestas cambian de orden a medida que se votan, etc. Incluya el enlace para compartir de la respuesta a la que se refiere, ya que eso no cambiará.
rjmunro
3

Creo que necesitas autossh. Lo he estado usando durante años y, combinado con la pantalla, hace que todas mis sesiones de terminal sean completamente portátiles y transparentes. Simplemente cierro el disquete, me muevo a una nueva ubicación, abro el disquete y todas mis pantallas y pantallas anidadas se conectan automáticamente. Ya ni siquiera pienso en eso.

http://www.linux.com/archive/feature/134133

es lo básico ... Escribí un script lil para automatizar el proceso en mi .screenrc para un host dado. (también hace mi reenvío ssh, por lo que en todos estos lugares diferentes puedo hacer un túnel de mi conexión a través de mis servidores)

en la distribución autossh debería haber un programa llamado rscreen (y ... ¡lo hay!)

#!/bin/sh                                                                       
#
# sample script to use autossh to open up a remote screen
# session, or reconnect to an existing one. 
#
# $Id: rscreen,v 1.4 2002/05/07 17:54:13 harding Exp $
#
if [ "X$1" = "X" ]; then
    echo "usage: `basename $0` <host>"
    exit 1
fi

if [ "X$SSH_AUTH_SOCK" = "X" ]; then
    eval `ssh-agent -s`
    ssh-add $HOME/.ssh/id_rsa
fi

#AUTOSSH_POLL=600
#AUTOSSH_PORT=20000
#AUTOSSH_GATETIME=30
#AUTOSSH_LOGFILE=$HOST.log
#AUTOSSH_DEBUG=yes 
#AUTOSSH_PATH=/usr/local/bin/ssh
export AUTOSSH_POLL AUTOSSH_LOGFILE AUTOSSH_DEBUG AUTOSSH_PATH AUTOSSH_GATETIME 

autossh -M 20004 -t $1 "screen -e^Zz -D -R"

Esto debería ayudar con problemas ssh / screen

Finalmente, para mantener mi agente ssh en ejecución, uso el llavero, ya que soy una especie de cabeza de shell ... Creo que OSX tiene algo disponible para mantener a su agente cerca ...

chiggsy
fuente
2

Aquí está el método que uso:

SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK) ; eval $SOCK ; export SSH_AUTH_SOCK
DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY) ; eval $DISP ; export DISP

Por lo general, configuro un alias o una función de shell con estos comandos:

function ssh-screen-auth() {
  SOCK=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep SSH_AUTH_SOCK)
  eval $SOCK
  export SSH_AUTH_SOCK
  DISP=$(sudo cat /proc/$(pgrep -f "screen -(r|DR)")/environ | tr "\0" "\n" | grep DISPLAY)
  eval $DISP
  export DISPLAY
}

Puede que tenga que adaptar la expresión regular ' pantalla - (r | DR) ' a los comandos exactos que utiliza para volver a conectar su pantalla.

  • La primera línea lee la variable de entorno SSH_AUTH_SOCK en el espacio de proceso del comando " screen -r " que acaba de escribir y actualiza el valor en su shell actual.
  • La segunda línea es necesaria si usa " ssh -X " para reenviar conexiones X11: actualiza la variable DISPLAY de la misma manera.

Una advertencia con mi método: las cosas pueden salir mal si hay otro comando de " pantalla " ejecutándose en la computadora.

Farzy
fuente
-1 por el uso innecesario de sudo.
0xC0000022L
1

Normalmente mantengo sesiones a largo plazo (más de 6 meses) en mi lugar de trabajo en diferentes servidores. Por lo tanto, volver a conectar y tener un agente de reenvío ssh viable ha sido problemático. Esto es lo que configuré en mis sistemas:

if [ -z "${STY}" -a -t 0 -a X${USER} = Xmyusername ]; then
    reattach () {
        if [ -n "${SSH_AUTH_SOCK}" ]; then
            ln -snf "${SSH_AUTH_SOCK}" "${HOME}/.ssh/agent-screen"
            SSH_AUTH_SOCK="${HOME}/.ssh/agent-screen" export SSH_AUTH_SOCK
        fi
        exec screen -A -D -RR ${1:+"$@"} ;
    }

    screen -wipe
    echo 'starting screen... (type Cntl-C to abort)'
    sleep 5 && reattach
fi

Si acabo de iniciar sesión en el servidor remoto sin iniciar / volver a conectar la pantalla, habrá dos "sockets", uno en uso screeny otro por el nuevo shell. No debe haber dos sesiones de "puesta en marcha", pero una segunda sesión todavía podría haber empezado a utilizar reattach -S new; en esta situación, el agente se compartiría con el ~/.ssh/agent-screenvalor. Para recuperar un agente de reenvío en funcionamiento, luego me desconectaría y volvería a iniciar sesión. Esto X${USER} = Xmyusernamegarantiza que el código no se invoque sudoen el mismo servidor.

Arcege
fuente
1

Estoy usando una variación de lo que @apinstein está usando para mi .bashrc .

case "$TERM" in
    screen)
           export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
        ;;
         *)
           if [[ -n "$SSH_AUTH_SOCK" ]]; then
               ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
           fi
        ;;
esac

Esto funciona para todas las aplicaciones que se ejecutan en mi sesión de pantalla. Esto funcionaría para todos los nuevos shells en su sesión de pantalla. Para los shells existentes, debe ejecutar export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sockel shell del host para que funcione.

PD Perdón por agregar esto como una respuesta independiente, mientras que se basó en la respuesta de @ apinstein. Tuve que hacer esto ya que los comentarios en stackoverflow no admiten bloques de código.

Sandip Bhattacharya
fuente
¿Por qué no siempre enlace simbólico y siempre exportar?
Collin Anderson
@CollinAnderson Dos comportamientos diferentes. uno dentro de un shell de pantalla y otro dentro del shell de inicio de sesión normal. ssh establece la variable de entorno en un shell de inicio de sesión y, por lo tanto, el enlace simbólico allí. Si hacemos esto dentro de una sesión de pantalla, provocaremos un bucle de enlace simbólico.
Sandip Bhattacharya
Ahh, cierto. Debería vincular solo si $ SSH_AUTH_SOCK aún no es un enlace. Ver mi publicación superuser.com/a/424588/134212
Collin Anderson
0

Probé este sencillo revestimiento como se sugiere en Hagamos amigos de screen y ssh-agent y funciona para mí.

Inicio de sesión por primera vez en Target. Solo debe hacerse una vez.

ssh -o StrictHostKeyChecking=no -C <userid>@<server>

Pantalla de inicio por primera vez ... Debe hacerse solo una vez.

eval `ssh-agent`; /usr/bin/screen -D -R -h 10000
ssh-add

Si está desconectado o desconectado, use este comando para iniciar sesión posteriormente para conectarse a la pantalla de salida.

ssh -o StrictHostKeyChecking=no -C -t <userid>@<server> ssh-agent /usr/bin/screen -D -R -h 10000
Sharjeel
fuente
0

Todas estas son respuestas realmente buenas. Lo hago de manera ligeramente diferente. Después de iniciar una nueva sesión ssh y volver a conectar la pantalla, restablezco la SSH_AUTH_SOCKvariable de entorno en función del contenido del entorno de bash de raíz. Solo necesito acceso ssh-agent de vez en cuando cuando estoy usando svn, así que simplemente restablezco el SSH_AUTH_SOCKrequerido en estos shells.

Esto utiliza el sistema de archivos proc, por lo que es específico de Linux. Solo he probado esto en una caja de linux sin cabeza a la que solo tengo acceso, podría tomar algunos ajustes para que funcione en otros entornos.

Para restablecer SSH_AUTH_SOCK (esto podría convertirse en un alias).

$ . ~/bin/screen_auth.sh

screen_auth.sh tiene este aspecto

# Find the pid of putty's bash shell
tty=`who | awk '/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ { print substr($2, 5) }'`
pid=`ps -t $tty | grep bash | awk '{print $1}'`
# Find the SSH_AUTH_SOCK variable in its enviornment
auth_sock=`xargs --null --max-args=1 echo < /proc/$pid/environ | grep SSH_AUTH_SOCK`
eval "export $auth_sock"
iain
fuente
0

Todas las soluciones anteriores sufren condiciones de carrera (ya sea en múltiples sesiones de SCREEN o en múltiples conexiones SSH). La única solución universal que se me ocurre es primero presionar SSH_AUTH_SOCK para SCREEN el proceso del servidor screen -ry luego colocarlo dentro de la sesión BASH antes de cada comando interactivo no integrado. Desafortunadamente, SCREEN y BASH se diseñaron sin ser conscientes de este tipo de problemas, por lo que es bastante difícil de implementar correctamente (aunque nunca es tarde para publicar solicitudes de funciones en ambos proyectos). Se intentó superar este problema para las sesiones de BASH que se pueden encontrar aquí:

Instalar:

  1. poner ambos scripts en $HOME/bin, agregar bit ejecutable;
  2. asegúrese de que eso $HOME/binvaya antes /usr/binen PATH

    RUTA = $ INICIO / bin: $ RUTA

  3. agregue esto a su .bashrc:

    fuente $ HOME / bin / screen-helper setup

Ahora puede intentar crear una sesión SCREEN dentro de la sesión SSH, desconectar, desconectar, conectar y volver a conectar y, con suerte, ssh-add -ldebería mostrar correctamente sus claves.

midenok
fuente
Tenga en cuenta que el ssh-agentdaemon permanente (como se sugiere aquí superuser.com/a/412052/376867 ) no sufre de una condición de carrera, sino un llavero obsoleto. Y lo que es más importante, no es muy seguro dejar todas sus claves en el host remoto junto con la sesión de pantalla (o incluso más tiempo hasta que se reinicie en caso de una publicación mencionada).
midenok
0

Hojeé otras respuestas y no pude encontrar la mía. Esto es lo que uso. Cree un archivo ~/.screenrc-wrappercon los siguientes contenidos:

escape ^xx
bindkey ^Ad detach

Y agregue esto a su ~/.bashrc(o ~/.zshrcsi lo usa):

  if echo $TERM | grep -v 'screen' && ! screen -x -SU wrapper; then
      if echo $TERM | grep -v 'screen' && ! screen -x -SU main; then
      screen -c ~/.screenrc-wrapper -SU wrapper ssh-agent screen -SU main
      fi
  fi

De esta forma, usaría dos sesiones de pantalla: una es "envoltura" y la otra es la interna. Esto mantendrá vivo a este último incluso cuando cierre la sesión y seguirá teniendo ssh-agent. Otra buena característica es que recordará la configuración de su ventana: si usa ventanas divididas, puede ser muy útil.

Puede encontrar esta función en contexto en mis archivos de puntos .

d33tah
fuente