Совместное использование одного и того же ssh-агента среди нескольких сеансов входа

33481
intuited

Есть ли удобный способ гарантировать, что все логины от данного пользователя (т.е. меня) используют один и тот же ssh-agent? Я взломал сценарий, чтобы сделать эту работу большую часть времени, но я все время подозревал, что есть какой-то способ сделать это, что я только что пропустил. Кроме того, с тех пор были достигнуты удивительные достижения в области компьютерных технологий, как, например, этот веб-сайт.

Итак, цель в том, чтобы

  • всякий раз, когда я вхожу в ящик, независимо от того, идет ли он через SSH, или в графическом сеансе, запущенном из gdm / kdm / etc, или в консоли:
    • если мое имя пользователя в данный момент не ssh-agentзапущено, оно запускается, переменные среды экспортируются, иssh-add вызываются.
    • в противном случае координаты существующего агента экспортируются в переменные среды сеанса входа в систему.

Это средство особенно ценно, когда рассматриваемый ящик используется как точка ретрансляции при sshвходе в третий ящик. В этом случае он избегает необходимости вводить парольную фразу закрытого ключа каждый раз, когда вы вводите ssh, а затем хотите, например, сделатьgit push или что-то еще.

Сценарий, приведенный ниже, делает это в основном надежно, хотя в последнее время он потерпел неудачу, когда произошел сбой X, и я начал еще один графический сеанс. В этом случае могли происходить и другие проблемы.

Вот мой плохой сценарий. Я получаю это из моего .bashrc.

# ssh-agent-procure.bash # v0.6.4 # ensures that all shells sourcing this file in profile/rc scripts use the same ssh-agent. # copyright me, now; licensed under the DWTFYWT license.  mkdir -p "$HOME/etc/ssh";  function ssh-procure-launch-agent { eval `ssh-agent -s -a ~/etc/ssh/ssh-agent-socket`; ssh-add; }  if [ ! $SSH_AGENT_PID ]; then if [ -e ~/etc/ssh/ssh-agent-socket ] ; then SSH_AGENT_PID=`ps -fC ssh-agent |grep 'etc/ssh/ssh-agent-socket' |sed -r 's/^\S+\s+(\S+).*$/\1/'`;  if [[ $SSH_AGENT_PID =~ [0-9]+ ]]; then # in this case the agent has already been launched and we are just attaching to it.  ##++ It should check that this pid is actually active & belongs to an ssh instance export SSH_AGENT_PID; SSH_AUTH_SOCK=~/etc/ssh/ssh-agent-socket; export SSH_AUTH_SOCK; else # in this case there is no agent running, so the socket file is left over from a graceless agent termination. rm ~/etc/ssh/ssh-agent-socket; ssh-procure-launch-agent; fi; else ssh-procure-launch-agent; fi; fi; 

Пожалуйста, скажите мне, что есть лучший способ сделать это. Также, пожалуйста, не придирайтесь к несоответствиям / оплошностям (например, добавляя varвещи etc); Я написал это некоторое время назад и с тех пор многому научился.

57
KeyError: «DWTFYWT» не найден; Вы имели в виду [WTFPLv2] (http://sam.zoy.org/wtfpl/)? grawity 14 лет назад 1
@ Grawity: спасибо за эту ссылку, их часто задаваемые вопросы сделали мой день: ** Кстати, с WTFPL, я могу также ... ** * О, да, конечно, вы можете. * ** Но я могу ... ** * Да, вы можете. * ** Может ... ** * Да! * Хахахахахаха quack quixote 14 лет назад 0
@ Grawity: Нет, это именно то, что я хотел, чтобы вы думали, мвахахаха. intuited 14 лет назад 0

15 ответов на вопрос

33
h355ian

ssh -A [user@]remotehost

Я думаю, что это может быть то, что вы ищете. Используйте ключ -A при запуске ssh forward вашего ssh-agent. Вот пример использования:

У меня есть удаленный сервер, на котором есть некоторые git-репозитории с удаленным указателем на github. Без ssh-agent, запущенного в сеансе экрана, я должен ввести ключевую фразу для моего ключа, чтобы сделать «мастер происхождения git pull». Booo! Кроме того, на удаленном сервере должен быть установлен мой закрытый ключ - больше Boooo!

Вместо этого, просто используя ssh -A [user@]remotehostпроходы по моему локально работающему ssh-agent. Теперь мне больше не нужен мой личный ключ, чтобы существовать даже на удаленном хосте. Я не верю, что вам нужно делать какие-либо скрипты с ssh-agent.

Это то, что я искал, спасибо! tmow 13 лет назад 2
Не знал об этом, но оказалось, что это именно то, что я искал, когда подошел к этому вопросу. Will McCutchen 12 лет назад 3
Это даже лучше, чем я искал! Отличный ответ! WhyNotHugo 11 лет назад 1
Смотрите также `man 5 ssh_config` для настройки конфигурации` ForwardAgent`. По умолчанию он включает переадресацию агента, устраняя необходимость в аргументе `-A`. Перед использованием переадресации агентов следует помнить, что существует угроза безопасности, когда другие привилегированные пользователи на удаленном компьютере могут получить доступ к перенаправленному сокету агента. Это также упоминается на странице руководства. Это хорошо объяснено [здесь] (http://www.symantec.com/connect/articles/ssh-and-ssh-agent). starfry 10 лет назад 1
24
Zed

С таким же успехом я мог бы добавить свой вариант:

function sshagent_findsockets { find /tmp -uid $(id -u) -type s -name agent.\* 2>/dev/null }  function sshagent_testsocket { if [ ! -x "$(which ssh-add)" ] ; then echo "ssh-add is not available; agent testing aborted" return 1 fi  if [ X"$1" != X ] ; then export SSH_AUTH_SOCK=$1 fi  if [ X"$SSH_AUTH_SOCK" = X ] ; then return 2 fi  if [ -S $SSH_AUTH_SOCK ] ; then ssh-add -l > /dev/null if [ $? = 2 ] ; then echo "Socket $SSH_AUTH_SOCK is dead! Deleting!" rm -f $SSH_AUTH_SOCK return 4 else echo "Found ssh-agent $SSH_AUTH_SOCK" return 0 fi else echo "$SSH_AUTH_SOCK is not a socket!" return 3 fi }  function sshagent_init { # ssh agent sockets can be attached to a ssh daemon process or an # ssh-agent process.  AGENTFOUND=0  # Attempt to find and use the ssh-agent in the current environment if sshagent_testsocket ; then AGENTFOUND=1 ; fi  # If there is no agent in the environment, search /tmp for # possible agents to reuse before starting a fresh ssh-agent # process. if [ $AGENTFOUND = 0 ] ; then for agentsocket in $(sshagent_findsockets) ; do if [ $AGENTFOUND != 0 ] ; then break ; fi if sshagent_testsocket $agentsocket ; then AGENTFOUND=1 ; fi done fi  # If at this point we still haven't located an agent, it's time to # start a new one if [ $AGENTFOUND = 0 ] ; then eval `ssh-agent` fi  # Clean up unset AGENTFOUND unset agentsocket  # Finally, show what keys are currently in the agent ssh-add -l }  alias sagent="sshagent_init" 

И затем каждый раз, когда я вхожу в систему, если я хочу подключить агента (что я не всегда), я просто набираю sagent.

`если [! -x "$ (которое ssh-add)"]; `следует заменить на` if! который ssh-add; `или` if! команда -v ssh-add`. (Помните, `[` это просто команда) grawity 14 лет назад 2
Ну, вы можете сделать это, но на самом деле это должно быть `if! который ssh-add> / dev / null` для предотвращения печати пути, и в этот момент я не совсем уверен, что он более понятен, хотя, полагаю, это сэкономит вам один дополнительный вызов команды. Zed 14 лет назад 0
так что в основном ответ - нет. дерьмо. Ну, это выглядит более развитым, чем мой хак, поэтому, вероятно, это будет полезно. Странно, что нет более структурированного способа сделать это, хотя, кажется, что-то, что было бы весьма полезно. intuited 14 лет назад 0
Сейчас я нахожусь в порыве репозиториев, поэтому я настроил [github repo] (http://github.com/intuited/sshag) для вашего сценария. Еще раз спасибо. Я надеюсь, что я был достаточно формален с лицензированием: ~ / intuited 14 лет назад 0
Я не против Пожалуйста, прокомментируйте здесь, если кто-то представит улучшения, хотя. Zed 14 лет назад 0
In my case I could have multiple agent socket files. To always use the latest one (by timestamp) I modified the above find command to this: `find /tmp -uid $(id -u) -type s -printf '%Ts\t%p\n' -name agent.\* 2>/dev/null | sort -nr | cut -f2` Dirk Gorissen 8 лет назад 0
Как сказал Кев: попробуйте использовать брелок, он создан для этого. Но еще лучше, делай то, что сказал MarkMo! 00prometheus 8 лет назад 0
https://github.com/intuited/sshag/pull/1 "используйте` sshag user @ domain` вместо `ssh user @ domain`". Протестировано на Linux и Git-for-Windows (MSYS2). go2null 7 лет назад 0
20
vonhogen

Вот довольно хороший, который работает и в Cygwin:

SSH_ENV=$HOME/.ssh/environment  function start_agent { echo "Initialising new SSH agent..." /usr/bin/ssh-agent | sed 's/^echo/#echo/' > $ echo succeeded chmod 600 $ . $ > /dev/null /usr/bin/ssh-add; }  # Source SSH settings, if applicable  if [ -f "$" ]; then . $ > /dev/null #ps $ doesn't work under cywgin ps -efp $ | grep ssh-agent$ > /dev/null || { start_agent; } else start_agent; fi 

Добавьте его в ваш .bash_profile или .bashrc

Источник: http://www.cygwin.com/ml/cygwin/2001-06/msg00537.html

Также хорошо работает с Git Bash (mingw64) для Windows Dolphin 8 лет назад 0
`$ ` должен быть `" $ "`, если в вашем имени пользователя Windows есть пробел rgvcorley 7 лет назад 1
Этот ответ, кажется, скачет по интернету. Здесь он находится в [гораздо большем потоке stackoverflow] (https://stackoverflow.com/a/18915067/4970632). Лучший / самый простой подход ИМХО. Luke Davis 6 лет назад 0
9
kev

Попробуйте использовать брелок, это сделано для этого. http://www.gentoo.org/doc/en/keychain-guide.xml

6
MarkMo

I have recently started using:

https://github.com/ccontavalli/ssh-ident

All I have to do is add:

 alias ssh=/path/to/ssh-ident 

In my .bashrc file. The script takes care of:

  • creating an agent when it is first needed
  • load the necessary keys on demand
  • share agents across multiple login sessions
  • manage multiple agents, one for each 'identity' that I use online, and use the right agent based on the host I'm connecting to or the current working directory.
ssh-идент это фантастика! Он разблокирует ключ и загружает агент, когда я пытаюсь выполнить ssh, вместо того, чтобы разблокировать ключ заранее. Это делает ключевые тайм-ауты полезными. Что еще более важно, он хранит мои агенты отдельно для разных целей (серьезная угроза безопасности; у root на одной машине мой уровень доступа ко всем остальным машинам, для которых у текущего агента есть ключи!) 00prometheus 8 лет назад 0
5
grawity

Я предпочитаю сделать вещи максимально простыми: (фрагмент из ~/.profile)

check-ssh-agent() { [ -S "$SSH_AUTH_SOCK" ] && { ssh-add -l >& /dev/null || [ $? -ne 2 ]; } }  # attempt to connect to a running agent check-ssh-agent || export SSH_AUTH_SOCK="$(< ~/.tmp/ssh-agent.env)" # if agent.env data is invalid, start a new one check-ssh-agent || { eval "$(ssh-agent -s)" > /dev/null echo "$SSH_AUTH_SOCK" > ~/.tmp/ssh-agent.env } 

Я не думал об использовании -aраньше, но это может быть проще:

check-ssh-agent || export SSH_AUTH_SOCK=~/.tmp/ssh-agent.sock check-ssh-agent || eval "$(ssh-agent -s -a ~/.tmp/ssh-agent.sock)" > /dev/null 
Ницца. Я несколько упростил это в своем ответе (ниже). Ether 9 лет назад 0
2
Greg Bray

В моем случае у меня есть шикарно-ГИТ установка в PowerShell и хотел Cygwin использовать тот же SSH-агент. Мне пришлось сделать некоторые манипуляции с путями, поскольку они используют разные папки tmp, и был создан файл .env UTF16 с BOM и CR \ LF, так что было интересно иметь дело. Добавление следующего к .bashrc, используемому cygwin, должно работать:

# Connect to ssh-agent started by posh-git SSH_AGENT_ENV=$(cygpath "$LOCALAPPDATA\Temp") if [ -z $SSH_AUTH_SOCK ] && [ -z $SSH_TTY ]; then # if no agent & not in ssh if [ -f "$SSH_AGENT_ENV/.ssh/SSH_AUTH_SOCK.env" ]; then AUTH_SOCK=$(iconv -c -f UTF-16LE -t US-ASCII "$SSH_AGENT_ENV/.ssh/SSH_AUTH_SOCK.env" | tr -d '\r\n') export SSH_AUTH_SOCK="$" ssh-add -l > /dev/null if [ $? = 2 ] ; then echo "Failed to setup posh-git ssh-agent using $AUTH_SOCK" unset SSH_AUTH_SOCK else echo "Found posh-git ssh-agent $AUTH_SOCK" fi else #Start new agent if you want (not shared by posh-git) echo "failed to setup posh-git ssh-agent" #eval `ssh-agent -s` > /dev/null fi fi 
1
Jorrit Jorritsma

Снова пример для немедленного добавления вашего .bash_profile с просьбой добавить ваш ключ по умолчанию при входе в систему. Переадресация не была вариантом в моем случае.

do-ssh-agent() { # function to start the ssh-agent and store the agent details for later logon ssh-agent -s > ~/.ssh-agent.conf 2> /dev/null . ~/.ssh-agent.conf > /dev/null }  # set time a key should be kept in seconds keyage=3600  if [ -f ~/.ssh-agent.conf ] ; then . ~/.ssh-agent.conf > /dev/null ssh-add -l > /dev/null 2>&1 # $?=0 means the socket is there and it has a key # $?=1 means the socket is there but contains no key # $?=2 means the socket is not there or broken stat=$? if [ $stat -eq 1 ] ; then ssh-add -t $keyage > /dev/null 2>&1 elif [ $stat -eq 2 ] ; then rm -f $SSH_AUTH_SOCK do-ssh-agent ssh-add -t $keyage > /dev/null 2>&1 fi else do-ssh-agent ssh-add -t $keyage > /dev/null 2>&1 fi 
1
Ether

This is my solution, adapted from https://superuser.com/a/141233/5255 (in this thread):

# attempt to connect to a running agent - cache SSH_AUTH_SOCK in ~/.ssh/ sagent() { [ -S "$SSH_AUTH_SOCK" ] || export SSH_AUTH_SOCK="$(< ~/.ssh/ssh-agent.env)" # if cached agent socket is invalid, start a new one [ -S "$SSH_AUTH_SOCK" ] || { eval "$(ssh-agent)" ssh-add -t 25920000 -K ~/.ssh/id_rsa echo "$SSH_AUTH_SOCK" > ~/.ssh/ssh-agent.env } } 
1
raghavan

create file ~/ssh-agent.sh

agent_out_file="$HOME/ssh-agent.out" function initialize { pgrep ssh-agent && kill $(pgrep ssh-agent) ssh-agent -s > $agent_out_file . $agent_out_file } pgrep ssh-agent if [ $? -eq 0 ]; then # ssh agent running ssh-add -l > /dev/null 2>&1 status=$? if [ $status -eq 0 ]; then # can connect to ssh agent and keys available echo nothing to do elif [ $status -eq 1 ]; then # can connect to ssh agent and no keys available echo nothing to do elif [ $status -eq 2 ]; then # cannot connect to ssh agent . $agent_out_file fi else # ssh agent not running initialize fi 

include the file in .bashrc

. ~/ssh-agent.sh 

Похожие вопросы