3.3.5 Cygwin下Git访问SSH服务
在本书第5篇第29章中介绍的以公钥认证的方式访问Git服务,是实现Git写操作的最重要的服务。以公钥认证方式访问SSH协议的Git服务器时无须输入口令,而且更安全。使用公钥认证就涉及如何创建公钥/私钥对,以及在SSH连接时应该选择哪一个私钥的问题(如果建立有多个私钥)。
Cygwin下的openssh软件包提供的ssh命令和Linux下的ssh命令没有什么区别,也提供了ssh-keygen命令来管理SSH公钥/私钥对。但是,Cygwin当前的openssh(版本号:5.7p1-1)有一个Bug,使用Git克隆采用SSH协议的版本库时偶尔会中断,从而无法完成版本库的克隆。示例如下:
$git clone git@bj.ossxp.com:ossxp/gitbook.git
Cloning into gitbook…
remote:Counting objects:3486,done.
remote:Compressing objects:100%(1759/1759),done.
fatal:The remote end hung up unexpectedly MiB|3.03 MiB/s
fatal:early EOFs:75%(2615/3486),13.97 MiB|3.03 MiB/s
fatal:index-pack failed
如果您也遇到同样的问题,建议使用PuTTY提供的plink.exe作为SSH客户端,替代Cygwin自带的ssh命令。
1.安装PuTTY
PuTTY是Windows下的一个开源软件,提供SSH客户端服务,还包括公钥管理的相关工具。访问PuTTY的主页(http://www.chiark.greenend.org.uk/~sgtatham/putty/),下载并安装PuTTY。安装完毕会发现PuTTY软件包包含了多个可执行程序,下面几个命令用于与Git的整合。
Plink:即plink.exe,是命令行的SSH客户端,用于替代ssh命令。默认安装于C:\Program Files\PuTTY\plink.exe路径中。
PuTTYgen:用于管理PuTTY格式的私钥,也可以用于将openssh格式的私钥转换为PuTTY格式的私钥。
Pageant:SSH认证代理,运行于后台,负责为SSH连接提供私钥访问服务。
2.PuTTY格式的私钥
PuTTY使用专有格式的私钥文件(扩展名为.ppk),而不能直接使用openssh格式的私钥。也就是用openssh的ssh-keygen命令创建的私钥不能直接被PuTTY拿过来使用,必需经过转换,程序PuTTYgen可以实现私钥格式的转换。
运行PuTTYgen程序,如图3-15所示。
图 3-15 运行PuTTYgen程序
PuTTYgen既可以重新创建私钥文件,又可以通过点击加载按钮(load)读取openssh格式的私钥文件,从而可以将其转换为PuTTY格式的私钥。点击加载按钮,会弹出文件选择对话框,选择openssh格式的私钥文件(如文件id_rsa),如果转换成功,会显示如图3-16的界面。
图 3-16 PuTTYgen完成私钥加载
然后点击"Save private key"(保存私钥),就可以将私钥保存为PuTTY的.ppk格式,例如将私钥保存到文件~/.ssh/jiangxin-cygwin.ppk中。
3.Git使用Pageant进行公钥认证
Git在使用命令行工具Plink(plink.exe)作为SSH客户端访问SSH协议的版本库服务器时,如何选择公钥呢?使用Pageant是一个非常好的选择。Pageant是PuTTY软件包中的代理软件,为各个PuTTY应用提供私钥请求,当Plink连接SSH服务器需要请求公钥认证时,Pageant就会给Plink提供相应的私钥。
运行Pageant,启动后会在托盘区显示一个图标,在后台运行。使用鼠标右键单击Pageant的图标,就会弹出相关的菜单,如图3-17所示。
图 3-17 Pageant的弹出菜单
点击弹出菜单中的"Add Key"(添加私钥)按钮,会弹出文件选择框,选择扩展名为.ppk的PuTTY格式的公钥,即完成了Pageant的私钥准备工作。
接下来,还需要对Git进行设置,设置Git使用plink.exe作为SSH客户端,而不是默认的ssh命令。通过设置GIT_SSH环境变量即可实现:
$export GIT_SSH=/cygdrive/c/Program\Files/PuTTY/plink.exe
上面在设置GIT_SSH环境变量的过程中使用了Cygwin格式的路径,而非Windows格式的,因为Git是在Cygwin的环境中调用plink.exe命令的,所以要使用Cygwin能够理解的路径。
这样就可以用Git访问SSH协议的Git服务器了。运行在后台的Pageant会在需要的时候为plink.exe提供私钥访问服务,但在首次连接一个使用SSH协议的Git服务器的时候,很可能会因为远程SSH服务器的公钥没有经过确认而导致git命令执行失败。例如:
$git clone git@bj.ossxp.com:ossxp/gitbook.git
Cloning into gitbook…
The server's host key is not cached in the registry.You
have no guarantee that the server is the computer you
think it is.
The server's rsa2 key fingerprint is:
ssh-rsa 2048 49:eb:04:30:70:ab:b3:28:42:03:19:fe:82:f8:1a:00
Connection abandoned.
fatal:The remote end hung up unexpectedly
这是因为在首次连接SSH服务器时要对其公钥进行确认(以防止被钓鱼),而运行于Git下的plink.exe没有机会从用户那里获取输入,以建立对该SSH服务器公钥的信任,因此Git访问失败。解决办法非常简单,直接运行plink.exe连接一次远程SSH服务器,并对公钥确认进行应答即可。操作如下:
$/cygdrive/c/Program\Files/PuTTY/plink.exe git@bj.ossxp.com
The server's host key is not cached in the registry.You
have no guarantee that the server is the computer you
think it is.
The server's rsa2 key fingerprint is:
ssh-rsa 2048 49:eb:04:30:70:ab:b3:28:42:03:19:fe:82:f8:1a:00
If you trust this host,enter"y"to add the key to
PuTTY's cache and carry on connecting.
If you want to carry on connecting just once,without
adding the key to the cache,enter "n".
If you do not trust this host,press Return to abandon the
connection.
Store key in cache?(y/n)
输入"y",将公钥保存在信任链中,以后再和该主机连接时就不会弹出该确认应答了。当然,Git命令也就可以成功执行了。
4.使用自定义SSH脚本取代Pageant
使用Pageant时还要在它每次启动时手动选择私钥文件,这比较麻烦。实际上,可以创建一个脚本对plink.exe进行封装,在封装的脚本中使用-i参数指定私钥文件。
例如,创建脚本~/bin/ssh-jiangxin,文件内容如下:
!/bin/sh
/cygdrive/c/Program\Files/PuTTY/plink.exe-T-i\
c:/cygwin/home/jiangxin/.ssh/jiangxin-cygwin.ppk$*
设置该脚本为可执行脚本。
$chmod a+x~/bin/ssh-jiangxin
使用下面的命令通过该脚本与远程SSH服务器连接:
$~/bin/ssh-jiangxin git@bj.ossxp.com
Using username "git".
hello jiangxin,the gitolite version here is v1.5.5-9-g4c11bd8
the gitolite config gives you the following access:
R gistore-bj.ossxp.com/.*$
R gistore-ossxp.com/.*$
C R W ossxp/.*$
R W test/repo1
R W test/repo2
R W test/repo3
@R@W test/repo4
@C@R W users/jiangxin/.+$
设置GIT_SSH变量,使之指向新建立的脚本,然后就可以脱离Pageant来连接SSH协议的Git库了。
$export GIT_SSH=~/bin/ssh-jiangxin