如何在一个客户端上使用多个SSH私钥的最佳方法

1151
我希望使用多个私钥连接到不同的服务器或同一服务器的不同部分(我的用途是服务器系统管理、Git 管理以及在同一服务器内正常使用 Git)。我尝试简单地将密钥堆叠在 id_rsa 文件中,但无济于事。显然,一个直接的方法是使用以下命令:
ssh -i <key location> login@server.example.com 

这相当繁琐。

你有什么简便的方法建议吗?


6
我写了这篇文章,深入探讨了各种配置及其优缺点。 - Raffi
21个回答

1580

来自我的.ssh/config文件:

Host myshortname realname.example.com
    HostName realname.example.com
    IdentityFile ~/.ssh/realname_rsa # private key for realname
    User remoteusername

Host myother realname2.example.org
    HostName realname2.example.org
    IdentityFile ~/.ssh/realname2_rsa  # different private key for realname2
    User remoteusername

然后您可以使用以下内容进行连接:

ssh myshortname

ssh myother

等等。


7
这真是个好帮手(除了https://dev59.com/-3E95IYBdhLWcg3wMa51#3828682之外)。如果你想使用PuTTY密钥,请按照这里的文档操作:http://blog.padraigkitterick.com/2007/09/16/using-putty-ssh-keys-with-openssh-on-ubuntu - Urda
90
请注意,您还可以为同一“Host”指定多个“IdentityFile”条目,在连接时按顺序尝试。 - sschuberth
2
这让我在我的Windows电脑上省了很多麻烦。谢谢!ssh-agent可以滚粗。 - Derek
2
如果您使用的是Windows系统,而且您的SSH客户端似乎忽略了您的.ssh/config文件,请参考这个答案:https://dev59.com/52kw5IYBdhLWcg3w_feJ - Zachary Yates
20
дҪҝз”ЁIdentitiesOnly yesеҸҜд»ҘйҳІжӯўдҪҝз”Ё~/.ssh/id_rsaжҲ–е…¶д»–иә«д»ҪйӘҢиҜҒдҝЎжҒҜгҖӮ(иҝҷжҳҜеҺҹе§Ӣзј–иҫ‘зҡ„еҶ…е®№) - user3338098
显示剩余10条评论

592

当连接时,您可以指示ssh依次尝试多个密钥。以下是方法:

$ cat ~/.ssh/config
IdentityFile ~/.ssh/id_rsa
IdentityFile ~/.ssh/id_rsa_old
IdentityFile ~/.ssh/id_ed25519
# ... and so on

$ ssh server.example.com -v
....
debug1: Next authentication method: publickey
debug1: Trying private key: /home/example/.ssh/id_rsa
debug1: read PEM private key done: type RSA
debug1: Authentications that can continue: publickey
debug1: Trying private key: /home/example/.ssh/id_rsa_old
debug1: read PEM private key done: type RSA
....
[server ~]$

这样,您就不必指定哪个密钥适用于哪个服务器。它将只使用第一个有效的密钥。

此外,只有在给定服务器愿意接受该密钥时,您才需要输入密码短语。如上所示,即使有密码短语,ssh 也没有尝试为 .ssh/id_rsa 请求密码。

当然,这种方法并不像其他答案中的每个服务器配置那样出色,但至少您无需为连接的每个服务器都添加配置!


20
这是一个很好的解决方案,但并没有完全满足提问者的需求。对我来说,这正是正确的解决方案,并且完美地满足了“在一个客户端上使用多个SSH私钥的最佳方法”的需求。 - Wade
4
似乎在配置文件的主机声明下这并不起作用。 - Maksim Luzik
60
这在使用Git时效果不佳,因为如果您有两个Github部署密钥,列表中的第一个是有效的并且可以正常工作,但随后Github会抱怨仓库不匹配。 - Adam Reis
3
如果SFTP/目标服务器有安全策略锁定帐户(例如在3次多次连接尝试失败后),那么这不会最终锁定该帐户吗?尝试连接,但使用“错误的密钥”文件。 - alchemist.gamma
14
如果您的服务器上安装了类似于fail2ban的软件,需要注意。由于其他密钥产生的失败登录尝试,您可能会被关在其中一个监狱中...请注意。 - Piccolo
显示剩余4条评论

299

前面的回答已经很好地解释了如何创建配置文件来管理多个ssh密钥。我认为,还需要解释的重要事情是在克隆存储库时使用别名替换主机名。

假设您的公司GitHub帐户用户名为abc1234,您的个人GitHub帐户的用户名为jack1234。

并且,假设您创建了两个RSA密钥,即id_rsa_company和id_rsa_personal。那么,你的配置文件将像下面这样:

# Company account
Host company
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa_company

# Personal account
Host personal
HostName github.com
PreferredAuthentications publickey
IdentityFile ~/.ssh/id_rsa_personal

现在,当你从公司的 GitHub 帐户克隆名为 demo 的代码仓库时,仓库的 URL 将类似于:

Repo URL: git@github.com:abc1234/demo.git

现在,在执行git clone时,你应该将上述仓库的URL修改为:

git@company:abc1234/demo.git

注意现在github.com已被我们在配置文件中定义的别名“company”所替代。

同样地,根据配置文件中提供的别名修改个人账户中仓库的克隆URL。


28
我希望我能给这个回答点赞不止一次... 这是处理问题的正确方法,而且比其他选项更安全和更快。还更容易扩展(允许为“同一”主机名定义不同的键)。 - Guy
2
很好的解释!对我来说完美无缺。如果你忘记使用别名克隆仓库,通常可以在之后编辑远程源的URL。 - tkahn
2
请注意,配置文件必须为(chmod 600)。 - Christiano Matos
5
虽然没有明确说明,但这种方法解决了在使用多个密钥与 GitHub 时的一个重要问题:由于您始终作为相同用户“git”登录到 GitHub,因此在任何 GitHub 帐户上保存的任何密钥都将允许进行 SSH 登录。但是,在 SSH 登录后,GitHub 将检查所使用的密钥是否被授权执行特定操作(例如检出存储库),如果您使用错误的密钥,则操作将失败。但是 SSH 部分已成功,因此 SSH 不会尝试其他密钥。该解决方案通过引入主机名别名来解决该问题。太棒了! - ntc2
11
值得一提的是,如果您使用ssh-agent,则应将 IdentitiesOnly yes选项添加到您的配置文件中,否则ssh-agent会尝试使用不同别名的密钥连接到给定别名的主机名相匹配的主机。 - William Stanley
显示剩余4条评论

277

Randal Schwartz的回答几乎完全帮助了我。 由于我在服务器上有不同的用户名,因此我必须在文件中添加User关键字:

Host           friendly-name
HostName       long.and.cumbersome.server.name
IdentityFile   ~/.ssh/private_ssh_file
User           username-on-remote-machine

现在您可以使用友好名称进行连接:

ssh friendly-name

更多关键字可以在OpenSSH手册页中找到。注意:列出的一些关键字可能已经存在于您的/etc/ssh/ssh_config文件中。


如果我没记错的话,当使用user@host进行连接时,你通常会直接在URL中指定用户。 - a1an
5
我更喜欢使用关键词“Port”。另一个有趣的关键词是“StrictHostKeyChecking”。 - Ethan

118
ssh-add ~/.ssh/xxx_id_rsa

在添加之前,请确保您进行测试:

ssh -i ~/.ssh/xxx_id_rsa username@example.com

如果您遇到错误问题,有时更改文件的安全性可以解决问题:

chmod 0600 ~/.ssh/xxx_id_rsa

4
在我看来,这是最简洁优雅的解决方案。非常管用! - artur
6
+1 表示同意修改权限为 0600,因为权限问题导致我无法连接。 - amacy
1
来自在Mac上的Ubuntu,这正是我所需要的。 - Hariom Balhara
注意:之前,我创建了Randal Schwartz(被接受的)答案中推荐的配置文件。我不得不删除那个文件才能使它工作。(在删除该文件后,Randal的答案对我无效,但这个有效)。 - cssyphus
当您将使用 ssh -i 指定身份文件时,为什么需要 ssh-add - atlex2
显示剩余2条评论

103
  1. Generate an SSH key:

     $ ssh-keygen -t rsa -C <email1@example.com>
    
  2. Generate another SSH key:

     $ ssh-keygen -t rsa -f ~/.ssh/accountB -C <email2@example.com>
    

    Now, two public keys (id_rsa.pub, accountB.pub) should be exists in the ~/.ssh/ directory.

     $ ls -l ~/.ssh     # see the files of '~/.ssh/' directory
    
  3. Create configuration file ~/.ssh/config with the following contents:

     $ nano ~/.ssh/config
    
     Host bitbucket.org
         User git
         Hostname bitbucket.org
         PreferredAuthentications publickey
         IdentityFile ~/.ssh/id_rsa
    
     Host bitbucket-accountB
         User git
         Hostname bitbucket.org
         PreferredAuthentications publickey
         IdentitiesOnly yes
         IdentityFile ~/.ssh/accountB
    
  4. Clone from default account.

     $ git clone git@bitbucket.org:username/project.git
    
  5. Clone from the accountB account.

     $ git clone git@bitbucket-accountB:username/project.git
    
注意:由于 User git 指令的存在,您可以省略 repo URL 中的 git@ 部分,从而缩短您的 clone 命令,如下所示:
    $ git clone bitbucket-accountB:username/project.git

这个指令的唯一目的就是如此。如果你不需要它(例如你总是从网站上复制粘贴git clone命令),你可以将其从配置中省略。 在此处查看更多

如果您已经克隆了代码库,您可以更改远程URL:https://devconnected.com/how-to-change-git-remote-origin/ - Daniel Hári

29

我同意Tuomas的观点,建议使用ssh-agent。我还想为工作添加第二个私钥,这篇教程 对我非常有帮助。

步骤如下:

  1. $ ssh-agent bash
  2. $ ssh-add /path.to/private/key,例如 ssh-add ~/.ssh/id_rsa
  3. 通过 $ ssh-add -l 进行验证
  4. 使用 $ssh -v <host url> 进行测试,例如 ssh -v git@assembla.com

4
多年来,我一直使用 ssh-agent,但最近在我的 i3 窗口管理器中切换到了 Gnome 的 gnome-keyring。原因很简单:Gnome Keyring 管理器可以自动添加和删除 ssh 密钥,无需我记住 ssh-add 命令。此外,它还提供了一个密码来解锁这些密钥(并在指定时间后超时以增强安全性)。各有所好。由于我在 Arch 上使用 Gnome 设置,所以与我的设置兼容,非常方便。如果您反对 Gnome,请忽略此评论。 - eduncan911
@eduncan911,我同意gnome-keyring可能会有所帮助,但它实际上无法处理ed25519密钥,因此对我来说是不可行的。更新:从https://wiki.archlinux.org/index.php/GNOME/Keyring#Cannot_handle_ECDSA_and_Ed25519_keys中可以看出,它现在使用系统的ssh-agent,所以这不再是一个问题。 - Brian Minton
ssh-agent bash starts subsession. Also you can just evaluate the output of ssh-agent -s like eval `ssh-agent -s` . After that use ssh-add - Piroxiljin

26

对于我在 MacOs 上,唯一有效的解决方案是在文件~/.ssh/config中添加以下内容:

Host *
  IdentityFile ~/.ssh/your_ssh_key
  IdentityFile ~/.ssh/your_ssh_key2
  IdentityFile ~/.ssh/your_ssh_key3
  AddKeysToAgent yes

your_ssh_key 没有任何扩展名,不要使用 .pub


可以运行但是会提示“load pubkey "path/.ssh/key": invalid format”错误。 - Norman Potts
这是对我有用的一些内容,与你的有点相似: $ eval "$(ssh-agent -s)" $ ssh-add ~/.ssh/{private_key} $ git clone git@{alias}:{github_user}/{repo}.git 然后在 ~/.ssh/config 中添加以下内容: Host github.com-{alias} HostName github.com PreferredAuthentications publickey IdentityFile ~/.ssh/{private_key}{repo}/.git/config 中添加以下内容: [remote "origin"] url = git@github.com-{alias}:{github_user}/{repo}.git fetch = +refs/heads/*:refs/remotes/origin/*. gist - vcamargo
太棒了!在我的Mac OS上运行良好。 - Mukundhan

24

现在,使用Git的最新版本,我们可以在存储库特定的Git配置文件中指定sshCommand

  [core]
      repositoryformatversion = 0
      filemode = true
      bare = false
      logallrefupdates = true
      sshCommand = ssh -i ~/.ssh/id_rsa_user
   [remote "origin"]
      url = git@bitbucket.org:user/repo.git
      fetch = +refs/heads/*:refs/remotes/origin/*

4
这是最正确的操作方式。如果您不想在文件中深入操作,只需在Git存储库中运行“git config --local core.sshCommand"ssh -i ~/.ssh/your_other_rsa_file"”即可。 - Canis
同时也考虑到这种方式迄今为止是最方便的。顺便说一下,@Canis,**--local** 参数并不是真正需要的,它是默认范围。 - undefined

17

我之前遇到过这个问题,当时我有两个Bitbucket账户,并想为它们存储不同的SSH密钥。以下是解决方法:

我创建了两个独立的SSH配置,如下所示。

Host personal.bitbucket.org
    HostName bitbucket.org
    User git
    IdentityFile /Users/username/.ssh/personal
Host work.bitbucket.org
    HostName bitbucket.org
    User git
    IdentityFile /Users/username/.ssh/work

现在,当我需要从我的工作帐户克隆存储库时,命令如下。

git clone git@bitbucket.org:teamname/project.git

我不得不修改这个命令为:

git clone git@**work**.bitbucket.org:teamname/project.git

同样,我个人帐户的克隆命令必须进行修改为:

git clone git@personal.bitbucket.org:name/personalproject.git

有关更多信息,请参阅此链接


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接