5.3. 使用 SSH 协议
SSH协议用于为Git提供远程读写操作,是远程写操作的标准服务,在智能HTTP协议出现之前,甚至是写操作的唯一标准服务。
5.3.1. SSH协议语法格式
对于拥有shell登录权限的用户帐号,可以用下面的语法访问Git版本库:
语法1: ssh://[<username>@]<server>[:<port>]/path/to/repos/myrepo.git 语法2: [<username>@]<server>:/path/to/repos/myrepo.git
说明:
SSH协议地址格式可以使用两种不同的写法,第一种是使用
ssh://
开头的SSH协议标准URL写法,另外一种是SCP格式的写法。两种写法均可,SSH协议标准URL写法稍嫌复杂,但是对于非标准SSH端口(非22端口),可以通过URL给出端口号。
<username>是服务器<server>上的用户帐号。
如果省略用户名,则缺省使用当前登录用户名(配置和使用了服务器别名除外)。
<port>为SSH协议端口缺省为22。
端口只有在SSH协议标准URL写法可以给出,如果省略则使用缺省值22(配置和使用了服务器别名除外)。
/path/to/repos/myrepo.git
是服务器中版本库的绝对路径。若用相对路径则相对于username用户的主目录而言。如果采用口令认证,不能像HTTPS协议那样可以在URL中同时给出登录名和口令,必须每次连接时输入。
如果采用公钥认证,则无须输入口令。
5.3.2. 服务架设方式比较
SSH协议来实现Git服务,有如下方式:
其一是用标准的ssh帐号访问版本库。即用户帐号可以直接登录到服务器,获得shell。
对于这种使用标准SSH帐号方式,直接使用标准的SSH服务就可以了,无须赘述。
另外的方式是,所有用户都使用同一个专用的SSH帐号访问版本库。各个用户通过公钥认证的方式用此专用SSH帐号访问版本库。而用户在连接时使用的不同的公钥可以用于区分不同的用户身份。
Gitosis和Gitolite就是实现该方式的两个服务器软件。
标准SSH帐号和专用SSH帐号的区别见表29-1。
表29-1:不同SSH服务架设Git的对照
标准SSH Gitosis/Gitolite 帐号 每个用户一个帐号 所有用户共用同一个帐号 认证方式 口令或公钥认证 公钥认证 用户是否能直接登录shell 是 否 安全性 差 好 管理员是否需要shell 是 否 版本库路径 相对路径或绝对路径 相对路径 授权方式 操作系统中用户组和目录权限 通过配置文件授权 对分支进行写授权 否 Gitolite 对路径进行写授权 否 Gitolite 架设难易度 简单 复杂
实际上,标准SSH,也可以用公钥认证的方式实现所有用户共用同一个帐号。不过这类似于把一个公共帐号的登录口令同时告诉给多个人。
在服务器端(server)创建一个公共帐号,例如:anonymous。
管理员收集需要访问git服务的用户公钥。如:
user1.pub
、user2.pub
。使用ssh-copy-id命令远程将各个git用户的公钥加入服务器(server)的公钥认证列表中。
$ ssh-copy-id -i user1.pub anonymous@server $ ssh-copy-id -i user2.pub anonymous@server
如果直接在服务器上操作,则直接将文件追加到
authorized_keys
文件中。$ cat /path/to/user1.pub >> ~anonymous/.ssh/authorized_keys $ cat /path/to/user2.pub >> ~anonymous/.ssh/authorized_keys
在服务器端的
anonymous
用户主目录下建立git库,就可以实现多个用户利用同一个系统帐号(git)访问Git服务了。
这样做除了免除了逐一设置帐号,以及用户无需口令认证之外,标准SSH部署Git服务的缺点一个也不少,而且因为用户之间无法区分,更无法进行针对用户授权。
下面重点介绍一下SSH公钥认证,因为它们是后面介绍的Gitosis和Gitolite服务器软件的基础。
5.3.3. 关于SSH公钥认证
关于公钥认证的原理,维基百科上的这个条目是一个很好的起点:http://en.wikipedia.org/wiki/Public-key_cryptography。
如果用户的主目录下不存在.ssh
目录,说明SSH公钥/私钥对尚未创建。可以用这个命令创建:
$ ssh-keygen
该命令会在用户主目录下创建.ssh
目录,并在其中创建两个文件:
id_rsa
私钥文件。是基于RSA算法创建。该私钥文件要妥善保管,不要泄漏。
id_rsa.pub
公钥文件。和
id_rsa
文件是一对儿,该文件作为公钥文件,可以公开。
创建了自己的公钥/私钥对后,就可以使用下面的命令,实现无口令登录远程服务器,即用公钥认证取代口令认证。
$ ssh-copy-id -i .ssh/id_rsa.pub <user>@<server>
说明:
- 该命令会提示输入用户user在server上的SSH登录口令。
- 当此命令执行成功后,再以user用户登录server远程主机时,不必输入口令直接登录。
- 该命令实际上将
.ssh/id_rsa.pub
公钥文件追加到远程主机server的user主目录下的.ssh/authorized_keys
文件中。
检查公钥认证是否生效,运行SSH到远程主机,正常的话应该直接登录成功。如果要求输入口令则表明公钥认证配置存在问题。如果SSH登录存在问题,可以通过查看服务器端的/var/log/auth.log
日志文件进行诊断。
5.3.4. 关于SSH主机别名
在实际应用中,有时需要使用多套公钥/私钥对,例如:
- 使用默认的公钥访问git帐号,获取shell,进行管理员维护工作。
- 使用单独创建的公钥访问git帐号,执行git命令。
- 访问GitHub(免费的Git服务托管商)采用其他公钥。
首先要能够创建不同名称的公钥/私钥对。还是用ssh-keygen命令,如下:
$ ssh-keygen -f ~/.ssh/<filename>
注:
- 将
<filename>
替换为有意义的名称。 - 会在
~/.ssh
目录下创建指定的公钥/私钥对。 文件<filename>
是私钥,文件<filename>.pub
是公钥。
将新生成的公钥添加到远程主机的.ssh/authorized_keys
文件中,建立新的公钥认证。例如:
$ ssh-copy-id -i .ssh/<filename>.pub <user>@<server>
这样,就有两个公钥用于登录主机server,那么当执行下面的ssh登录指令,用到的是那个公钥呢?
$ ssh <user>@<server>
当然是默认公钥~/.ssh/id_rsa.pub
。那么如何用新建的公钥连接server呢?
SSH的客户端配置文件~/.ssh/config
可以通过创建主机别名,在连接主机时,使用特定的公钥。例如~/.ssh/config
文件中的下列配置:
host bj user git hostname bj.ossxp.com port 22 identityfile ~/.ssh/jiangxin
当执行
$ ssh bj
或者执行
$ git clone bj:path/to/repos/myrepo.git
含义为:
- 登录的SSH主机为
bj.ossxp.com
。 - 登录时使用的用户名为git。
- 认证时使用的公钥文件为
~/.ssh/jiangxin.pub
。