问题描述

从Ubuntu 12.04升级到14.04之后,github的SSH认证总是失败,重新添加新的Key也不行。

$git push
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

查看~/.ssh目录可以看出目录中有多对key文件。工作中,你可能使用公用的github,也可能公司有自己搭建的私有代码托管gitlab,这就需要创建多对key,而每一对key文件对应着不同的服务器。

$ls ~/.ssh/
aws_ec2.pem  gitshell.pub    id_rsa.gibh.gitlab      id_rsa.github.pub  onecoao.pem
config       git_skybit      id_rsa.gibh.gitlab.pub  known_hosts
gitshell     git_skybit.pub  id_rsa.github           known_hosts.old

所以很有可能的情况是,key配置虽然正确,但是git命令在ssh连接时根本没有找到对应的key。

系统环境

  • Ubuntu: 14.04
  • git: 1.9.1
  • ssh: OpenSSH_6.6.1p1 Ubuntu-2ubuntu2, OpenSSL 1.0.1f 6 Jan 2014

解决方法

测试ssh发现,认证过程中ssh会读取两个配置文件,一个是自己配置的~/.ssh/config,另一个是系统自带的/etc/ssh/ssh_config。 怎么让不同的服务器git访问使用不同key pair,就是这两个配置文件的一种功能,即通过配置文件指定每个Host对应的key文件。

$ssh -vT git@github.com
OpenSSH_6.6.1, OpenSSL 1.0.1f 6 Jan 2014
debug1: Reading configuration data /home/yeyanbo/.ssh/config
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to github.com [192.30.252.129] port 22.
debug1: Connection established.
debug1: identity file /home/yeyanbo/.ssh/id_rsa type -1
debug1: identity file /home/yeyanbo/.ssh/id_rsa-cert type -1
debug1: identity file /home/yeyanbo/.ssh/id_dsa type -1
debug1: identity file /home/yeyanbo/.ssh/id_dsa-cert type -1
debug1: identity file /home/yeyanbo/.ssh/id_ecdsa type -1
debug1: identity file /home/yeyanbo/.ssh/id_ecdsa-cert type -1
debug1: identity file /home/yeyanbo/.ssh/id_ed25519 type -1
debug1: identity file /home/yeyanbo/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2
debug1: Remote protocol version 2.0, remote software version libssh-0.6.0
debug1: no match: libssh-0.6.0
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: RSA 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
debug1: Host 'github.com' is known and matches the RSA host key.
debug1: Found key in /home/yeyanbo/.ssh/known_hosts:3
debug1: ssh_rsa_verify: signature correct
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: /home/yeyanbo/.ssh/id_rsa
debug1: Trying private key: /home/yeyanbo/.ssh/id_dsa
debug1: Trying private key: /home/yeyanbo/.ssh/id_ecdsa
debug1: Trying private key: /home/yeyanbo/.ssh/id_ed25519
debug1: No more authentication methods to try.
Permission denied (publickey).

查看一下这两个文件的内容:

$cat ~/.ssh/config 
Host gitlab
    User git
    HostName 192.168.1.214
    IdentityFile ~/.ssh/id_rsa.gibh.gitlab

Host github
    User git
    HostName github.com
    IdentityFile ~/.ssh/id_rsa.github

Host gitshell
    User git
    HostName gitshell.com
    IdentityFile ~/.ssh/gitshell
$cat /etc/ssh/ssh_config
# This is the ssh client system-wide configuration file.  See
# ssh_config(5) for more information.  This file provides defaults for
# users, and the values can be changed in per-user configuration files
# or on the command line.

# Configuration data is parsed as follows:
#  1. command line options
#  2. user-specific file
#  3. system-wide file
# Any configuration value is only changed the first time it is set.
# Thus, host-specific definitions should be at the beginning of the
# configuration file, and defaults at the end.

# Site-wide defaults for some commonly used options.  For a comprehensive
# list of available options, their meanings and defaults, please see the
# ssh_config(5) man page.
Host *
#   ForwardAgent no
#   ForwardX11 no
#   ForwardX11Trusted yes
#   RhostsRSAAuthentication no
#   RSAAuthentication yes
#   PasswordAuthentication yes
#   HostbasedAuthentication no
#   GSSAPIAuthentication no
#   GSSAPIDelegateCredentials no
#   GSSAPIKeyExchange no
#   GSSAPITrustDNS no
#   BatchMode no
#   CheckHostIP yes
#   AddressFamily any
#   ConnectTimeout 0
#   StrictHostKeyChecking ask
#   IdentityFile ~/.ssh/identity
#   IdentityFile ~/.ssh/id_rsa
#   IdentityFile ~/.ssh/id_dsa
#   Port 22
#   Protocol 2,1
#   Cipher 3des
#   Ciphers aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc
#   MACs hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-ripemd160
#   EscapeChar ~
#   Tunnel no
#   TunnelDevice any:any
#   PermitLocalCommand no
#   VisualHostKey no
#   ProxyCommand ssh -q -W %h:%p gateway.example.com
#   RekeyLimit 1G 1h
    SendEnv LANG LC_*
    HashKnownHosts yes
    GSSAPIAuthentication yes
    GSSAPIDelegateCredentials no

每一个Host代表一个服务器配置的开始。HostName参数指定服务器地址,IdentityFile参数指定所要用到的key文件。

第一个文件是自定义配置的,是升级后从12.04版本保留下来的,可以看出Host后面为服务器的名称,下面的HostName指定了服务器地址。而第二个文件为14.04系统自带的配置,这里Host后面用星号代替,而后面启用和没启用的参数中却没有HostName。

再看上面的ssh测试结果,本次测试中,ssh使用了系统配置文件/etc/ssh/ssh_config中的第19行所对应的Host配置,从而最终选择了默认的~/.ssh/id_rsa文件,而自定义配置文件~/.ssh/config未能产生效果。

是否在14.04中,服务器地址应该配置在Host后面?这样猜测不是没有道理的,星号正好可以在ssh连接时,作为服务器筛选的通配符使用。

那么修改一下~/.ssh/config,将HostName去掉,并将地址放到Host后面,修改后内容如下:

Host 192.168.1.214
    User git
    IdentityFile ~/.ssh/id_rsa.gibh.gitlab

Host github.com
    User git
    IdentityFile ~/.ssh/id_rsa.github

Host gitshell.com
    User git
    IdentityFile ~/.ssh/gitshell

再测试ssh,测试结果如下:

$ ssh -vT git@github.com
OpenSSH_6.6.1, OpenSSL 1.0.1f 6 Jan 2014
debug1: Reading configuration data /home/yeyanbo/.ssh/config
debug1: /home/yeyanbo/.ssh/config line 5: Applying options for github.com
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 19: Applying options for *
debug1: Connecting to github.com [192.30.252.128] port 22.
debug1: Connection established.
debug1: identity file /home/yeyanbo/.ssh/id_rsa.github type 1
debug1: identity file /home/yeyanbo/.ssh/id_rsa.github-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1p1 Ubuntu-2ubuntu2
debug1: Remote protocol version 2.0, remote software version libssh-0.6.0
debug1: no match: libssh-0.6.0
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: RSA 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48
debug1: Host 'github.com' is known and matches the RSA host key.
debug1: Found key in /home/yeyanbo/.ssh/known_hosts:3
debug1: ssh_rsa_verify: signature correct
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: Offering RSA public key: /home/yeyanbo/.ssh/id_rsa.github
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug1: key_parse_private2: missing begin marker
debug1: key_parse_private_pem: PEM_read_PrivateKey failed
debug1: read PEM private key done: type <unknown>
Enter passphrase for key '/home/yeyanbo/.ssh/id_rsa.github': 
debug1: key_parse_private2: missing begin marker
debug1: read PEM private key done: type RSA
debug1: Authentication succeeded (publickey).
Authenticated to github.com ([192.30.252.128]:22).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: Sending environment.
debug1: Sending env LANG = zh_CN.UTF-8
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
Hi lijax! You've successfully authenticated, but GitHub does not provide shell access.
debug1: channel 0: free: client-session, nchannels 1
Transferred: sent 3312, received 1768 bytes, in 0.6 seconds
Bytes per second: sent 5392.4, received 2878.5
debug1: Exit status 1

可以看出已经成功找到~/.ssh/config中github的配置,并找到~/.ssh/id_rsa.github秘钥文件。

再进行简短测试,认证成功:)

$ ssh -T git@github.com
Enter passphrase for key '/home/yeyanbo/.ssh/id_rsa.github': 
Enter passphrase for key '/home/yeyanbo/.ssh/id_rsa.github': 
Hi lijax! You've successfully authenticated, but GitHub does not provide shell access.