我想通过 SSH 在网络(静态以太网)上的多台计算机之间进行通信。为了做到这一点,我需要运行ssh-add
每次我在特定机器上登录时。
我该怎么做才能使其设置一次并且每次登录或重新启动计算机时都不会要求我输入密码?
我知道有一种方法可以在bash_profile
文件中添加一些行,但每次重新启动/登录特定计算机时我仍然需要输入密码。
if [ -z "$SSH_AUTH_SOCK" ] ; then
eval `ssh-agent -s`
ssh-add
fi
答案1
这是安全性和便利性之间权衡的典型例子。幸运的是,有很多选择。最合适的解决方案取决于使用场景和所需的安全级别。
带密码的 ssh 密钥,无 ssh-agent
现在每次使用密钥进行身份验证时都必须输入密码。虽然从安全角度来看这是最好的选择,但它的可用性最差。这也可能导致选择弱密码,以减轻重复输入密码的负担。
带有密码的 ssh 密钥,以及 ssh-agent
添加以下内容~/.bash_profile
将在登录时自动启动ssh-agent
并加载 ssh 密钥:
if [ -z "$SSH_AUTH_SOCK" ] ; then
eval `ssh-agent -s`
ssh-add
fi
现在每次登录时都必须输入密码。虽然从可用性的角度来看稍好一些,但这有一个缺点,即ssh-agent
无论在登录会话期间是否使用密钥,都会提示输入密码。每个新登录还会生成一个不同的ssh-agent
实例,即使在注销后,该实例仍会在内存中使用添加的键运行,除非明确终止。
要ssh_agent
在注销时终止,请将以下内容添加到~/.bash_logout
if [ -n "$SSH_AUTH_SOCK" ] ; then
eval `/usr/bin/ssh-agent -k`
fi
或以下内容~/.bash_profile
trap 'test -n "$SSH_AUTH_SOCK" && eval `/usr/bin/ssh-agent -k`' 0
通过在文件系统中的ssh-agent
固定位置(例如在科林·安德森的回答。这是对生成多个代理实例的改进。但是,除非显式终止,否则解密后的密钥在注销后仍保留在内存中。
在桌面上,桌面环境中包含 ssh 代理,例如Gnome 密钥环 SSH 代理,可能是一种更好的方法,因为它们通常可以在登录会话期间第一次使用 ssh 密钥时提示输入密码,并将解密的私钥存储在内存中直到会话结束。
带有密码的 ssh 密钥,以及 ssh-ident
ssh-ident
是一个实用程序,可以ssh-agent
代表您进行管理并根据需要加载身份。它仅在需要时添加密钥,无论有多少终端、SSH 或登录会话需要访问ssh-agent
.它还可以添加和使用不同的代理和不同的密钥集,具体取决于您连接到的主机或ssh
从中调用的目录。这允许在对不同主机使用代理转发时隔离密钥。它还允许在 GitHub 等网站上使用多个帐户。
要启用ssh-ident
,请安装它并将以下别名添加到您的~/.bash_profile
:
alias ssh='/path/to/ssh-ident'
带有密码的 ssh 密钥,以及 keychain
keychain
是一个小型实用程序,它ssh-agent
代表您进行管理,并允许ssh-agent
在登录会话结束时保持运行。在后续登录时,keychain
将连接到现有ssh-agent
实例。实际上,这意味着仅在重新启动后首次登录时才必须输入密码。在后续登录时,ssh-agent
将使用现有实例中的未加密密钥。这对于在cron
没有无密码 ssh 密钥的作业中允许无密码 RSA/DSA 身份验证也很有用。
要启用keychain
,请安装它并向以下添加类似内容~/.bash_profile
:
eval `keychain --agents ssh --eval id_rsa`
从安全角度来看,ssh-ident
和keychain
比仅限于特定会话生命周期的实例更糟糕ssh-agent
,但它们提供了很高的便利性。为了提高 的安全性keychain
,有些人将--clear
选项添加到他们的~/.bash_profile
钥匙串调用中。通过这样做,必须在登录时重新输入密码(如上所述),但cron
在用户注销后作业仍然可以访问未加密的密钥。这keychain
维基页面有更多信息和示例。
没有密码的 ssh 密钥
从安全角度来看,这是最糟糕的选择,因为私钥一旦暴露就完全不受保护。然而,这是确保重新启动后无需重新输入密码的唯一方法。
带有密码的 ssh 密钥,以及 ssh-agent
,将密码短语传递给 ssh-add
从脚本
ssh-add
虽然从脚本传递密码似乎是一个简单的想法,例如echo "passphrase\n" | ssh-add
,但这并不像看起来那么简单ssh-add
不读取密码stdin
,而是/dev/tty
直接打开读取。
这可以是解决了和expect
,一种用于自动化交互式应用程序的工具。以下是使用脚本中存储的密码添加 ssh 密钥的脚本示例:
#!/usr/bin/expect -f
spawn ssh-add /home/user/.ssh/id_rsa
expect "Enter passphrase for /home/user/.ssh/id_rsa:"
send "passphrase\n";
expect "Identity added: /home/user/.ssh/id_rsa (/home/user/.ssh/id_rsa)"
interact
请注意,由于密码以明文形式存储在脚本中,从安全角度来看,这并不比拥有无密码 ssh 密钥更好。如果要使用此方法,请务必确保expect
包含密码短语的脚本具有适当的权限设置,使其只能由密钥所有者读取、写入和运行。
答案2
将其添加到您的~/.bashrc
,然后注销并重新登录即可生效。
if [ ! -S ~/.ssh/ssh_auth_sock ]; then
eval `ssh-agent`
ln -sf "$SSH_AUTH_SOCK" ~/.ssh/ssh_auth_sock
fi
export SSH_AUTH_SOCK=~/.ssh/ssh_auth_sock
ssh-add -l > /dev/null || ssh-add
这只会在您每次重新启动后首次登录时提示输入密码。ssh-agent
只要它运行,它就会继续重复使用相同的内容。
答案3
与OP的问题没有密切关系,但可能对其他人有用:从 7.2.0 开始,有一个选项允许在首次身份验证时ssh
添加密钥;ssh-agent
该选项可以在系统范围或您的个人文件中AddKeysToAgent
设置为yes
、no
、ask
、 或。confirm
.ssh/config
答案4
以下是自动化 SSH 密码的解决方法。
创建一个单行脚本,将您的密码打印到标准输出,例如:
echo 'echo MY_SSH_PASSWORD' > ~/.print_ssh_password && chmod 700 ~/.print_ssh_password
重要提示:确保将前导空格复制到防止将您的密码存储到您的历史记录中。
并使用以下方法之一。
使用标准输入方法:
cat ~/.ssh/id_rsa | SSH_ASKPASS=~/.print_ssh_password ssh-add -
或者命名管道方法:
-
mkfifo --mode 0600 ~/.ssh_fifo
ssh-add
通过指定用于身份验证的程序来运行:cat ~/.ssh/id_rsa >~/.ssh_fifo | SSH_ASKPASS=~/.print_ssh_password ssh-add ~/.ssh_fifo
看:
man ssh-add
阅读更多有关SSH_ASKPASS
.-