Linux SSH建立連接過程分析


https://blog.csdn.net/qwertyupoiuytr/article/details/71213463

 

SSH建立連接的過程主要分為下面幾個階段:

SSH協議版本協商階段。SSH目前包括SSH1和SSH2兩個大版本。
密鑰和算法協商階段,SSH支持多種加密算法,雙方根據自己和對端支持的算法進行協商,最終決定要使用的算法。
認證階段,服務器對客戶端進行身份驗證。
會話請求階段,完成認證后,客戶端會向服務器端發送會話請求。
交互會話階段,會話請求通過后,服務器端和客戶端進行信息的交互。
 

1)SSH協議版本協商階段:

客戶端通過TCP三次握手與服務器的SSH端口建立TCP連接。
服務器通過建立好的連接向客戶端發送一個包含SSH版本信息的報文,格式為“SSH-<SSH協議大版本號>.<SSH協議小版本號>-<軟件版本號>”,軟件版本號主要用於調試。
客戶端收到版本號信息后,如果服務器使用的協議版本號低於自己的,但是客戶端能夠兼容這個低版本的SSH協議,則就使用這個版本進行通信。否則,客戶端會使用自己的版本號。
客戶端將自己決定使用的版本號發給服務器,服務器判斷客戶端使用的版本號自己是否支持,從而決定是否能夠繼續完成SSH連接。
如果協商成功,則進入密鑰和算法協商階段。
 

2)密鑰和算法協商階段:

服務器端和客戶端分別發送算法協商報文給對端,報文中包含自己支持的公鑰算法列表,加密算法列表,MAC(Message Authentication Code,消息驗證碼)算法列表,壓縮算法列表等。
和版本協商階段類似,服務器端和客戶端根據自己和對端支持的算法來決定最終要使用的各個算法。
服務器端和客戶端利用Diffie-Hellman密鑰交換算法,主機密鑰對等參數,生成共享密鑰和會話ID。會話密鑰用於在后續的通信過程中兩端對傳輸的數據進行加密和解密,而會話ID用於認證過程。
 

3)認證階段:

客戶端向服務器端發送認證請求,請求中包含用戶名,認證方法,密碼或密鑰。
服務器端對客戶端進行認證,如果認證失敗,則向客戶端發送失敗消息,其中包含可以再次認證的方法列表。
客戶端再次使用支持的認證方法中的一種進行認證,直到達到認證次數上限被服務器終止連接,或者認證成功為止。
SSH支持的兩種認證方式:

密碼認證:客戶端通過用戶名/密碼進行認證,將使用會話密鑰加密后的用戶名和密碼發送給服務器,服務器解密后與系統保存的用戶名和密碼進行對比,並向客戶端返回認證成功或失敗的消息。
密鑰認證:采用數字簽名來進行認證,目前可以通過RSA和DSA兩種算法實現數字簽名,客戶端通過用戶名,公鑰以及公鑰算法等信息來與服務器完成驗證。
 

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中),找到該公鑰后,服務器通過公鑰加密一段隨機字符串,並使用共享密鑰加密后發送給客戶端。
客戶端首先使用共享密鑰解密得到使用自己的公鑰加密的字符串,再使用自己的私鑰解密得到原始字符串,再通過共享密鑰加密后發送給服務器。
服務器通過共享密鑰解密得到字符串,與之前自己用公鑰加密的那個字符串進行對比,如果一致,則說明客戶端的私鑰與自己的公鑰對應,認證成功,否則認證失敗。

---------------------
作者:遠行的風
來源:CSDN
原文:https://blog.csdn.net/qwertyupoiuytr/article/details/71213463
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM