SSH 協議用於為 Git 提供遠端讀寫操作,是遠端寫操作的標準服務。
SSH協議語法格式
對於擁有 shell 登入許可權的使用者賬號,可以用下面的語法訪問 Git 版本庫:
語法 1 : ssh://[<username>@]<server>[:<port>]/home/xxx/repo1.git
語法 2 : [<username>@]<server>:/home/xxx/repo1.git
注意 :
SSH 協議地址格式可以使用兩種不同的寫法,第一種是使用 ssh:// 開頭的標準的 SSH 協議 URL 寫法,第二種是 SCP 格式的寫法。SSH 協議標準的 URL 寫法稍嫌複雜,但是對於非標準 SSH 埠(非 22)可以直接在 URL 中給出埠號。
<username> 是伺服器 <server> 上的使用者賬號,如果省略使用者名稱,則會使用當前登入使用者的使用者名稱(配置和使用了主機別名的除外)。
<port> 為SSH 協議埠,預設為 22。當使用了非預設埠時,最好使用語法1。當然使用語法2也可以實現,但是要通過 ~/.ssh/config 配置檔案設定主機別名。
路徑 /home/xxx/repo1.git 是伺服器中版本庫的絕對路徑。若用相對路徑則是相對於 username 使用者的家目錄。
如果採用口令 認證,必須在每次連線時輸入口令。
如果採用公鑰認證,則不用輸入口令。
伺服器架設方式比較
SSH 協議有兩種方式來實現 Git 服務。第一種是用標準的 SSH 賬號訪問版本庫。即使用者賬號可以直接登入到伺服器獲得 shell。對於這種使用標準 SSH 賬號的方式,直接使用標準的 SSH 服務就可以了。
第二種實現方式是所有使用者都使用同一個專用的 SSH 賬號訪問版本庫,訪問時通過公鑰認證的方式。雖然所有使用者用同一個賬號訪問,但可以通過在建立連線時所用的不同公鑰來區分不同的使用者身份。Gitolite 就是實現該方式的伺服器軟體。
標準 SSH 賬號和專用 SSH 賬號這兩種實現方式的區別:
標準 SSH | Gitolite | |
賬號 | 每個使用者一個賬號 | 所有使用者公用同一個賬號 |
認證方式 | 口令或公鑰認證 | 公鑰認證 |
登入到 shell | 是 | 否 |
安全性 | 差 | 好 |
管理員需要 shell | 是 | 否 |
版本庫路徑 | 相對路徑或絕對路徑 | 相對路徑 |
授權方式 | 作業系統中使用者組和目錄許可權 | 通過配置檔案授權 |
分支寫授權 | 否 | Gitolite |
路徑寫授權 | 否 | Gitolite |
假設難易度 | 簡單 | 複雜 |
實際上,標準 SSH 也可以用公鑰認證的方式實現使用使用者公用同一個賬號,不過這類似於把一個公共賬號的登入口令同時告訴給多個人。具體操作如下:
1. 在伺服器端建立一個公共賬號,例如 sparker。
2. 管理員收集需要訪問git服務的使用者公鑰。如 user1.pub,user2.pub。
3. 使用 ssh-copy-id 命令將各個 git 使用者的公鑰遠端加入伺服器的公鑰認證列表中。
3.1. 遠端操作,可以使用 ssh-copy-id 命令。
$ ssh-copy-id -i user1.pub sparker@server
$ ssh-copy-id -i user2.pub sparker@server
3.2. 如果直接在伺服器上操作,則直接將檔案追加到 authorized_keys檔案中。
$ cat user1.pub >> ~sparker/.ssh/authorized_keys
$ cat user2.pub >> ~sparker/.ssh/authorized_keys
4. 在伺服器端的 sparker 使用者主目錄下建立 git 庫,就可以實現多個使用者利用同一個系統賬號(sparker)訪問 git 服務了。
這樣做除了不必逐一設定賬號,以及使用者無須口令認證之外,標準 SSH 部署 git 服務的缺點一個也不少,而且因為無法區分使用者,也就無法針對使用者進行授權。
SSH公鑰認證
為實現公鑰認證,作為認證的客戶端一方需要擁有兩個檔案,即公鑰/私鑰對。一般情況下,公鑰/私鑰對檔案建立在使用者家目錄下的 .ssh 目錄中。如果使用者家目錄中不存在 .ssh 目錄,說明 SSH 公鑰/私鑰對尚未建立。可以用下面的命令建立:
$ ssh-keygen
該命令會在使用者家目錄下建立 .ssh 目錄,並在其中建立兩個檔案:
1. id_rsa
私鑰檔案,它是基於 RSA 演算法建立的,一定要妥善保管不要洩露。
2. id_rsa.pub
公鑰檔案,和 id_rsa 檔案是一對兒,該檔案作為公鑰檔案可以公開。
建立了自己的公鑰/私鑰對以後,就可以使用下面的命令,實現無口令登入遠端伺服器 (即用公鑰認證取代口令認證)。
$ ssh-copy-id -i .ssh/id_rsa.pub <user>@<server>
注意:
該命令會提示使用者輸入 user 在 server 上的 SSH 登入口令。
此命令執行成功後,再以 user 使用者用 ssh 命令登入 server 遠端主機時,不必輸入口令即可直接登入。
該命令實際上是將 .ssh/id_rsa.pub 公鑰檔案追加到遠端主機 serve r的 user 家目錄下的 .ssh/authorized_keys 檔案中。
檢查公鑰認證是否生效,通過 ssh 命令連線遠端主機,正常的話應該直接登入成功。如果要求輸入口令則表明公鑰認證配置存在問題。如果 SSH 登入存在問題,可以通過檢視伺服器端的 /var/log/auth.log 檔案進行診斷。
SSH主機別名
在實際使用中,有時需要使用多套公鑰/私鑰對,例如:
1. 使用預設的公鑰訪問伺服器的 git 賬號,可以執行 git 命令,但不能進行 shell 登入。
2. 使用特別建立的公鑰訪問伺服器的 git 賬號,能夠獲取 shell,登入後可以對 Git 伺服器軟體進行升級、維護等操作。
3. 訪問 Github 使用其他公鑰(非預設公鑰)。
從上面的說明可以看出,使用者可能擁有不止一套公鑰/私鑰對。為了建立不同的公鑰/私鑰對,在使用 ssh-keygen 命令時就需要通過-f引數指定不同的私鑰名稱。具體用法如下:
$ ssh-keygen -f ~/.ssh/<filename>
請將 <filename> 替換為有意義的名稱。命令執行完畢後,會在 ~/.ssh 目錄下建立指定的公鑰/私鑰對:檔案 <filename> 是私鑰,檔案 <filename>.pub 是公鑰。
將新生成的公鑰新增到遠端主機登入使用者家目錄下的 .ssh/authorized_keys 檔案中,就可以使用新建立的公鑰建立到遠端主機 <server> 的 <user> 賬戶的無口令登入。操作如下:
$ ssh-copy-id -i .ssh/<filename>.pub <user>@<server>
現在使用者存在多個公鑰/私鑰對,那麼當執行下面的 ssh 登入命令時,用到的是哪個公鑰呢?
$ ssh <user>@<server>
當然是預設公鑰 ~/.ssh/id_rsa.pub。那麼如何用新建的公鑰連線 server 呢?
SSH 的客戶端配置檔案 ~/.ssh/config可以通過建立主機別名,在連線主機時選擇使用特定的公鑰。例如 ~/.ssh/config 檔案中的下列配置:
host abc
user git
hostname abc.xxx.com
port 22
Identityfile ~/.ssh/abc
注意,hostname 也可以寫成 IP。
然後執行下面的 SSH 登入命令:
$ ssh abc
或者執行 git 命令:
$ git clone abc:/home/abc/repo1.git
雖然這兩條命令各不相同,但是都使用了 SSH 協議,以及相同的主機別名:abc。參考上面在 ~/.ssh/config 檔案中建立的主機別名,可以做出如下判斷:
1. 登入的SSH主機名為 abc.xxx.com。
2. 登入時使用的使用者名稱為 git。
3. 認證時使用的公鑰檔案為 ~/.ssh/abc.pub。