--------------------------------------------------------------------html
本文參考多篇文章結合自身狀況完成,可自由轉載,需保留本文出處!ios
博主:疲憊的豆豆git
http://www.cnblogs.com/dzblog/p/6930147.htmlgithub
--------------------------------------------------------------------算法
看完後須要明白的如下幾個概念:shell
know_host : 存儲 已經確保正常、能夠安全鏈接的全部服務器(hosts)的公鑰。ubuntu
authorized_hosts : 存儲 已經認證的客戶端的公鑰。vim
public key :公鑰segmentfault
private key :私鑰安全
使用ssh和https有什麼不一樣:
HTTPS:使用https url克隆對初學者來講會比較方便,複製https url而後到git Bash裏面直接用clone命令克隆到本地就行了,可是每次fetch和push代碼都須要輸入帳號和密碼,這也是https方式的麻煩之處(發現了https免密登陸的方式)。
SSH:使用SSH url克隆卻須要在克隆以前先配置和添加好SSH key,所以,若是你想要使用SSH url克隆的話,你必須是這個項目的擁有者或管理員,不然你是沒法添加SSH key的。另外ssh默認是每次fetch和push代碼都不須要輸入帳號和密碼,若是你想要每次都輸入帳號密碼才能進行fetch和push也能夠另外進行設置
生成SSH Key的基本命令:
#步驟1: cd ~/.ssh ls #這兩個命令就是檢查是否已經存在id_rsa.pub或id_dsa.pub文件,若是文件已經存在,那麼你能夠跳過步驟2 #步驟2:建立一個SSH Key ssh-keygen -t rsa -C "你的email地址" #代碼參數含義: #-t指定密鑰類型,默認是rsa,能夠省略。 #-C設置註釋文字,好比郵箱。 #-f指定密鑰文件存儲文件名。
SSH是一種網絡協議,用於計算機之間的加密登陸。若是一個用戶從本地計算機,使用SSH協議登陸另外一臺遠程計算機,咱們就能夠認爲,這種登陸是安全的,即便被中途截獲,密碼也不會泄露。
最先的時候,互聯網通訊都是明文通訊,一旦被截獲,內容就暴露無疑。1995年,芬蘭學者Tatu Ylonen設計了SSH協議,將登陸信息所有加密,成爲互聯網安全的一個基本解決方案,迅速在全世界得到推廣,目前已經成爲Linux系統的標準配置。
SSH僅僅是一協議標準,其具體的實現有不少,既有開源實現的OpenSSH,也有商業實現方案。使用範圍最普遍的固然是開源實現OpenSSH。
本文只討論SSH在Linux Shell中的用法。若是要在Windows系統中使用SSH,請使用PuTTY。
SSH主要用於遠程登陸。假定你要以用戶名user,登陸遠程主機host,只要一條簡單命令就能夠了。
$ ssh user@host
若是本地用戶名與遠程用戶名一致,登陸時能夠省略用戶名。
$ ssh host
SSH的默認端口是22,也就是說,你的登陸請求會送進遠程主機的22端口。使用p參數,能夠修改這個端口,好比改爲8888。
$ ssh -p 8888 user@host
上面這條命令表示,ssh直接鏈接遠程主機的8888端口。
既然說ssh是互聯網安全的一個基本解決方案,那若是保證數據安全?
首先想到的實現方案確定是對數據進行加密。加密的方式主要有兩種:
所謂對稱加密,指加密解密使用同一套祕鑰。以下圖所示:
對稱加密-Client端
對稱加密-Server端
對稱加密的加密強度高,很難破解。
可是在實際應用過程當中不得不面臨一個棘手的問題:如何安全的保存密鑰呢?尤爲是考慮到數量龐大的Client端,很難保證密鑰不被泄露。一旦一個Client端的密鑰被竊據,那麼整個系統的安全性也就不復存在。爲了解決這個問題,非對稱加密應運而生。非對稱加密有兩個密鑰:"公鑰"和"私鑰"。
特性:
公鑰加密後的密文,只能經過其對應的私鑰進行解密。
經過公鑰推理出私鑰的可能性微乎其微。
以用戶TopGun爲例,以下(圖三):
登陸流程:
遠程Server收到Client端用戶TopGun的登陸請求,Server把本身的公鑰發給用戶。
Client使用這個公鑰,將密碼進行加密。
Client將加密的密碼發送給Server端。
遠程Server用本身的私鑰,解密登陸密碼,而後驗證其合法性。
若驗證結果,給Client相應的響應。
私鑰是Server端獨有的,這就保證了Client的登陸信息即便在網絡傳輸過程當中被竊據,也沒有私鑰進行解密,保證了數據的安全性,這充分利用了非對稱加密的特性。
這就必定安全了嗎?
SSH之因此可以保證安全,緣由在於它採用了公鑰加密。
整個過程如上圖所示:
(1)遠程主機收到用戶的登陸請求,把本身的公鑰發給用戶。
(2)用戶使用這個公鑰,將登陸密碼加密後,發送回來。
(3)遠程主機用本身的私鑰,解密登陸密碼,若是密碼正確,就贊成用戶登陸。
這個過程自己是安全的,可是實施的時候存在一個風險:
Client端如何保證接受到的公鑰就是目標Server端的?,若是一個攻擊者中途攔截Client的登陸請求,向其發送本身的公鑰,Client端用攻擊者的公鑰進行數據加密。攻擊者接收到加密信息後再用本身的私鑰進行解密,不就竊取了Client的登陸信息了嗎?
若是有人截獲了登陸請求,而後冒充遠程主機,將僞造的公鑰發給用戶,那麼用戶很難辨別真僞。由於不像https協議,SSH協議的公鑰是沒有證書中心(CA)公證的,也就是說,都是本身簽發的。能夠設想具體場景,若是攻擊者插在用戶與遠程主機之間(好比在公共的wifi區域),用僞造的公鑰,獲取用戶的登陸密碼。再用這個密碼登陸遠程主機,那麼SSH的安全機制就蕩然無存了。這種風險就是著名的"中間人攻擊"(Man-in-the-middle attack)。
以用戶TopGun爲例,如圖四:
那SSH協議是如何應對的呢?
從上面的描述能夠看出,問題就在於如何對Server的公鑰進行認證?在https中能夠經過CA來進行公證,但是SSH的publish key和private key都是本身生成的,無法公證。只能經過Client端本身對公鑰進行確認。
一般在第一次登陸的時候,系統會出現下面提示信息:
$ ssh user@host The authenticity of host 'host (12.18.429.21)' can't be established. RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d. Are you sure you want to continue connecting (yes/no)?
上面的信息說的是:沒法確認主機host(12.18.429.21)的真實性,不過知道它的公鑰指紋,詢問你是否繼續鏈接?
所謂"公鑰指紋",是指公鑰長度較長(這裏採用RSA算法,長達1024位),很難比對,因此對其進行MD5計算,將它變成一個128位的指紋。上例中是98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d,再進行比較,就容易多了。
之因此用fingerprint代替key,主要是key過於長(RSA算法生成的公鑰有1024位),很難直接比較。因此,對公鑰進行hash生成一個128位的指紋,這樣就方便比較了。
很天然的一個問題就是,用戶怎麼知道遠程主機的公鑰指紋應該是多少?
回答是沒有好辦法,遠程主機必須在本身的網站上貼出公鑰指紋,以便用戶自行覈對,或者本身甄別host地址是否正確。
假定通過風險衡量之後(通常用戶直接就選擇yes吧),用戶決定接受這個遠程主機的公鑰。
Are you sure you want to continue connecting (yes/no)? yes
系統會出現一句提示,表示host主機已經獲得承認。
Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.
而後,會要求輸入密碼。
Password: (enter password)
若是密碼正確,就能夠登陸了。
當遠程主機的公鑰被接受之後,它就會被保存在文件$HOME/.ssh/known_hosts之中。下次再鏈接這臺主機,系統就會認出它的公鑰已經保存在本地了,從而跳過警告部分,直接提示輸入密碼。
每一個SSH用戶都有本身的known_hosts文件,此外系統也有一個這樣的文件,一般是/etc/ssh/ssh_known_hosts,保存一些對全部用戶均可信賴的遠程主機的公鑰。
我本地的known_hosts文件,能夠發現已經保存了五個我以爲放心的服務器(hosts)的公鑰
簡單說,當host已被確認,並被追加到文件known_hosts中,下次鏈接只須要輸入密碼便可,以後的流程就按照圖3進行。
|1|sgbtTTUJ/9xTRBchGIGXXt51J6M=|Bb5EzE/lSWWElJN12apF7fSxtSY= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBAQmeHZvdibukSrHVjiGvRRp121o9u6wggOnckia4LTv6AS/r3F05BogWJuPCyjEXT+U3neNYGtcqbSsXv/fO+U= |1|F4L6YTHVeEcS/E9eqk5xLOHKNr4=|SEILG9DHeT9FA9H/cjyvMzWSgew= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGZgdcSEtfhdP83mlq1WOUlByl5zT4Mxn2SrH/EydDTO32reFKwUgAVOnHC0qVXIpp1Cup//qi1BbItUguENAro= |1|pPkIGKq8X1aFVc3Yawr3L8waBes=|JOtrUbUxAAq20A/yKwHWKawirIk= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGZgdcSEtfhdP83mlq1WOUlByl5zT4Mxn2SrH/EydDTO32reFKwUgAVOnHC0qVXIpp1Cup//qi1BbItUguENAro= |1|QCS+wt47tTYBGwGT/xCqca38sTo=|IqOJYH8AS6hvBwKO8V5dwmfGQik= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBORUpIyKsByC4cmSytCVpSLrLcWgu5x/2Oy0eDpxI9qzvQf13p9/e74un+AsyspKhV8CVW0ES65YPy1cgGGp79Y= |1|/cf8UrQvOCilbSE6NBIPApJ+QDU=|sC0XF3Ug/QyCl770t0EsulwcXN8= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHEfk6MWAQM5uutCW+wUiTVcEkE5NUG4Tp6AFputB7dKlga1yOEA1mHs90gDN8Gg1u44mUEEDp/xPU6qnZ2Lv6A=
使用密碼登陸,每次都必須輸入密碼,很是麻煩。好在SSH提供了另一種能夠免去輸入密碼過程的登陸方式:公鑰登陸。
所謂"公鑰登陸",原理很簡單,就是用戶將本身的公鑰儲存在遠程主機上。
登陸的時候,遠程主機會向用戶發送一段隨機字符串,用戶用本身的私鑰加密後,再發回來。遠程主機用事先儲存的公鑰進行解密,若是成功,就證實用戶是可信的,直接容許登陸shell,再也不要求密碼。
以用戶TopGun爲例,流程以下:
公鑰認證流程:
1. Client端用戶TopGun將本身的公鑰存放在Server上,追加在文件authorized_keys中。
2. Server收到登陸請求後,隨機生成一個字符串str1,併發送給Client。
3. Client用本身的私鑰對字符串str1進行加密。
4. 將加密後字符串發送給Server。
5. Server用以前存儲的公鑰進行解密,比較解密後的str2和str1。
6. 根據比較結果,返回客戶端登錄結果。
在步驟1中,Client將本身的公鑰存放在Server上。須要用戶手動將公鑰copy到server上。這就是在配置ssh的時候進程進行的操做。下圖是GitLab上SSH keys設置視圖:
這種方法要求用戶必須提供本身的公鑰。若是沒有現成的,能夠直接用ssh-keygen生成一個:
$ ssh-keygen
運行上面的命令之後,系統會出現一系列提示,能夠一路回車。其中有一個問題是,要不要對私鑰設置口令(passphrase),若是擔憂私鑰的安全,這裏能夠設置一個。
運行結束之後,在$HOME/.ssh/目錄下,會新生成兩個文件:id_rsa.pub和id_rsa。前者是你的公鑰,後者是你的私鑰。
好比,我須要用用戶user登陸host服務器,只需再輸入下面的命令,將公鑰傳送到遠程主機host上面:
$ ssh-copy-id user@host
好了,今後你再登陸,就不須要輸入密碼了。
若是仍是不行,就打開遠程主機的/etc/ssh/sshd_config這個文件,檢查下面幾行前面"#"註釋是否取掉。
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
而後,重啓遠程主機的ssh服務。
// ubuntu系統
service ssh restart
// debian系統
/etc/init.d/ssh restart
遠程主機將用戶的公鑰,保存在登陸後的用戶主目錄的$HOME/.ssh/authorized_keys文件中。公鑰就是一段字符串,只要把它追加在authorized_keys文件的末尾就好了。
這裏不使用上面的ssh-copy-id命令,改用下面的命令,解釋公鑰的保存過程:
$ ssh user@host 'mkdir -p .ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub
這條命令由多個語句組成,依次分解開來看:(1)"$ ssh user@host",表示登陸遠程主機;(2)單引號中的mkdir .ssh && cat >> .ssh/authorized_keys,表示登陸後在遠程shell上執行的命令:(3)"$ mkdir -p .ssh"的做用是,若是用戶主目錄中的.ssh目錄不存在,就建立一個;(4)'cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub的做用是,將本地的公鑰文件~/.ssh/id_rsa.pub,重定向追加到遠程文件authorized_keys的末尾。
寫入authorized_keys文件後,公鑰登陸的設置就完成了。
我本地的ahtorized_keys文件。添加後內容以下:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDQsqm2aqI3MCUcDlcqnU9JfE30TYfUjayKGf/+WvLOpFVUqhwnrAFVT7VaCW5G5Lh3IlWzGCflhl0Yjasb3BTELV+W+zHpefgEwJaNB725yfzdPvk/aGrHv7UusggMqqR11JDW2zlISo/xUysEzJ4pTnjz6AcdKUCE8biB3s37yTSa8k78g2j06tzLglr+np179jCiq9RJfKCs/omeCHbU+pyhcCk6DoL/SRHzNczfHIcJBvhWvY7CPKHb2vqD9k5d9cS2renGvB2/fCkyyNdnVZgKc3r5ufJUD+yWJ6yMHNT/hMn0uybEHuVz8s/zXjdH3xgx40UrfLs8eNKTKpAN app@bjxg-ap-27-7 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCk7sNBV8ag8KKApN4mapTQTkDEbcA3VNFIhSuO+YLTbkO29KU6FSQhlT2It2hmmmdaVJXEMx6JmQS7+62DNHIpHnzaKimEU+tKosAdOwHoZPcskMw6QlvjkhicKg7+kNsFdeSuAtE3V4ShbFPUfRNAs/9a/b56/FqqGIk6oPVu19CSvMyLnnqTht9rMQdIw4uOynogEKivgdwsAFh4qayJSz8VwklN9dx+8dqw8e9e/CxXEDWuZ2T/DtEa+gIRy0bvJaDcgzcpvxMkf+71HTpYlvkziF1YPmPX60gcyCkRkLnmM1fSkHXhAmBxZuSLc3l1VKXXWkH9rsgvxLzKuML/ app@bjxg-ap-28-7
生成密鑰操做
1. 打開ssh目錄,通常是隱藏的 cd ~/.ssh
2. 生成密鑰文件,這樣就會生成默認名字爲id_rsa和id_rsa.pub
ssh-keygen -t rsa -C "YOUR_EMAIL@YOUREMAIL.COM" (說明:YOUR_EMAIL@YOUREMAIL.COM換成你本身的郵箱)
3. 打開公鑰文件(id_rsa.pub),並把內容複製至代碼託管平臺上 或者 須要訪問的服務器(host)上的authorized_keys裏。
vim ~/.ssh/id_rsa.pub
進入 GitLab-->帳戶設置-->Profile Settings --> SSH Keys,點擊Add keys 按鈕,在 Title 文本框中輸入任意字符,在 Key 文本框粘貼剛纔複製的公鑰字符串,按保存按鈕完成操做。
cd ~/.ssh/ vim authorized_keys
4. 測試
ssh -T git@gitlab.com #或者 ssh -T user@host
成功應該提示:
delon@macpro:~/.ssh$ ssh -T git@git.hostname.com
Welcome to GitLab, CIRobot!
這樣就能夠只用ssh協議的URL了,通常默認是https協議的,如圖點擊SSH便可切換:
這樣push代碼時就不用再輸密碼了。
ssh-keygen是用於生產密鑰的工具。
id_rsa:保存私鑰
id_rsa.pub:保存公鑰
authorized_keys:保存已受權的客戶端公鑰
known_hosts:保存已認證的遠程主機公鑰
關係圖:
須要注意的是:一臺主機可能既是Client,也是Server。因此會同時擁有authorized_keys和known_hosts。
這部分Git熟悉的基本能夠略過:有些童鞋可能在設置這個多帳號前已經配置了一個Github/GitLab的ssh,而後把代碼clone下來,配置多帳號後,原來的代碼就提交不上了。
此時你進入 原來clone的代碼文件夾下,執行 git remote -v,便可看到遠處資源庫路徑
如:git@github.com:test/xxxxxx.git
執行git remote remove origin刪除該遠程路徑
執行git remote add origin git@test.github.com:test/xxxxxx.git加上正確的遠程倉庫。
GitLab的話
執行git remote add origin http://git.host.com/ios/項目名.git
https://segmentfault.com/a/1190000002627706
http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html
http://www.jianshu.com/p/33461b619d53