SSH 協議基本原理及 wireshark 抓包分析

1、SSH協議簡介

咱們常常會使用ssh username@hostIp命令登錄咱們的linux服務器,以下圖所示:html

咱們也明白這是使用了SSH協議進行登錄,但咱們想知道的是,爲何可使用SSH協議進行登錄,並且爲何使用SSH就是安全的,其背後的原理是什麼?下面咱們就一塊兒來探討下這幾個話題。linux

固然啦!若是如今你手頭上有相關公網可訪問的雲主機,那麼請你登錄你的雲主機,而後執行grep sshd.*Failed /var/log/secure命令看看,或許你會驚訝的發現有不少輸出日誌,你就會明白到底有多少人想嘗試登錄你的主機了。git

簡單地說,SSH協議是創建在不安全的網絡之上的進行遠程安全登錄的協議。它是一個協議族,其中有三個子協議,分別是:github

  • 一、傳輸層協議[SSH-TRANS]:提供服務器驗證、完整性和保密性功能,創建在傳統的TCP/IP協議之上。
  • 二、驗證協議[SSH-USERAUTH]:向服務器驗證客戶端用戶,有基於用戶名密碼和公鑰兩種驗證方式,創建在傳輸層協議[SSH-TRANS]之上。
  • 三、鏈接協議[SSH-CONNECT]:將加密隧道複用爲若干邏輯信道。它創建在驗證協議之上。

這裏不對SSH協議作更加詳細的介紹,咱們能夠自行百度一下。下面的寫做思路將先經過wireshire抓包分析SSH協議上述三個流程,最後將提出整個學習過程當中小編遇到的問題進行探討。算法

2、SSH協議握手過程分析

在接着下面的內容以前,這裏有幾個概念很是重要!安全

  • 一、會話密鑰 key:key是經過客戶端和服務器之間經過諸如D-H算法協商出來的。
  • 二、公鑰 pub key:pub key成爲服務器主機密鑰server_host_key,用於SSH-TRANS傳輸協議進行服務器驗證,說白了就是客戶端去驗證服務器用的

SSH協議握手過程大體流程以下圖所示:服務器

下面是小編經過wireshire工具抓的數據包,讓咱們分別一步步進行分析:網絡

  • 一、TCP三次握手創建鏈接

咱們都知道,TCP協議有個叫三次握手的過程,從上面圖中能夠看出序號(647-649)便是TCP鏈接創建過程。app

NO. 描述 seq Win ACK 解釋
647 第一次握手 0 8192 seq = 0表示客戶端當前的TCP包序列號
648 第二次握手 0 14600 1 seq = 0,表示服務器端當前的TCP包序列號
ack = 1(客戶端seq + 1),表示對客戶端第 seq = 0 的TCP包進行應答
649 第三次握手 1 65536 1 seq = 1,表示客戶端端當前的TCP包序列號
ack = 1(服務器seq + 1),表示對服務器端第 seq = 0 的TCP包進行應答
  • 二、SSH版本協議交換

上圖序號(647-649)便是SSH版本協議交換過程。ssh

NO. 描述 解釋
650 協議版本協商 服務器將本身的SSH協議版本發送到客戶端,格式爲:SSH-protoversion(版本號)-softwareversion(自定義) SP(空格一個,可選) comments(註釋,可選) CR(回車) LF(換行)
651 協議版本協商 客戶端將本身的SSH協議版本發送到服務器,格式爲:SSH-protoversion(版本號)-softwareversion(自定義) SP(空格一個,可選) comments(註釋,可選) CR(回車符) LF(換行符)

這一步其實沒什麼高大上的內容,就是發送一個格式爲SSH-protoversion-softwareversion SP comments CR LF的字節流而已。

  • 三、密鑰協商key

上圖序號(652-677)便是SSH版本協議交換過程。

密鑰協商過程從客戶端和服務器相互發出Key Exchange Init請求開始,主要是告訴對方本身支持的相關加密算法列表、MAC算法列表等。

最後協商成功以後,將會生成一個對稱加密會話密鑰key以及一個會話ID,在這裏要特別強調,這個是對稱加密密鑰key,不要和公鑰相混淆了,公鑰和密鑰在上面開頭已經着重強調二者的區別了,公鑰是給客戶端去驗證服務器用的。

在這一步中,公鑰會從服務器傳送到客戶端:

而會話密鑰是經過D-H算法計算出來的,不會在網絡上傳輸,其破解的難度取決於離散對數的破解難度,通常不會被破解的,有興趣的能夠自行了解該算法原理。

下面我將貼出Key Exchange Init發送的請求包數據分析

NO. 描述 解釋
1 kex_algorithms 密鑰交換算法,裏邊即包含咱們使用的D-H算法,用於生成會話密鑰
2 server_host_key_algorithms 服務器主機密鑰算法,能夠採用 ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,有公鑰和私鑰的說法,公鑰即咱們上面講到的pub key,對於公鑰私鑰的概念,能夠參見understanding public key private key concepts
3 encryption_algorithms_client_to_server 對稱加密算法,經常使用的有aes128-cbc,3des-cbc
4 mac_algorithms_client_to_server MAC算法,主要用於保證數據完整性
5 compression_algorithms_client_to_server 壓縮算法
  • 四、認證階段

上圖序號(678-680)便是SSH版本認證階段。

  • 一、基於帳號和口令的驗證方式

    客戶端將本身的用戶名 + 密碼用上面生成的會話密鑰key進行加密以後傳送到服務器端進行驗證,服務器端驗證經過,則響應成功,不然在進行有限次(推薦是20次)從新認證。至於服務器是怎麼驗證的,是否結合了會話ID小編也不清楚,網上衆說紛紜。
    注意,用戶名和密碼是採用上面密鑰協商階段生成的會話密鑰key進行加密的,包括後面的鏈接會話階段所傳送的數據都是,不要認爲是採用服務器的pub key加密的

  • 二、基於公鑰和私鑰的驗證方式

    這種方式也稱爲免密登錄。簡單地說,就是客戶端本身生成公鑰私鑰(一般採用ssh-keygen程序生成),而後將公鑰以某種方式(一般是手動添加)保存到服務器~/.ssh/authorized_keys文件中,之後服務器都會接受客戶端傳過來的通過會話密鑰加密過的公鑰,而後解密獲得公鑰以後和本地authorized_keys配置的公鑰是否相等,若是是,則容許登錄。

若是你配過github或者gitlab的公鑰,其實第二種方式認證方式很好理解,由於github它們也是採用SSH協議進行代碼克隆的,沒有配置公鑰好像是不容許克隆的。

3、相關問題

  • 一、密鑰協商階段安全嗎?有沒有中間人攻擊的狀況!

就個人理解,第一次老是不安全的。爲何呢?上面說到協商過程當中,服務器會將本身的公鑰server_host_key_algorithms發送給客戶端,可是客戶端沒法保證它拿到的公鑰就是目標服務器所發出來的,極可能有個中間人攔截了你的請求,而後中間人發了另一個公鑰給到你客戶端,這就不安全了!這也很好解釋了爲何咱們第一次登錄的時候,Shell終端老是會出現這個提示的緣由:

這也是將確認權留給客戶端本身去判斷的一種策略。相反,若是想要更加安全,那麼咱們能夠採用第二種認證方式進行登錄。因爲提示的是通過MD5以後的公鑰,那麼咱們怎麼判斷這個值是有效的呢?請看下面第3個疑問。

  • 二、傳輸協議協商出來的會話密鑰和會話ID到底有什麼做用?

會話密鑰:對稱加密算法的密鑰,用於對通訊數據進行加解密,會話ID有點像WEB中的Session,就是用來表示每個會話的,同時在認證階段也起判斷是否同一會話有效的做用。

  • 三、既然密碼驗證登錄,那麼客戶端第一次登錄的時候如何驗證服務器公鑰的正確性?

請你告訴小編吧!小編苦於找不到答案!

4、其餘

下面是相關資料文檔:

咱們可能會問了,既然有了SSH協議文檔,那麼假如咱們想要照着文檔寫一個實現出來,那麼應該怎麼去入手呢?其實SSH中的傳輸協議[SSH-TARNS]是基於TCP協議的,所以咱們能夠從建立一個最基本Java Socket套接字開始,逐步實現SSH的傳輸協議、認證協議以及鏈接協議。若是你對實現過程感興趣,能夠研究下ganymed-ssh2-build209.jar中的源碼,結合SSH協議RFC文檔,你就會發現,其實SSH協議中的協商和認證過程,其實都是經過Socket輸入流、輸出流的形式實現的。小編本身擼到協商階段果斷放棄,緣由是不懂得算法太多了!

相關文章
相關標籤/搜索