ssh-agent后台运行

介绍 ssh-agent 原理以及使用方法。


描述

因为要在本机执行一些git操作,配置了多ssh-key,但每次打开终端都要执行eval $(ssh-agent -s)然后再执行ssh-add操作,查看ssh-agent手册发现ssh-add 这个命令不是用来永久性的记住你所使用的私钥的。

实际上,它的作用只是把你指定的私钥添加到 ssh-agent 所管理的一个session 当中。而 ssh-agent 是一个用于存储私钥的临时性的 session 服务,也就是说当你重启之后,ssh-agent服务也就重置了。

最快速的解决办法就是:

vim ~/.bashrc

添加

evalssh-agent -s# ssh-agent 依赖于特殊环境变量,使用 eval 以正确产生环境变量

ssh-add $HOME/.ssh/id_rsa

但这样会有个问题,当退出运行 ssh-agent 的会话后,ssh-agent 会被关闭,这样一来会影响后续密钥认证过程,导致自动 ssh 失败、ssh 脚本运行出错…

而且如果打开多终端后,后台会开启多个ssh-agent进程.

让我们先来看一下ssh-agent是如何工作的:

$ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-sp4EAi4iNWF5/agent.26520; export SSH_AUTH_SOCK;
SSH_AGENT_PID=26521; export SSH_AGENT_PID;
echo Agent pid 26521;


ps x | grep ssh-agent
21983 ?        Ss     0:00 ssh-agent
26521 ?        Ss     0:00 ssh-agent
26540 pts/5    S+     0:00 grep --color=auto ssh-agent

我们可以从第一个命令中得到$SSH_AUTH_SOCK 以及 $SSH_AGENT_PID.

其中,$SSH_AGENT_PID 这个就是ssh-agent的id,我们可以通过ssh-agent -k $SSH_AGENT_PID 来干掉它

非常重要的环境变量是$SSH_AUTH_SOCK, 这个环境变量非常重要,如果这个变量有问题,你无法使用ssh-add命令来添加私钥

在~/.bashrc中使用脚本使ssh-agent后台运行

对于 GnomeGNOME SSH Keyring Agent 较好地处理了 ssh-key的使用问题。

对于非 gnome 的 bash 环境,可以将如下命令添加到 ~/.bashrc或者~/.bash_profile中来加载无密码的 ssh-key:

下面的脚本可让ssh-agent在后台运行并使多终端使用同一个ssh-agent服务且自动添加$HOME/id_rsa私钥文件。

findAgent=`find /tmp/ -type s -name agent.\* 2> /dev/null | grep '/tmp/ssh-.*/agent.*'`
if [ $? -ne  0 ];then
        eval `ssh-agent`
        #ln -sf "$SSH_AUTH_SOCK" $findAgent
        ssh_keys=`find $HOME/.ssh/  -name  "id_rsa*" |grep -v pub`
        ssh_agent_keys=$(ssh-add -l | awk '{key=NF-1; print $key}')
        ssh_keys_count=`find $HOME/.ssh/  -name  "id_rsa*" |grep -v pub |wc -l`
        ssh_agent_keys_count=$(ssh-add -l | awk '{key=NF-1; print $key}' |wc -l)
        for k in "${ssh_keys}"; do
                for l in "${ssh_agent_keys}"; do
                        if  [ $ssh_keys_count != $ssh_agent_keys_count ];then
                                if [ "$k" != "$l" ]; then
                                        ssh-add $k > /dev/null 2>&1
                                fi
                        fi
                done
        done


else
export SSH_AUTH_SOCK=$findAgent
        ssh_keys=`find $HOME/.ssh/  -name  "id_rsa*" |grep -v pub`
        ssh_agent_keys=$(ssh-add -l | awk '{key=NF-1; print $key}')
        ssh_keys_count=`find $HOME/.ssh/  -name  "id_rsa*" |grep -v pub |wc -l`
        ssh_agent_keys_count=$(ssh-add -l | awk '{key=NF-1; print $key}' |wc -l)
        for k in "${ssh_keys}"; do
                for l in "${ssh_agent_keys}"; do
                        if  [ $ssh_keys_count != $ssh_agent_keys_count ];then
                                if [ "$k" != "$l" ]; then
                                        ssh-add $k > /dev/null 2>&1
                                fi
                        fi
                done
        done
fi

关闭终端时退出ssh-agent

vim ~/.bash_logout

if [ -n "$SSH_AUTH_SOCK" ] ; then
  eval `/usr/bin/ssh-agent -k`
fi

如果 ssh-key有密码,可以考虑在脚本中使用 expect 自动交互加载 key files,此方法适用于bash终端,对于zsh可能有点问题.

使用keychain控制ssh-agent后台运行

keychain is a small utility which manages ssh-agent on your behalf and allows the ssh-agent to remain running when the login session ends. On subsequent logins, keychain will connect to the existing ssh-agent instance. In practice, this means that the passphrase must be be entered only during the first login after a reboot. On subsequent logins, the unencrypted key from the existing ssh-agent instance is used. This can also be useful for allowing passwordless RSA/DSA authentication in cron jobs without passwordless ssh-keys.

To enable keychain, install it and add something like the following to ~/.bash_profile:

sudo apt-get install keychain
eval `keychain --agents ssh --eval id_rsa`

From a security point of view, ssh-ident and keychain are worse than ssh-agent instances limited to the lifetime of a particular session, but they offer a high level of convenience. To improve the security of keychain, some people add the –clear option to their ~/.bash_profile keychain invocation. By doing this passphrases must be re-entered on login as above, but cron jobs will still have access to the unencrypted keys after the user logs out. The keychain wiki page has more information and examples.

提示

类似的工具还有GNOME KeyringKWallet,有兴趣的可自行了解。

使用ssh-agent.service控制ssh-agent后台运行

On Arch Linux, the following works really great (should work on all systemd-based distros):

Create a systemd user service, by putting the following to ~/.config/systemd/user/ssh-agent.service:

[Unit]
Description=SSH key agent

[Service]
Type=forking
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
ExecStart=/usr/bin/ssh-agent -a $SSH_AUTH_SOCK

[Install]
WantedBy=default.target

Setup shell to have an environment variable for the socket (.bash_profile, .zshrc, …):

export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"

Enable the service, so it’ll be started automatically on login, and start it:

systemctl --user enable ssh-agent

systemctl --user start ssh-agent

Add the following configuration setting to your ssh config file ~/.ssh/config (this works since SSH 7.2):

AddKeysToAgent yes

This will instruct the ssh client to always add the key to a running agent, so there’s no need to ssh-add it beforehand.

参考:

ssh-agent wiki

How can I run ssh-add automatically, without password prompt

Start ssh-agent on login

Using ssh-agent with ssh

How to make ssh-agent automatically add the key on demand

Use ssh-add automatically

Sharing the same ssh-agent among multiple login sessions

Managing multiple SSH agents

上次更新:
贡献者: iEchoxu