测试小站: 处理网 回收帮 培训网 富贵论坛 老富贵论坛

[SSH,命令行,Server,Git,大小写]多 SSH Key 管理技巧与 Git 多账户登录问题

   对很多开发者,尤其是手握几台甚至几十台机器的同学而言,登录到远程机器处理事务应该是家常便饭。如果你也是其中一员,悄悄问一句,你平时是如何记住一堆帐号、机器地址以及一些附加登录选项的呢?或许你也是这么干的:

  倘若你有一个远程服务器,地址为 test.server, 防止人为攻击,你将 ssh 的端口号从 22 改成了 8892,当你需要登录到这台机器时,需要这么做:

  ~ ssh YOURNAME@test.server -p 8892

  password: *******

  尚好。如果你先前已经将已经注册了一个公钥/私钥对,并且正确的部署到了远程机器,你可以省却输入密码这个环节(推荐学习 ssh-copy-id 命令)。

  为了可以再懒一点,索性将这一串代码添加一个 alias:

  ~ aliastest='ssh YOURNAME@test.server -p 8892'

  ~ test

  一条 test 命令即可让你登录到服务器,对于只有一两台远程机器的你,应该算是特别便捷了。

  多 SSH Key 的管理

  SSH 连接建立之前,会在系统中寻找它的配置,一般有两个位置。

  /etc/ssh/ssh_config 这里是对所有用户适用的全局配置~/.ssh/config 或者 $HOME/.ssh/config 这是用户的个人配置,这些配置会覆盖全局配置

  注意:一般来说,我们给 ~/.ssh 文件夹赋予的权限为 0700。

  配置格式比较简单,以下配置等同于上面我们的登录命令设置:

  Host test

  HostName test.server

  User YOURNAME

  Port 8892

  可以是 param value 也可以为 param=value,其中 param 对大小写不敏感,value 对大小写敏感。

  使用 ssh test 即可完成登录,当我们有稍微麻烦点配置的时候,如数据库的 3306 端口对外不开放,可以开放另一个接口,然后内部跳转到 3306,使用命令行的写法是:

  ssh -f -N -L 8999:127.0.0.1:3306test@database.server

  大串的命令行,过多的参数,实在是有点不好记。而在 config 文件中的配置就一目了然:

  Hosttest

  HostNametest.server

  UserYOURNAME

  LocalForward 8999 127.0.0.1:3306

  当你有多台远程终端的时候,config 文件的优势就更加明显了:

  # serverlist

  Host list

  HostName *.serverlist

  User YOURNAME

  IdentityFile ~/.ssh/serverlist.key

  # personal server

  Host personal

  HostName proxy1.barretlee proxy2.barretlee

  User barretlee

  IdentityFile ~/.ssh/proxy.barretlee.key

  # school

  HostName 222.20.74.89

  User school

  LocalForward 8999127.0.0.1:3306

  IdentityFile ~/.ssh/school.key

  # and so on.

  这里常用的的 param 也不是很多:

  Host,SSH 连接名HostName,如上所示,可以是通配符,可以是 IP,也可以是域名等User,登录的用户名IdentifyFile,version 1 协议下默认是 ~/.ssh/identify,version 2 协议下,默认是依次匹配:~/.ssh/id_dsa,~/.ssh/id_ecdsa,~/.ssh/id_rsa,还有 version 2 兼容模式。LocalForward 端口的内部跳转Port,端口设置,默认 SSH 的端口是 22Protocal,协议版本号,1 或者 2

  Git 多账户登录问题

  向仓库 push 代码之前,我们都会做一番设置,简单归纳为如下几步:

  注册获取用户名 barretlee创建仓库 barretlee/test.git创建密钥,ssh-keygen -t rsa -C "barret.china@gmail"将公钥 id_rsa 填到 Git Server 上(如果没有可视化界面,还需要登录到 Server 命令行操作推送)本地通过 ssh-agent 将密钥添加到 session 中,ssh-add id_rsa,部分终端中还需要手动开启 ssh-agent然后测试连接,如 github 中, ssh -T git@git.github看到了 ‘welcome barretlee…’ 的提示,开始 push 你的代码

  突然有一天,你又注册了一个帐号 xiaohuzige,也走了一遍上面的流程,发现死活也连接不上,服务器总是提示:You have no permission to access this repo,这是怎么回事呢?

  这个时候,你可以输入这个命令,看看是哪个环节出了问题:

  ? ~ ssh -vT git@github

  OpenSSH_6.9p1, LibreSSL 2.1.7

  debug1: Reading configuration data /Users/barretlee/.ssh/config

  debug1: /Users/barretlee/.ssh/config line 2: Applying options for *

  debug1: Reading configuration data /etc/ssh/ssh_config

  debug1: /etc/ssh/ssh_config line 20: Applying options for *

  debug1: /etc/ssh/ssh_config line 102: Applying options for *

  debug1: Connecting to github [192.30.252.128] port 22.

  debug1: Connection established.

  debug1: key_load_public: No such file or directory

  debug1: identity file /Users/barretlee/.ssh/id_rsa type -1

  debug1: key_load_public: No such file or directory

  debug1: identity file /Users/barretlee/.ssh/id_rsa-cert type -1

  debug1: key_load_public: No such file or directory

  debug1: identity file /Users/barretlee/.ssh/id_dsa type -1

  debug1: key_load_public: No such file or directory

  debug1: identity file /Users/barretlee/.ssh/id_dsa-cert type -1

  debug1: key_load_public: No such file or directory

  debug1: identity file /Users/barretlee/.ssh/id_ecdsa type -1

  debug1: key_load_public: No such file or directory

  debug1: identity file /Users/barretlee/.ssh/id_ecdsa-cert type -1

  debug1: key_load_public: No such file or directory

  debug1: identity file /Users/barretlee/.ssh/id_ed25519 type -1

  debug1: key_load_public: No such file or directory

  debug1: identity file /Users/barretlee/.ssh/id_ed25519-cert type -1

  debug1: Enabling compatibility mode for protocol 2.0

  debug1: Local version string SSH-2.0-OpenSSH_6.9

  debug1: Remote protocol version 2.0, remote software version libssh-0.7.0

  debug1: no match: libssh-0.7.0

  debug1: Authenticating to github:22 as 'git'

  debug1: SSH2_MSG_KEXINIT sent

  debug1: SSH2_MSG_KEXINIT received

  debug1: kex: server->client chacha20-poly1305@openssh none

  debug1: kex: client->server chacha20-poly1305@openssh none

  debug1: expecting SSH2_MSG_KEX_ECDH_REPLY

  debug1: Server host key: ssh-rsa SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8

  debug1: Host 'github' is known and matches the RSA host key.

  debug1: Found key in /Users/barretlee/.ssh/known_hosts:4

  Warning: Permanently added the RSA host key for IP address '192.30.252.128' to the list of known hosts.

  debug1: SSH2_MSG_NEWKEYS sent

  debug1: expecting SSH2_MSG_NEWKEYS

  debug1: SSH2_MSG_NEWKEYS received

  debug1: Roaming not allowed by server

  debug1: SSH2_MSG_SERVICE_REQUEST sent

  debug1: SSH2_MSG_SERVICE_ACCEPT received

  debug1: Authentications that can continue: publickey

  debug1: Next authentication method: publickey

  debug1: Trying private key: /Users/barretlee/.ssh/id_rsa

  debug1: Trying private key: /Users/barretlee/.ssh/id_dsa

  debug1: Trying private key: /Users/barretlee/.ssh/id_ecdsa

  debug1: Trying private key: /Users/barretlee/.ssh/id_ed25519

  debug1: No more authentication methods to try.

  Permission denied (publickey).

  不加 v 参数,输出的内容很简洁:

  ? ~ ssh -T git@github

  Warning: Permanently added the RSA host key for IP address '192.30.252.129' to the list of known hosts.

  Permission denied (publickey).

  好吧,我知道你看不懂上面一长串的内容,也没心情看下去,但是你可以把焦点落到重复的那几段:

  debug1: ...

  debug1: xxx, No such file or directory

  debug1: ...

  debug1: Trying private key: /Users/barretlee/.ssh/xxx

  debug1: ...

  之前我们提到了 Protocal Version 1 和 Version 2,不同的版本号,默认的私钥地址不一样,所以程序会不断去尝试寻找默认的地址,如果没找到,最后会提示,授权失败,禁止访问。

  我们可以在 push 代码之前,使用 ssh-agent 来管理私钥的 session,如:

  ? ~ ssh-add .ssh/coding_barretlee

  Identity added: ~/.ssh/coding_barretlee (coding_barretlee)

  ? ~ ssh-add .ssh/github_barretlee

  Identity added: ~/.ssh/github_barretlee (github_barretlee)

  那么当程序寻找私钥的时候,就会优先到 ssh-agent 添加的 session 中寻找。session 的生命周期不是很长,当你重启电脑之后它就没了。如果你有遇到了 Permission Denied 的提示,请重新执行 ssh-add 命令。

  当你在某个 Git 服务器上有多个帐号的时候,可能某个帐号总是提示:Permission Denied。拿 coding.net 上来说,我有两个账户,一个是 barretlee,另一个是 taobaofed,由于先前我一直用的 barretlee 账户,后来者 taobaofed 的代码死活推不上去。反反复复地检查配置,反反复复地检查上传的公钥,反反复复地使用 ssh -T git@git.coding.net 测试,没看到哪里不对,然而 taobaofed 的代码就是推不上去,这是怎么回事呢?

  当然,上面 SSH 介绍了那么多,其简明易懂的配置在这里也是可以用上的:

  ### default for all ##

  Host *

  ForwardAgent no

  ForwardX11 no

  ForwardX11Trusted yes

  User nixcraft

  Port 22

  Protocol 2

  ServerAliveInterval 60

  ServerAliveCountMax 30

  ## barretlee coding ##

  Host coding-barretlee

  HostName git.coding.net

  User barretlee

  IdentityFile ~/.ssh/coding_barretlee

  ## taobaofed coding ##

  Host coding-taobaofed

  HostName git.coding.net

  User taobaofed

  IdentityFile ~/.ssh/coding_taobaofed

  使用这种配置,我们可以避免使用 ssh-agent 添加 session 操作。可是,我就是按照上面的方式配置的呀,依然不行!

  这里的问题在于,我们的 User 项不正确,每次推送代码的时候,git 会读取上次的的 User 配置,而我的配置是 barretlee,那么下次提交代码的时候虽然 IdentityFile 用对了,但是 User 不是 taobaofed,所以死活也推不动代码。

  解决的方案很简单,如果在下载代码之前就已经设置好了两个帐号,你可以通过如下命令克隆代码:

  ? ~ git clone git@coding-taobaofed:taobaofed/blog.git

  如果是在已有的仓库中,其默认 origin 配置会是:

  git.coding/taobaofed/blog.git 或者 git@

  git.coding.net:taobaofed/blog.git,你可以将仓库下的 .git/config 文件修改下:

  [remote "origin"]

  url=git@coding-taobaofed:taobaofed/blog.git

  fetch=+refs/heads/*:refs/remotes/origin/*

  防止克隆其他仓库代码也出现问题,我们可以将 ~/.ssh/config 稍加修改:

  ## barretlee coding ##

  Host git.coding.net coding-barretlee

  HostName git.coding.net

  User barretlee

  IdentityFile ~/.ssh/coding_barretlee

  ## taobaofed coding ##

  Host coding-taobaofed

  HostName git.coding.net

  User taobaofed

  IdentityFile ~/.ssh/coding_taobaofed

  那么,通过正常的 clone(如git clone git@

  git.coding.net:barretlee/blog.git)就不会出现 Permission Denied 的提示了。

  最后

  撰写本文之前,我已经踩坑三小时,花了三个小时,摸索出来这么些东西,感觉以后妈妈再也不用担心我的 Git/SSH 的配置问题了。

  最主要的手段依然是通过 ssh -vT 查看 SSH 交互过程中出现了什么障碍,debug 信息还是很有考究价值的!

posted @ 2021-12-09 13:41  linjingyg  阅读(196)  评论(0)    收藏  举报