ssh那些事兒(1)—基本原理

web開發系列-ssh那些事兒1


        工作了快一年了,大部分時間在熟悉業務,也斷斷續續的學習了些web相關內容,現在打算抽出點時間來整理下學習筆記,同時也對一些自己不夠清楚的知識點做個梳理吧。這個系列我打算把web相關的東東儘可能的都總結一遍,當然還有很多地方自己也還不清楚,請大家指正。

        關於ssh的基本原理,阮一峯老師在他的博文中《SSH基本原理和應用》已經介紹的比較清楚了,爲了完整性,我也寫下自己的一些理解吧。ssh是一種計算機之間的加密登陸的協議,存在很多實現,目前用得比較多的免費的ssh實現是openssh,很多linux發行版一般都自帶安裝了。基本的用法就是大家熟悉的命令行 $ssh user@host,當然如果不是默認端口22,還要加參數-p port,如端口是12345,那麼登陸命令就是ssh -p12345 user@host。ssh登陸驗證有2種方式,密碼認證和公鑰認證,在公司服務器上用的的基本是密鑰登陸,這樣更加安全。

          

1、密碼認證

          密碼認證的過程是這樣的,(1)用戶輸入ssh命令發送登陸請求 (2)遠程主機收到用戶登陸請求後,把自己的公鑰發給用戶。(3)用戶使用這個公鑰將自己的登陸密碼加密後發送給遠程主機。(4)遠程主機用自己的私鑰解密,得到登陸密碼,如果密碼驗證正確,則允許用戶登陸,並將該遠程主機的公鑰保存在$HOME/.ssh/known_hosts中。但是這個過程容易受到中間人攻擊,所以用戶在輸入自己密碼前必須要覈對遠程主機的密鑰是否正確(一般在首次登陸時,遠程主機會將自己的公鑰生成指紋讓用戶確認,如果公鑰指紋與遠程主機公佈的不一致,就有問題了。注意一點,我們覈對的是公鑰的指紋,因爲公鑰太長,很難一個個覈對,而md5之類的哈希之後長度相對短一些,方便覈對。但是實際存儲在known_hosts中的是公鑰本身)。具體細節請見參考資料1。

         

2、公鑰認證

         密鑰認證則會安全一些,登陸期間不會涉及到登陸密碼在網絡上傳遞,不過過程也相對複雜一些。主要分爲以下幾個步驟:

(1)首先你需要自己生成一對公私鑰,然後將公鑰如id_rsa.pub加入到遠程主機目錄$HOME/.ssh/authorized_keys文件中。目前用得比較多的是rsa加密算法生成密鑰,rsa是一種非對稱加密方法,比較安全。rsa加密算法原理,我會在另外一篇博客中說明,暫且不管。生成密鑰的過程中會提示你輸入加密密碼,最好輸入密碼,不然你的私鑰萬一泄露了,那就不安全了。創建密鑰的命令爲ssh-keygen,具體參數含義參見http://lamp.linux.gov.cn/OpenSSH/ssh-keygen.html。

(2)接下來,就是驗證過程了。用戶輸入ssh登陸命令,這是ssh客戶端提示用戶輸入創建密鑰的時候設置的密碼(Passphrase)來解密私鑰。(如果在使用ssh-keygen生成密鑰時指定了Passphrase加密私鑰,需要解密,加密私鑰的算法是對稱加密算法DES)。

(3)ssh客戶端向遠程主機發送私鑰簽名的包含username,公鑰等信息的消息(簽名用到的參數除了username,公鑰,還有公鑰加密算法名,消息標識等)。

(4)遠程主機的ssh進程檢查消息中指定用戶的$HOME/.ssh/authorized_keys,確定公鑰是否可以用作驗證(也就是確認從用戶客戶機的消息中傳過來的公鑰是否在authorized_keys文件中存在),如果公鑰合法,則接下來使用公鑰解密該消息,驗證消息合法性。

        更詳細的過程請參見公鑰認證過程

        如果公鑰驗證失敗,則ssh會嘗試其他認證策略,如密碼認證等,這個由ssh客戶端配置而定。需要注意的是,在認證過程中,用戶的本地機器上並不再需要公鑰,你即使刪掉本機上的id_rsa.pub文件同樣可以認證成功,這是因爲這裏所謂的公私鑰其實是個廣義的詞,在私鑰中其實是即包含了私鑰,也包含了公鑰,當然還可能包含其他信息。你可以通過ssh-keygen -y ~/.ssh/id_rsa命令來得到公鑰。所以,公鑰驗證中得第3步中的公鑰就是從這裏得到的。具體公鑰和私鑰的組織格式以及具體存儲的內容,都將在下次博客說明rsa算法的時候一併分析。


3、ssh agent

        公鑰認證是比較安全了,但是每次都要輸入密碼,比較麻煩。通過ssh agent可以解決這個問題。我們可以使用ssh-add .ssh/id_rsa命令將私鑰加入到ssh-agent中由ssh agent來管理。當然在加入的時候,系統會提示你輸入密碼來解鎖私鑰。ssh-agent可以同時管理多個私鑰,加入私鑰到agent中後,連接遠程服務器的步驟如下:

(1)ssh 客戶端向遠端服務器發起登陸請求。

(2)ssh客戶端會先向本地的ssh agent請求,得到私鑰簽名的包含username和公鑰等信息的消息。

(3)ssh客戶端向遠端服務器發送該消息(包含username,公鑰以及簽名等信息)。

(4)遠端服務器的ssh進程檢查消息驗證公鑰是否可以用於驗證以及簽名的正確性,如果驗證通過,則同意登陸。

        可以看到,使用ssh-agent過程中,整個過程ssh客戶端是沒有得到私鑰的,私鑰只是存在於ssh-agent中。將私鑰加入到ssh-agent之後,後續的登陸就不再需要我們輸入密碼來解鎖私鑰了,方便了登陸過程。

        但是,還有個問題比較麻煩的就是,比如我們登陸了遠端服務器A,但是我們又想從A登陸到遠端服務器B,就不行了。當然最簡單的做法是將私鑰拷貝一份到A上面,這樣就可以從A直接登陸到B 了。但是在實際開發中,這樣是萬萬不可的,因爲服務器是大家公用的,你若暴露了自己的私鑰,是會導致安全問題的,當然你會說我設了密碼,一時半會破解不了,但是不怕一萬就怕萬一,所以這就需要提到ssh另外一個特性ssh agent forwarding了。


4、使用ssh agent forwarding的公鑰認證

        很多時候,我們需要從本地機器登陸到遠端服務器A,然後又需要從A登陸到遠端服務器B,而我們在A上面是沒有放置自己的私鑰的,這時候就需要用到ssh agent forwarding了。ssh agent forwarding認證過程如下:

(1)假設用戶從本地機器登陸到了遠端服務器A,而本地機器的agent中保存了用戶私鑰。

(2)用戶從A向另一個遠端服務器B發起ssh登陸請求。

(3)服務器A的ssh客戶端向“A的ssh agent”發起請求,獲取私鑰簽名的包含username,公鑰等信息的消息。

        需要注意的是,服務器A上面的ssh agent根本就沒有啓動,服務器A的ssh客戶端只是檢查服務器A上面是否存在$SSH_AUTH_SOCK這個環境變量,如果存在則通過這個變量指定的domain socket通信,而這個domain socket實際上就是由A的sshd進程創建的,所以A的ssh客戶端實際上是與A的sshd進程通信。但是A的sshd並沒有私鑰信息,所以sshd所做的事情就是轉發該請求到用戶的本地機器的ssh客戶端,然後由本地機器的ssh客戶端將請求轉發給本地機器的ssh agent。本地機器的ssh agent將包含username,公鑰以及簽名信息的消息準備後,按照前面的路徑發送回A的ssh客戶端。

(4)服務器A向服務器B發送從用戶本地機器接收到的消息。

(5)服務器B的sshd進程檢查指定用戶$HOME/.ssh/authorized_keys文件,確定消息中的公鑰是否可用於驗證並驗證簽名的合法性。如果通過,則允許登陸。

        通過上述方法,可以實現任意級別的登陸,如從A登陸到B,B登陸到C等。由於私鑰只保存在本地機器上,這樣保證了私鑰的安全。agent forwarding功能默認是關閉的,所以在上面的步驟中要想成功,需要在登陸服務器A的時候加上-A 參數。命令類似ssh -A username@host

        需要注意一點的是,agent forwarding打開後,如上述過程中服務器A打開了agent forwarding,則服務器A上面的root用戶只要將$SSH_AUTH_SOCK指向用戶對應的套接字地址,則root用戶同樣可以以該用戶的身份登陸其他機器。因此需要確保agent forwarding只在可信的服務器上打開。


5、後續

        有時間會寫一篇ssh實戰的文章來說明下用法,對ssh操作不是很熟悉的朋友可以先參見這篇博客使用ssh agent forwarding操作下。

6、參考資料

1.SSH原理與應用:http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html

                                   http://www.ruanyifeng.com/blog/2011/12/ssh_port_forwarding.html

2.SSH Agent Forwarding原理: http://blog.pkufranky.com/2012/08/ssh-agent-forwarding-guide/

3.Openssh密鑰管理:https://www.ibm.com/developerworks/cn/linux/security/openssh/part1/  

                                        https://www.ibm.com/developerworks/cn/linux/security/openssh/part2/



發佈了121 篇原創文章 · 獲贊 133 · 訪問量 68萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章