https://blog.csdn.net/qwertyupoiuytr/article/details/71213463算法
SSH創建鏈接的過程主要分爲下面幾個階段:服務器
SSH協議版本協商階段。SSH目前包括SSH1和SSH2兩個大版本。
密鑰和算法協商階段,SSH支持多種加密算法,雙方根據本身和對端支持的算法進行協商,最終決定要使用的算法。
認證階段,服務器對客戶端進行身份驗證。
會話請求階段,完成認證後,客戶端會向服務器端發送會話請求。
交互會話階段,會話請求經過後,服務器端和客戶端進行信息的交互。
加密
1)SSH協議版本協商階段:.net
客戶端經過TCP三次握手與服務器的SSH端口創建TCP鏈接。
服務器經過創建好的鏈接向客戶端發送一個包含SSH版本信息的報文,格式爲「SSH-<SSH協議大版本號>.<SSH協議小版本號>-<軟件版本號>」,軟件版本號主要用於調試。
客戶端收到版本號信息後,若是服務器使用的協議版本號低於本身的,可是客戶端可以兼容這個低版本的SSH協議,則就使用這個版本進行通訊。不然,客戶端會使用本身的版本號。
客戶端將本身決定使用的版本號發給服務器,服務器判斷客戶端使用的版本號本身是否支持,從而決定是否可以繼續完成SSH鏈接。
若是協商成功,則進入密鑰和算法協商階段。
調試
2)密鑰和算法協商階段:blog
服務器端和客戶端分別發送算法協商報文給對端,報文中包含本身支持的公鑰算法列表,加密算法列表,MAC(Message Authentication Code,消息驗證碼)算法列表,壓縮算法列表等。
和版本協商階段相似,服務器端和客戶端根據本身和對端支持的算法來決定最終要使用的各個算法。
服務器端和客戶端利用Diffie-Hellman密鑰交換算法,主機密鑰對等參數,生成共享密鑰和會話ID。會話密鑰用於在後續的通訊過程當中兩端對傳輸的數據進行加密和解密,而會話ID用於認證過程。
字符串
3)認證階段:get
客戶端向服務器端發送認證請求,請求中包含用戶名,認證方法,密碼或密鑰。
服務器端對客戶端進行認證,若是認證失敗,則向客戶端發送失敗消息,其中包含能夠再次認證的方法列表。
客戶端再次使用支持的認證方法中的一種進行認證,直到達到認證次數上限被服務器終止鏈接,或者認證成功爲止。
SSH支持的兩種認證方式:string
密碼認證:客戶端經過用戶名/密碼進行認證,將使用會話密鑰加密後的用戶名和密碼發送給服務器,服務器解密後與系統保存的用戶名和密碼進行對比,並向客戶端返回認證成功或失敗的消息。
密鑰認證:採用數字簽名來進行認證,目前能夠經過RSA和DSA兩種算法實現數字簽名,客戶端經過用戶名,公鑰以及公鑰算法等信息來與服務器完成驗證。
hash
4)會話請求階段:
服務器等待客戶端請求。
認證完成後,客戶端想服務器發送會話請求。
服務器處理客戶端請求,完成後,會向客戶端回覆SSH_SMSG_SUCCESS報文,雙方進入交互會話階段。若是請求未被成功處理,則服務器返回SSH_SMSG_FAILURE報文,表示請求處理失敗或者不能識別客戶端請求。
5)交互會話階段:
客戶端將要執行的命令加密發送給服務器。
服務器收到後,解密命令,執行後將結果加密返回客戶端。
客戶端將返回結果解密後顯示到終端上。
下面咱們經過客戶端(172.31.100.107)抓包來簡單說明密鑰認證的過程:
報文1-3:能夠看到前三個包是客戶端與服務器端三次握手的過程
報文4:在創建鏈接後,服務器端將本身支持的SSH版本發送給客戶端
報文5:客戶端返回給服務器本身要使用的SSH版本,若是服務器端不支持這個版本,則到此就終止了SSH鏈接
報文6:客戶端將本身支持的公鑰算法列表,加密算法列表,MAC(MessageAuthentication Code,消息驗證碼)算法列表,壓縮算法列表等發送給服務器
報文7,8:服務器返回ACK報文
報文9:服務器將本身支持的公鑰算法列表,加密算法列表,MAC(MessageAuthentication Code,消息驗證碼)算法列表,壓縮算法列表等發送給客戶端
這裏在雙方協商的原則是以客戶端支持的協議爲主,客戶端支持的協議從左向右優先級依次遞減,從優先級高的協議開始匹配,若是客戶端支持的第一個協議,服務器也支持,則雙方就使用這個協議,若是服務器不支持,則在匹配第二個客戶端支持的協議,直到匹配到最後一個客戶端支持的協議,若是服務器都不支持,則雙方協商失敗。
報文10:客戶端開始與服務器進行通訊的共享密鑰的協商,因爲前面使用的是SSH2.0的協議,因此這裏使用的是Diffie-Hellman-Group-Exchange-SHA算法(關於DH-GEX-SHA算法的原理,能夠參考http://blog.csdn.net/lee244868149/article/details/51790397),在這個報文中,客戶端限制了密鑰交換參數Min,Numbers of Bits,Max
報文11:服務器端收到客戶端DH請求後,將用於生成公鑰的P和G發送給客戶端,P是一個大素數,知足客戶端在報文10中的限制,G是大於1的數,不須要特別大,一般取2或者5
報文12:客戶端收到P和G後,本身生成私鑰a,並根據私鑰a計算出本身的公鑰e,將e發送給服務器端
報文13:服務器收到客戶端發來的e後,根據e和服務器的私鑰b能夠計算出雙方的共享密鑰K,同時服務器經過私鑰b計算出客戶端計算K須要的參數f,將f發給客戶端
此外,KEY DH host key爲服務器的主機公鑰,一般爲RSA公鑰,KEY DH HSignature爲服務器用主機私鑰對計算出的哈希值H進行簽名的結果。
H的計算方法爲:H=hash(V_C||V_S||I_C||I_S||K_S||e||f||K)
其中的參數:
類型
值
說明
string
V_C
客戶端的初始報文(版本信息:SSH-2.0-xxx,不含結尾的CR和LF)
string
V_S
服務器的初始報文
string
I_C
客戶端 SSH_MSG_KEX_INIT的有效載荷(不含開頭的數據長度值)
string
I_S
服務器的同上
string
K_S
主機祕鑰(dh gex reply(33)過程服務器發送host key (RSA公鑰))
mpint
e
客戶端DH公鑰
mpint
f
服務器DH公鑰
mpint
K
共同DH計算結果
客戶端收到服務器發來的f後,根據f和本身的私鑰能夠計算出K,進而計算出H,同時客戶端會利用服務器發送過來的主機公鑰K_S來驗證服務器發送過來的H的簽名是否有效,若是有效,則客戶端在報文14中向服務器發送New Keys報文,表示雙方密鑰交換成功,計算出的H則做爲整個會話的會話ID。
爲了更直觀的理解,能夠參考下面的計算過程:
後面的數據報文都使用雙方協商的共享密鑰,因此在抓包結果中就看不到裏面的信息了,這裏說明一下後續密鑰認證的大體過程:
客戶端向服務器發送登錄要使用的IP地址和用戶名,服務器識別對應的客戶端公鑰(保存在authorized_keys中),找到該公鑰後,服務器經過公鑰加密一段隨機字符串,並使用共享密鑰加密後發送給客戶端。客戶端首先使用共享密鑰解密獲得使用本身的公鑰加密的字符串,再使用本身的私鑰解密獲得原始字符串,再經過共享密鑰加密後發送給服務器。服務器經過共享密鑰解密獲得字符串,與以前本身用公鑰加密的那個字符串進行對比,若是一致,則說明客戶端的私鑰與本身的公鑰對應,認證成功,不然認證失敗。