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

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

Итак, цель здесь в том, что

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

Это средство особенно ценно, когда рассматриваемая коробка используется в качестве точки реле, когда вы попадаете в третий ящик. В этом случае это позволяет избежать ввода парольной фразы секретного ключа каждый раз, когда вы 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; и # 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; 

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

Я мог бы также внести свои изменения в микс:

 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 в систему, если я хочу, чтобы связанный агент (который я не всегда), я просто sagent .

ssh -A [[email protected]]remotehost

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

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

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

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

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

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

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

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

Я недавно начал использовать:

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

Все, что мне нужно сделать, это добавить:

  alias ssh=/path/to/ssh-ident 

В моем файле .bashrc. Сценарий заботится:

  • Создание агента, когда он в первую очередь необходим
  • Загружать необходимые ключи по требованию
  • Делиться агентами через несколько сеансов входа в систему
  • Управлять несколькими агентами, по одному для каждого «идентификатора», который я использую в Интернете, и использовать нужный агент на основе хоста, к которому я подключаюсь, или текущего рабочего каталога.

Я предпочитаю держать все как можно проще: (фрагмент из ~/.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 

Опять пример, чтобы сразу ввести ваш .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 

Это мое решение, адаптированное из https://superuser.com/a/141233/5255 (в этой теме):

 # 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 } } 

Создать файл ~ / 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 

Включить файл в .bashrc

 . ~/ssh-agent.sh 

В моем случае у меня есть настройка posh-git в PowerShell и вы хотите, чтобы cygwin использовал один и тот же ssh-agent. Я должен был сделать некоторые манипуляции с путями, поскольку они используют разные папки 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="${AUTH_SOCK/\/tmp/$SSH_AGENT_ENV}" 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 

Это то, что я добавил, которое работает для меня. Сначала он проверяет, есть ли у вас агент, если да, он установит для него подходящие среды, если он не создаст его. Также устраняет создание дополнительных агентов:

Просто поместите его в свой .bashrc

 function start_agent() { killall ssh-agent 2> /dev/null ssh-agent | sed 's/ Agent pid//' > $SSH_ENV . $SSH_ENV > $SSH_PID_FILE ssh-add ~/.ssh/bb_readonly_rsa 2> /dev/null } mkdir -p "$HOME/.ssh/agent" SSH_ENV="$HOME/.ssh/agent/env" SSH_PID_FILE="$HOME/.ssh/agent/pid" if [[ -e $SSH_PID_FILE ]]; then SSH_PID=$(< $SSH_PID_FILE) PROCESS=$(ps -p $SSH_PID -o comm=) if [[ $PROCESS == 'ssh-agent' ]]; then . $SSH_ENV > $SSH_PID_FILE else start_agent fi else start_agent fi 

У меня есть вариация этой проблемы, тоже взятая прямо из моего .bashrc:

 # File for storing SSH agent information OSH=".agent.${HOSTNAME}" # Test if an agent file exists if [ -f ${OSH} ]; # We have one, so let's use it then eval `cat ${OSH}` >/dev/null else # No file exists, so we must spawn a new agent eval `ssh-agent | tee ${OSH}` >/dev/null fi # Try to list agent keys ssh-add -l &>/dev/null # Determine the agent status case $? in # Current and SSH keys installed, nothing to do here 0) ;; # Current but no SSH keys installed, so we must add them 1) ssh-add ;; # Stale, so we must redo from scratch with a new agent, then add keys *) eval `ssh-agent | tee ${OSH}` >/dev/null && ssh-add ;; esac 

Это решение хранит копию информации агента SSH в вашем домашнем каталоге. Если у вас есть авторизованный домашний каталог NFS, который может быть разделен между несколькими хостами, имя хоста используется как часть имени файла, чтобы различать их, поэтому вход в систему с одного компьютера не будет сжимать файл агента, который будет использоваться другим.

Поведение:

1) Запрограммированы первые сеансы пользователя для ключевой фразы.

2) Сеансы второго, третьего и четвертого (и т. Д.) Наследуют агента SSH и ключей (ов), добавленных в первый.

3) Если агент убит или сбой, первый последующий сеанс создаст новый агент, перезапишет файл агента новым – и снова предложит ключевую кодовую фразу. Впоследствии созданные сеансы будут вести себя как сценарий 2), пока новый агент SSH не будет запущен.

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

Это единственная функция, она использует переменную Zsh для идентификатора пользователя, если она есть, и пытается потратить меньше времени на разбор, возможно, огромных /tmp каталогов, ограничив find(1) немного больше.

Вероятно, он все еще подвержен ошибкам и запутан, но некоторые беглые тесты показывают, что он в основном работает для моих случаев использования, поэтому здесь идет:

 Attach_ssh_agent () {
   Если [-n "$ SSH_AGENT_PID"];  тогда
     Ssh-add -l> / dev / null
     RET = $?
     Если [$ ret -ge 2];  тогда
       Echo "Агент pid $ SSH_AGENT_PID менее полезен (ret = $ ret) - убийство ..."
       Kill $ SSH_AGENT_PID
       Unset $ SSH_AGENT_PID
     Elif [$ ret = 1];  тогда
       Echo «Агент pid $ SSH_AGENT_PID менее полезен (ret = $ ret) - будет его посеять ...»
     еще
       Echo "Агент pid $ SSH_AGENT_PID"
       вернуть
     фи
   фи
   Если [-S "$ SSH_AUTH_SOCK"];  тогда
     Ssh-add -l> / dev / null
     RET = $?
     Если [$ ret = 2];  тогда
       Echo "Socket $ SSH_AUTH_SOCK мертв - удаление ..."
       Rm -f $ SSH_AUTH_SOCK
       Unset SSH_AUTH_SOCK
     Elif [$ ret = 1];  тогда
       Echo "Socket $ SSH_AUTH_SOCK указывает на агента без ключей ..."
       SSH-добавить
     еще
       Echo "Найдено ssh-agent $ SSH_AUTH_SOCK (ret = $ ret)"
       вернуть
     фи
   фи
   Для sf в $ (find / tmp / -mindepth 2 -maxdepth 2 -uid $ {UID: - $ (id -u)} -path '/tmp/ssh-*/agent.*' -type s);  делать
     Test -r $ sf ||  Продолжать
     Экспорт SSH_AUTH_SOCK = $ sf
     SSH_AGENT_PID = $ (basename $ SSH_AUTH_SOCK | cut -d. -f2)
     # Гонки с другими вилами процесса, argh
     попробовать = 50
     While [$ try -gt 0];  делать
       попробовать = $ (($ примерки 1))
       Экспорт SSH_AGENT_PID = $ (($ SSH_AGENT_PID + 1))
       Echo "Тестирование $ SSH_AUTH_SOCK -> $ SSH_AGENT_PID"
       Если ps -u $ USER |  Grep ssh-agent |  \
            Awk '$ 1 ==' $ SSH_AGENT_PID '{
                   найдено = 1;
                   Выход (0);
               }
               КОНЕЦ {
                   If (! Found) {
                       Print "не найден запуск PID '$ SSH_AGENT_PID'";
                       выход (1);
                   }
               } ';  тогда
         Ssh-add -l> / dev / null
         RET = $?
         Если [$ ret -ge 2];  тогда
           Echo "Socket $ SSH_AUTH_SOCK не содержит ссылки на полезный агент при $ SSH_AGENT_PID - удалении ..."
           Rm -f $ SSH_AUTH_SOCK
           Kill $ SSH_AGENT_PID
           Unset SSH_AGENT_PID
           Продолжить 2
         Elif [$ ret = 1];  тогда
           Echo "Socket $ SSH_AUTH_SOCK содержит ссылку на менее полезный агент при $ SSH_AGENT_PID - посев ..."
           SSH-добавить
           если !  Ssh-add -l> / dev / null;  тогда
             Echo "Socket $ SSH_AUTH_SOCK по-прежнему содержит ссылку на менее полезный агент при $ SSH_AGENT_PID - прерывание."
             вернуть
           еще
             ломать
           фи
         еще
           ломать
         фи
       еще
         Echo "Socket $ SSH_AUTH_SOCK не содержит ссылку на работающего агента - удаление ..."
         Rm -f $ SSH_AUTH_SOCK
         Продолжать
       фи
     сделанный
     Если [$ try -gt 0];  тогда
       Echo "Найдено ssh-agent $ SSH_AUTH_SOCK"
       Echo "Агент pid $ SSH_AGENT_PID"
       вернуть
     фи
   сделанный
   Eval $ (ssh-agent -t 14400)
   SSH-добавить
 }
  • Передача агента SSH не работает
  • TortoiseGit с ключом openssh не аутентифицируется с использованием ssh-agent
  • Сохранить идентификаторы, добавленные ssh-add, чтобы они сохранялись
  • Возможно ли создать ssh-агент для нового сеанса tmux?
  • Давайте будем гением компьютера.