在多个登录会话之间共享同一个 `ssh-agent`

int*_*ted 74 ssh session login ssh-agent

有没有一种方便的方法来确保来自给定用户(即我)的所有登录都使用相同的 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;
Run Code Online (Sandbox Code Playgroud)

请告诉我有更好的方法来做到这一点。也请不要挑剔不一致/失态(例如把var东西放进去etc);我前段时间写了这篇文章,从那以后学到了很多东西。

小智 43

ssh -A [user@]remotehost

我想这可能就是你要找的。运行 ssh 时使用 -A 开关转发您的 ssh-agent。这是一个用例:

我有一个远程服务器,上面有一些 git repos,远程指向 github。如果没有在屏幕会话中运行 ssh-agent,我必须输入密钥的密码才能执行“git pull origin master”。嘘!此外,我必须在远程服务器上安装我的私钥- 更多的 Boooo!

相反,只需使用ssh -A [user@]remotehost我本地运行的 ssh-agent 传递。现在,我不再需要我的私钥甚至存在于远程主机上。我认为您根本不需要使用 ssh-agent 编写任何脚本。

  • 不知道这一点,但事实证明,当我解决这个问题时,这正是我所寻找的。 (4认同)
  • 另请参阅“man 5 ssh_config”以了解“ForwardAgent”配置设置。它默认启用代理转发,无需使用“-A”参数。在使用代理转发之前,请注意存在安全风险,远程计算机上的其他特权用户可能会访问转发的代理套接字。手册页上也提到了这一点。 [此处](http://www.symantec.com/connect/articles/ssh-and-ssh-agent)对此进行了很好的解释。 (4认同)
  • 这甚至比我想要的还要好!很好的答案! (2认同)

小智 29

我不妨将我自己的变体加入其中:

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"
Run Code Online (Sandbox Code Playgroud)

然后每次登录时,如果我想要附加代理(我并不总是这样),我只需输入sagent.

  • `如果[!-x "$(which ssh-add)" ];` 应该替换为 `if ! which ssh-add;` 或 `if ! 命令 -v ssh-add`。(记住,`[` 只是一个命令) (2认同)

von*_*gen 22

这是一个在 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
Run Code Online (Sandbox Code Playgroud)

将它添加到您的 .bash_profile 或 .bashrc

来源:http : //www.cygwin.com/ml/cygwin/2001-06/msg00537.html


小智 12

尝试使用钥匙串,它是为此而设计的。 http://www.gentoo.org/doc/en/keychain-guide.xml


Mar*_*kMo 8

我最近开始使用:

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

我所要做的就是添加:

  alias ssh=/path/to/ssh-ident
Run Code Online (Sandbox Code Playgroud)

在我的 .bashrc 文件中。该脚本负责:

  • 在第一次需要时创建代理
  • 按需加载必要的密钥
  • 跨多个登录会话共享代理
  • 管理多个代理,我在线使用的每个“身份”对应一个代理,并根据我连接的主机或当前工作目录使用正确的代理。


use*_*686 7

我更喜欢让事情尽可能简单:(摘自~/.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
}
Run Code Online (Sandbox Code Playgroud)

我之前没想过使用-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
Run Code Online (Sandbox Code Playgroud)