'圖解 SSH 原理'

OpenSSH Linux 算法 設計 通信 寧壹科技工作室 2019-07-29
"


"


圖解 SSH 原理


1. 初見 SSH


SSH是一種協議標準,用於在網絡主機之間進行加密的一種協議,其目的是實現安全遠程登錄以及其它安全網絡服務

SSH 僅僅是一協議標準,其具體的實現有很多,既有開源實現的 OpenSSH,也有商業實現方案。使用範圍最廣泛的當然是開源實現 OpenSSH。

為什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。

所以芬蘭就有這麼一位叫做 Tatu Ylonen 的人設計了 SSH 協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被洩露。

目前 SSH 協議已經在全世界廣泛被使用,且已經在成為各個 Linux 發行版的標配。


2. SSH 工作原理


在討論 SSH 的原理和使用前,我們需要分析一個問題:為什麼需要 SSH?

從 1.1 節 SSH 的定義中可以看出,SSH 和 Telnet、FTP 等協議主要的區別在於安全性。這就引出下一個問題:如何實現數據的安全呢?首先想到的實現方案肯定是對數據進行加密。加密的方式主要有兩種:

  1. 對稱加密(也稱為祕鑰加密)
  2. 非對稱加密(也稱公鑰加密)

所謂對稱加密,指加密解密使用同一套祕鑰。如下圖所示:


"


圖解 SSH 原理


1. 初見 SSH


SSH是一種協議標準,用於在網絡主機之間進行加密的一種協議,其目的是實現安全遠程登錄以及其它安全網絡服務

SSH 僅僅是一協議標準,其具體的實現有很多,既有開源實現的 OpenSSH,也有商業實現方案。使用範圍最廣泛的當然是開源實現 OpenSSH。

為什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。

所以芬蘭就有這麼一位叫做 Tatu Ylonen 的人設計了 SSH 協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被洩露。

目前 SSH 協議已經在全世界廣泛被使用,且已經在成為各個 Linux 發行版的標配。


2. SSH 工作原理


在討論 SSH 的原理和使用前,我們需要分析一個問題:為什麼需要 SSH?

從 1.1 節 SSH 的定義中可以看出,SSH 和 Telnet、FTP 等協議主要的區別在於安全性。這就引出下一個問題:如何實現數據的安全呢?首先想到的實現方案肯定是對數據進行加密。加密的方式主要有兩種:

  1. 對稱加密(也稱為祕鑰加密)
  2. 非對稱加密(也稱公鑰加密)

所謂對稱加密,指加密解密使用同一套祕鑰。如下圖所示:


圖解 SSH 原理


圖1-1:對稱加密-Client端

"


圖解 SSH 原理


1. 初見 SSH


SSH是一種協議標準,用於在網絡主機之間進行加密的一種協議,其目的是實現安全遠程登錄以及其它安全網絡服務

SSH 僅僅是一協議標準,其具體的實現有很多,既有開源實現的 OpenSSH,也有商業實現方案。使用範圍最廣泛的當然是開源實現 OpenSSH。

為什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。

所以芬蘭就有這麼一位叫做 Tatu Ylonen 的人設計了 SSH 協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被洩露。

目前 SSH 協議已經在全世界廣泛被使用,且已經在成為各個 Linux 發行版的標配。


2. SSH 工作原理


在討論 SSH 的原理和使用前,我們需要分析一個問題:為什麼需要 SSH?

從 1.1 節 SSH 的定義中可以看出,SSH 和 Telnet、FTP 等協議主要的區別在於安全性。這就引出下一個問題:如何實現數據的安全呢?首先想到的實現方案肯定是對數據進行加密。加密的方式主要有兩種:

  1. 對稱加密(也稱為祕鑰加密)
  2. 非對稱加密(也稱公鑰加密)

所謂對稱加密,指加密解密使用同一套祕鑰。如下圖所示:


圖解 SSH 原理


圖1-1:對稱加密-Client端

圖解 SSH 原理


圖1-2:對稱加密-Server端

對稱加密的加密強度高,很難破解。但是在實際應用過程中不得不面臨一個棘手的問題:如何安全的保存密鑰呢?

尤其是考慮到數量龐大的 Client 端,很難保證密鑰不被洩露。一旦一個 Client端的密鑰被竊取,那麼整個系統的安全性也就不復存在。為了解決這個問題,非對稱加密應運而生。非對稱加密有兩個密鑰:“公鑰”“私鑰”

兩個密鑰的特性:公鑰加密後的密文,只能通過對應的私鑰進行解密。而通過公鑰推理出私鑰的可能性微乎其微。

下面看下使用非對稱加密方案的登錄流程:


"


圖解 SSH 原理


1. 初見 SSH


SSH是一種協議標準,用於在網絡主機之間進行加密的一種協議,其目的是實現安全遠程登錄以及其它安全網絡服務

SSH 僅僅是一協議標準,其具體的實現有很多,既有開源實現的 OpenSSH,也有商業實現方案。使用範圍最廣泛的當然是開源實現 OpenSSH。

為什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。

所以芬蘭就有這麼一位叫做 Tatu Ylonen 的人設計了 SSH 協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被洩露。

目前 SSH 協議已經在全世界廣泛被使用,且已經在成為各個 Linux 發行版的標配。


2. SSH 工作原理


在討論 SSH 的原理和使用前,我們需要分析一個問題:為什麼需要 SSH?

從 1.1 節 SSH 的定義中可以看出,SSH 和 Telnet、FTP 等協議主要的區別在於安全性。這就引出下一個問題:如何實現數據的安全呢?首先想到的實現方案肯定是對數據進行加密。加密的方式主要有兩種:

  1. 對稱加密(也稱為祕鑰加密)
  2. 非對稱加密(也稱公鑰加密)

所謂對稱加密,指加密解密使用同一套祕鑰。如下圖所示:


圖解 SSH 原理


圖1-1:對稱加密-Client端

圖解 SSH 原理


圖1-2:對稱加密-Server端

對稱加密的加密強度高,很難破解。但是在實際應用過程中不得不面臨一個棘手的問題:如何安全的保存密鑰呢?

尤其是考慮到數量龐大的 Client 端,很難保證密鑰不被洩露。一旦一個 Client端的密鑰被竊取,那麼整個系統的安全性也就不復存在。為了解決這個問題,非對稱加密應運而生。非對稱加密有兩個密鑰:“公鑰”“私鑰”

兩個密鑰的特性:公鑰加密後的密文,只能通過對應的私鑰進行解密。而通過公鑰推理出私鑰的可能性微乎其微。

下面看下使用非對稱加密方案的登錄流程:


圖解 SSH 原理


圖1-3:非對稱加密登錄流程

  1. 遠程 Server 收到 Client 端用戶 TopGun 的登錄請求,Server 把自己的公鑰發給用戶。
  2. Client 使用這個公鑰,將密碼進行加密。
  3. Client 將加密的密碼發送給 Server端。
  4. 遠程 Server 用自己的私鑰,解密登錄密碼,然後驗證其合法性。
  5. 若驗證結果,給 Client 相應的響應。
私鑰是 Server 端獨有,這就保證了 Client 的登錄信息即使在網絡傳輸過程中被竊據,也沒有私鑰進行解密,保證了數據的安全性,這充分利用了非對稱加密的特性。

這樣就一定安全了嗎?

上述流程會有一個問題:Client 端如何保證接受到的公鑰就是目標 Server 端的?

如果一個攻擊者中途攔截 Client 的登錄請求,向其發送自己的公鑰,Client 端用攻擊者的公鑰進行數據加密。攻擊者接收到加密信息後再用自己的私鑰進行解密,不就竊取了 Client 的登錄信息了嗎?這就是所謂的中間人攻擊。


"


圖解 SSH 原理


1. 初見 SSH


SSH是一種協議標準,用於在網絡主機之間進行加密的一種協議,其目的是實現安全遠程登錄以及其它安全網絡服務

SSH 僅僅是一協議標準,其具體的實現有很多,既有開源實現的 OpenSSH,也有商業實現方案。使用範圍最廣泛的當然是開源實現 OpenSSH。

為什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。

所以芬蘭就有這麼一位叫做 Tatu Ylonen 的人設計了 SSH 協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被洩露。

目前 SSH 協議已經在全世界廣泛被使用,且已經在成為各個 Linux 發行版的標配。


2. SSH 工作原理


在討論 SSH 的原理和使用前,我們需要分析一個問題:為什麼需要 SSH?

從 1.1 節 SSH 的定義中可以看出,SSH 和 Telnet、FTP 等協議主要的區別在於安全性。這就引出下一個問題:如何實現數據的安全呢?首先想到的實現方案肯定是對數據進行加密。加密的方式主要有兩種:

  1. 對稱加密(也稱為祕鑰加密)
  2. 非對稱加密(也稱公鑰加密)

所謂對稱加密,指加密解密使用同一套祕鑰。如下圖所示:


圖解 SSH 原理


圖1-1:對稱加密-Client端

圖解 SSH 原理


圖1-2:對稱加密-Server端

對稱加密的加密強度高,很難破解。但是在實際應用過程中不得不面臨一個棘手的問題:如何安全的保存密鑰呢?

尤其是考慮到數量龐大的 Client 端,很難保證密鑰不被洩露。一旦一個 Client端的密鑰被竊取,那麼整個系統的安全性也就不復存在。為了解決這個問題,非對稱加密應運而生。非對稱加密有兩個密鑰:“公鑰”“私鑰”

兩個密鑰的特性:公鑰加密後的密文,只能通過對應的私鑰進行解密。而通過公鑰推理出私鑰的可能性微乎其微。

下面看下使用非對稱加密方案的登錄流程:


圖解 SSH 原理


圖1-3:非對稱加密登錄流程

  1. 遠程 Server 收到 Client 端用戶 TopGun 的登錄請求,Server 把自己的公鑰發給用戶。
  2. Client 使用這個公鑰,將密碼進行加密。
  3. Client 將加密的密碼發送給 Server端。
  4. 遠程 Server 用自己的私鑰,解密登錄密碼,然後驗證其合法性。
  5. 若驗證結果,給 Client 相應的響應。
私鑰是 Server 端獨有,這就保證了 Client 的登錄信息即使在網絡傳輸過程中被竊據,也沒有私鑰進行解密,保證了數據的安全性,這充分利用了非對稱加密的特性。

這樣就一定安全了嗎?

上述流程會有一個問題:Client 端如何保證接受到的公鑰就是目標 Server 端的?

如果一個攻擊者中途攔截 Client 的登錄請求,向其發送自己的公鑰,Client 端用攻擊者的公鑰進行數據加密。攻擊者接收到加密信息後再用自己的私鑰進行解密,不就竊取了 Client 的登錄信息了嗎?這就是所謂的中間人攻擊。


圖解 SSH 原理


圖1-4:中間人攻擊

2.1 SSH 中是如何解決這個問題的?

2.1.1 基於口令的認證


從上面的描述可以看出,問題就在於如何對 Server 的公鑰進行認證?在 https中可以通過 CA 來進行公證,可是 SSH 的 Publish keyPrivate key 都是自己生成的,沒法公證。

只能通過 Client 端自己對公鑰進行確認。通常在第一次登錄的時候,系統會出現下面提示信息:

The authenticity of host 'ssh-server.example.com (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)?

上面的信息說的是:無法確認主機 ssh-server.example.com(12.18.429.21)的真實性,不過知道它的公鑰指紋,是否繼續連接?

之所以用 fingerprint 代替 key,主要是 key 過於長(RSA 算法生成的公鑰有1024 位),很難直接比較。所以,對公鑰進行 Hash 生成一個 128 位的指紋,這樣就方便比較了。

如果輸入 yes 後,會出現下面信息:

Warning: Permanently added 'ssh-server.example.com,12.18.429.21' (RSA) to the list of known hosts.

Password: (enter password)

該 host 已被確認,並被追加到文件 known_hosts 中,然後就需要輸入密碼,之後的流程就按照圖 1-3 進行。

2.1.2 基於公鑰認證


在上面介紹的登錄流程中可以發現,每次登錄都需要輸入密碼,很麻煩。SSH 提供了另外一種可以免去輸入密碼過程的登錄方式:公鑰登錄。流程如下:


"


圖解 SSH 原理


1. 初見 SSH


SSH是一種協議標準,用於在網絡主機之間進行加密的一種協議,其目的是實現安全遠程登錄以及其它安全網絡服務

SSH 僅僅是一協議標準,其具體的實現有很多,既有開源實現的 OpenSSH,也有商業實現方案。使用範圍最廣泛的當然是開源實現 OpenSSH。

為什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。

所以芬蘭就有這麼一位叫做 Tatu Ylonen 的人設計了 SSH 協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被洩露。

目前 SSH 協議已經在全世界廣泛被使用,且已經在成為各個 Linux 發行版的標配。


2. SSH 工作原理


在討論 SSH 的原理和使用前,我們需要分析一個問題:為什麼需要 SSH?

從 1.1 節 SSH 的定義中可以看出,SSH 和 Telnet、FTP 等協議主要的區別在於安全性。這就引出下一個問題:如何實現數據的安全呢?首先想到的實現方案肯定是對數據進行加密。加密的方式主要有兩種:

  1. 對稱加密(也稱為祕鑰加密)
  2. 非對稱加密(也稱公鑰加密)

所謂對稱加密,指加密解密使用同一套祕鑰。如下圖所示:


圖解 SSH 原理


圖1-1:對稱加密-Client端

圖解 SSH 原理


圖1-2:對稱加密-Server端

對稱加密的加密強度高,很難破解。但是在實際應用過程中不得不面臨一個棘手的問題:如何安全的保存密鑰呢?

尤其是考慮到數量龐大的 Client 端,很難保證密鑰不被洩露。一旦一個 Client端的密鑰被竊取,那麼整個系統的安全性也就不復存在。為了解決這個問題,非對稱加密應運而生。非對稱加密有兩個密鑰:“公鑰”“私鑰”

兩個密鑰的特性:公鑰加密後的密文,只能通過對應的私鑰進行解密。而通過公鑰推理出私鑰的可能性微乎其微。

下面看下使用非對稱加密方案的登錄流程:


圖解 SSH 原理


圖1-3:非對稱加密登錄流程

  1. 遠程 Server 收到 Client 端用戶 TopGun 的登錄請求,Server 把自己的公鑰發給用戶。
  2. Client 使用這個公鑰,將密碼進行加密。
  3. Client 將加密的密碼發送給 Server端。
  4. 遠程 Server 用自己的私鑰,解密登錄密碼,然後驗證其合法性。
  5. 若驗證結果,給 Client 相應的響應。
私鑰是 Server 端獨有,這就保證了 Client 的登錄信息即使在網絡傳輸過程中被竊據,也沒有私鑰進行解密,保證了數據的安全性,這充分利用了非對稱加密的特性。

這樣就一定安全了嗎?

上述流程會有一個問題:Client 端如何保證接受到的公鑰就是目標 Server 端的?

如果一個攻擊者中途攔截 Client 的登錄請求,向其發送自己的公鑰,Client 端用攻擊者的公鑰進行數據加密。攻擊者接收到加密信息後再用自己的私鑰進行解密,不就竊取了 Client 的登錄信息了嗎?這就是所謂的中間人攻擊。


圖解 SSH 原理


圖1-4:中間人攻擊

2.1 SSH 中是如何解決這個問題的?

2.1.1 基於口令的認證


從上面的描述可以看出,問題就在於如何對 Server 的公鑰進行認證?在 https中可以通過 CA 來進行公證,可是 SSH 的 Publish keyPrivate key 都是自己生成的,沒法公證。

只能通過 Client 端自己對公鑰進行確認。通常在第一次登錄的時候,系統會出現下面提示信息:

The authenticity of host 'ssh-server.example.com (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)?

上面的信息說的是:無法確認主機 ssh-server.example.com(12.18.429.21)的真實性,不過知道它的公鑰指紋,是否繼續連接?

之所以用 fingerprint 代替 key,主要是 key 過於長(RSA 算法生成的公鑰有1024 位),很難直接比較。所以,對公鑰進行 Hash 生成一個 128 位的指紋,這樣就方便比較了。

如果輸入 yes 後,會出現下面信息:

Warning: Permanently added 'ssh-server.example.com,12.18.429.21' (RSA) to the list of known hosts.

Password: (enter password)

該 host 已被確認,並被追加到文件 known_hosts 中,然後就需要輸入密碼,之後的流程就按照圖 1-3 進行。

2.1.2 基於公鑰認證


在上面介紹的登錄流程中可以發現,每次登錄都需要輸入密碼,很麻煩。SSH 提供了另外一種可以免去輸入密碼過程的登錄方式:公鑰登錄。流程如下:


圖解 SSH 原理


圖1-5:公鑰認證流程

  1. Client 將自己的公鑰存放在 Server 上,追加在文件 authorized_keys 中。注意:Client 端的 Public key 是 Client 手動 Copy 到 Server端的,SSH 建立連接過程中沒有公鑰的交換操作。
  2. Server 端接收到 Client 的連接請求後,會在 authorized_keys 中匹配到 Client 的公鑰 pubKey,並生成隨機數 R,用 Client 的公鑰對該隨機數進行加密得到 pubKey(R),然後將加密後信息發送給 Client。
  3. Client 端通過私鑰進行解密得到隨機數 R,然後對隨機數 R 和本次會話的 SessionKey 利用 MD5 生成摘要 Digest1,發送給 Server 端。
  4. Server 端會也會對 R 和 SessionKey 利用同樣摘要算法生成 Digest2。
  5. Server 端會最後比較 Digest1 和 Digest2 是否相同,完成認證過程。

注意:在步驟1中,Client 將自己的公鑰存放在 Server 上。需要用戶手動將公鑰 Copy 到 Server 上。這就是在配置 SSH 的時候進程進行的操作。下圖是 GitHub 上 SSH keys 設置視圖:



"


圖解 SSH 原理


1. 初見 SSH


SSH是一種協議標準,用於在網絡主機之間進行加密的一種協議,其目的是實現安全遠程登錄以及其它安全網絡服務

SSH 僅僅是一協議標準,其具體的實現有很多,既有開源實現的 OpenSSH,也有商業實現方案。使用範圍最廣泛的當然是開源實現 OpenSSH。

為什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。

所以芬蘭就有這麼一位叫做 Tatu Ylonen 的人設計了 SSH 協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被洩露。

目前 SSH 協議已經在全世界廣泛被使用,且已經在成為各個 Linux 發行版的標配。


2. SSH 工作原理


在討論 SSH 的原理和使用前,我們需要分析一個問題:為什麼需要 SSH?

從 1.1 節 SSH 的定義中可以看出,SSH 和 Telnet、FTP 等協議主要的區別在於安全性。這就引出下一個問題:如何實現數據的安全呢?首先想到的實現方案肯定是對數據進行加密。加密的方式主要有兩種:

  1. 對稱加密(也稱為祕鑰加密)
  2. 非對稱加密(也稱公鑰加密)

所謂對稱加密,指加密解密使用同一套祕鑰。如下圖所示:


圖解 SSH 原理


圖1-1:對稱加密-Client端

圖解 SSH 原理


圖1-2:對稱加密-Server端

對稱加密的加密強度高,很難破解。但是在實際應用過程中不得不面臨一個棘手的問題:如何安全的保存密鑰呢?

尤其是考慮到數量龐大的 Client 端,很難保證密鑰不被洩露。一旦一個 Client端的密鑰被竊取,那麼整個系統的安全性也就不復存在。為了解決這個問題,非對稱加密應運而生。非對稱加密有兩個密鑰:“公鑰”“私鑰”

兩個密鑰的特性:公鑰加密後的密文,只能通過對應的私鑰進行解密。而通過公鑰推理出私鑰的可能性微乎其微。

下面看下使用非對稱加密方案的登錄流程:


圖解 SSH 原理


圖1-3:非對稱加密登錄流程

  1. 遠程 Server 收到 Client 端用戶 TopGun 的登錄請求,Server 把自己的公鑰發給用戶。
  2. Client 使用這個公鑰,將密碼進行加密。
  3. Client 將加密的密碼發送給 Server端。
  4. 遠程 Server 用自己的私鑰,解密登錄密碼,然後驗證其合法性。
  5. 若驗證結果,給 Client 相應的響應。
私鑰是 Server 端獨有,這就保證了 Client 的登錄信息即使在網絡傳輸過程中被竊據,也沒有私鑰進行解密,保證了數據的安全性,這充分利用了非對稱加密的特性。

這樣就一定安全了嗎?

上述流程會有一個問題:Client 端如何保證接受到的公鑰就是目標 Server 端的?

如果一個攻擊者中途攔截 Client 的登錄請求,向其發送自己的公鑰,Client 端用攻擊者的公鑰進行數據加密。攻擊者接收到加密信息後再用自己的私鑰進行解密,不就竊取了 Client 的登錄信息了嗎?這就是所謂的中間人攻擊。


圖解 SSH 原理


圖1-4:中間人攻擊

2.1 SSH 中是如何解決這個問題的?

2.1.1 基於口令的認證


從上面的描述可以看出,問題就在於如何對 Server 的公鑰進行認證?在 https中可以通過 CA 來進行公證,可是 SSH 的 Publish keyPrivate key 都是自己生成的,沒法公證。

只能通過 Client 端自己對公鑰進行確認。通常在第一次登錄的時候,系統會出現下面提示信息:

The authenticity of host 'ssh-server.example.com (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)?

上面的信息說的是:無法確認主機 ssh-server.example.com(12.18.429.21)的真實性,不過知道它的公鑰指紋,是否繼續連接?

之所以用 fingerprint 代替 key,主要是 key 過於長(RSA 算法生成的公鑰有1024 位),很難直接比較。所以,對公鑰進行 Hash 生成一個 128 位的指紋,這樣就方便比較了。

如果輸入 yes 後,會出現下面信息:

Warning: Permanently added 'ssh-server.example.com,12.18.429.21' (RSA) to the list of known hosts.

Password: (enter password)

該 host 已被確認,並被追加到文件 known_hosts 中,然後就需要輸入密碼,之後的流程就按照圖 1-3 進行。

2.1.2 基於公鑰認證


在上面介紹的登錄流程中可以發現,每次登錄都需要輸入密碼,很麻煩。SSH 提供了另外一種可以免去輸入密碼過程的登錄方式:公鑰登錄。流程如下:


圖解 SSH 原理


圖1-5:公鑰認證流程

  1. Client 將自己的公鑰存放在 Server 上,追加在文件 authorized_keys 中。注意:Client 端的 Public key 是 Client 手動 Copy 到 Server端的,SSH 建立連接過程中沒有公鑰的交換操作。
  2. Server 端接收到 Client 的連接請求後,會在 authorized_keys 中匹配到 Client 的公鑰 pubKey,並生成隨機數 R,用 Client 的公鑰對該隨機數進行加密得到 pubKey(R),然後將加密後信息發送給 Client。
  3. Client 端通過私鑰進行解密得到隨機數 R,然後對隨機數 R 和本次會話的 SessionKey 利用 MD5 生成摘要 Digest1,發送給 Server 端。
  4. Server 端會也會對 R 和 SessionKey 利用同樣摘要算法生成 Digest2。
  5. Server 端會最後比較 Digest1 和 Digest2 是否相同,完成認證過程。

注意:在步驟1中,Client 將自己的公鑰存放在 Server 上。需要用戶手動將公鑰 Copy 到 Server 上。這就是在配置 SSH 的時候進程進行的操作。下圖是 GitHub 上 SSH keys 設置視圖:



圖解 SSH 原理


GitHub 中 SSH keys 設置

在步驟 2 中,Server 端根據什麼信息在 authorized_keys 中進行查找的呢?主要是根據 Client 在認證的開始會發送一個 KeyID 給 Server,這個 KeyID 會唯一對應該 Client 的一個 PublicKey,Server 就是通過該 KeyID 在 authorized_keys 進行查找對應的 PublicKey。

3. SSH 實踐

3.1 生成密鑰操作

經過上面的原理分析,下面三行命令的含義應該很容易理解了:

$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 0600 ~/.ssh/authorized_keys

ssh-keygen 是用於生產密鑰的工具。

  • -t:指定生成密鑰類型(rsa、dsa、ecdsa 等)
  • -P:指定 passphrase,用於確保私鑰的安全
  • -f:指定存放密鑰的文件(公鑰文件默認和私鑰同目錄下,不同的是存放公鑰的文件名需要加上後綴 .pub)

首先看下面 ~/.ssh 中的四個文件:


"


圖解 SSH 原理


1. 初見 SSH


SSH是一種協議標準,用於在網絡主機之間進行加密的一種協議,其目的是實現安全遠程登錄以及其它安全網絡服務

SSH 僅僅是一協議標準,其具體的實現有很多,既有開源實現的 OpenSSH,也有商業實現方案。使用範圍最廣泛的當然是開源實現 OpenSSH。

為什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。

所以芬蘭就有這麼一位叫做 Tatu Ylonen 的人設計了 SSH 協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被洩露。

目前 SSH 協議已經在全世界廣泛被使用,且已經在成為各個 Linux 發行版的標配。


2. SSH 工作原理


在討論 SSH 的原理和使用前,我們需要分析一個問題:為什麼需要 SSH?

從 1.1 節 SSH 的定義中可以看出,SSH 和 Telnet、FTP 等協議主要的區別在於安全性。這就引出下一個問題:如何實現數據的安全呢?首先想到的實現方案肯定是對數據進行加密。加密的方式主要有兩種:

  1. 對稱加密(也稱為祕鑰加密)
  2. 非對稱加密(也稱公鑰加密)

所謂對稱加密,指加密解密使用同一套祕鑰。如下圖所示:


圖解 SSH 原理


圖1-1:對稱加密-Client端

圖解 SSH 原理


圖1-2:對稱加密-Server端

對稱加密的加密強度高,很難破解。但是在實際應用過程中不得不面臨一個棘手的問題:如何安全的保存密鑰呢?

尤其是考慮到數量龐大的 Client 端,很難保證密鑰不被洩露。一旦一個 Client端的密鑰被竊取,那麼整個系統的安全性也就不復存在。為了解決這個問題,非對稱加密應運而生。非對稱加密有兩個密鑰:“公鑰”“私鑰”

兩個密鑰的特性:公鑰加密後的密文,只能通過對應的私鑰進行解密。而通過公鑰推理出私鑰的可能性微乎其微。

下面看下使用非對稱加密方案的登錄流程:


圖解 SSH 原理


圖1-3:非對稱加密登錄流程

  1. 遠程 Server 收到 Client 端用戶 TopGun 的登錄請求,Server 把自己的公鑰發給用戶。
  2. Client 使用這個公鑰,將密碼進行加密。
  3. Client 將加密的密碼發送給 Server端。
  4. 遠程 Server 用自己的私鑰,解密登錄密碼,然後驗證其合法性。
  5. 若驗證結果,給 Client 相應的響應。
私鑰是 Server 端獨有,這就保證了 Client 的登錄信息即使在網絡傳輸過程中被竊據,也沒有私鑰進行解密,保證了數據的安全性,這充分利用了非對稱加密的特性。

這樣就一定安全了嗎?

上述流程會有一個問題:Client 端如何保證接受到的公鑰就是目標 Server 端的?

如果一個攻擊者中途攔截 Client 的登錄請求,向其發送自己的公鑰,Client 端用攻擊者的公鑰進行數據加密。攻擊者接收到加密信息後再用自己的私鑰進行解密,不就竊取了 Client 的登錄信息了嗎?這就是所謂的中間人攻擊。


圖解 SSH 原理


圖1-4:中間人攻擊

2.1 SSH 中是如何解決這個問題的?

2.1.1 基於口令的認證


從上面的描述可以看出,問題就在於如何對 Server 的公鑰進行認證?在 https中可以通過 CA 來進行公證,可是 SSH 的 Publish keyPrivate key 都是自己生成的,沒法公證。

只能通過 Client 端自己對公鑰進行確認。通常在第一次登錄的時候,系統會出現下面提示信息:

The authenticity of host 'ssh-server.example.com (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)?

上面的信息說的是:無法確認主機 ssh-server.example.com(12.18.429.21)的真實性,不過知道它的公鑰指紋,是否繼續連接?

之所以用 fingerprint 代替 key,主要是 key 過於長(RSA 算法生成的公鑰有1024 位),很難直接比較。所以,對公鑰進行 Hash 生成一個 128 位的指紋,這樣就方便比較了。

如果輸入 yes 後,會出現下面信息:

Warning: Permanently added 'ssh-server.example.com,12.18.429.21' (RSA) to the list of known hosts.

Password: (enter password)

該 host 已被確認,並被追加到文件 known_hosts 中,然後就需要輸入密碼,之後的流程就按照圖 1-3 進行。

2.1.2 基於公鑰認證


在上面介紹的登錄流程中可以發現,每次登錄都需要輸入密碼,很麻煩。SSH 提供了另外一種可以免去輸入密碼過程的登錄方式:公鑰登錄。流程如下:


圖解 SSH 原理


圖1-5:公鑰認證流程

  1. Client 將自己的公鑰存放在 Server 上,追加在文件 authorized_keys 中。注意:Client 端的 Public key 是 Client 手動 Copy 到 Server端的,SSH 建立連接過程中沒有公鑰的交換操作。
  2. Server 端接收到 Client 的連接請求後,會在 authorized_keys 中匹配到 Client 的公鑰 pubKey,並生成隨機數 R,用 Client 的公鑰對該隨機數進行加密得到 pubKey(R),然後將加密後信息發送給 Client。
  3. Client 端通過私鑰進行解密得到隨機數 R,然後對隨機數 R 和本次會話的 SessionKey 利用 MD5 生成摘要 Digest1,發送給 Server 端。
  4. Server 端會也會對 R 和 SessionKey 利用同樣摘要算法生成 Digest2。
  5. Server 端會最後比較 Digest1 和 Digest2 是否相同,完成認證過程。

注意:在步驟1中,Client 將自己的公鑰存放在 Server 上。需要用戶手動將公鑰 Copy 到 Server 上。這就是在配置 SSH 的時候進程進行的操作。下圖是 GitHub 上 SSH keys 設置視圖:



圖解 SSH 原理


GitHub 中 SSH keys 設置

在步驟 2 中,Server 端根據什麼信息在 authorized_keys 中進行查找的呢?主要是根據 Client 在認證的開始會發送一個 KeyID 給 Server,這個 KeyID 會唯一對應該 Client 的一個 PublicKey,Server 就是通過該 KeyID 在 authorized_keys 進行查找對應的 PublicKey。

3. SSH 實踐

3.1 生成密鑰操作

經過上面的原理分析,下面三行命令的含義應該很容易理解了:

$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 0600 ~/.ssh/authorized_keys

ssh-keygen 是用於生產密鑰的工具。

  • -t:指定生成密鑰類型(rsa、dsa、ecdsa 等)
  • -P:指定 passphrase,用於確保私鑰的安全
  • -f:指定存放密鑰的文件(公鑰文件默認和私鑰同目錄下,不同的是存放公鑰的文件名需要加上後綴 .pub)

首先看下面 ~/.ssh 中的四個文件:


圖解 SSH 原理


SSH 涉及文件

  1. id_rsa:保存私鑰
  2. id_rsa.pub:保存公鑰
  3. authorized_keys:保存已授權的客戶端公鑰
  4. known_hosts:保存已認證的遠程主機 ID(關於 known_hosts 詳情,見文末更新內容)

四個角色的關係如下圖所示:


"


圖解 SSH 原理


1. 初見 SSH


SSH是一種協議標準,用於在網絡主機之間進行加密的一種協議,其目的是實現安全遠程登錄以及其它安全網絡服務

SSH 僅僅是一協議標準,其具體的實現有很多,既有開源實現的 OpenSSH,也有商業實現方案。使用範圍最廣泛的當然是開源實現 OpenSSH。

為什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。

所以芬蘭就有這麼一位叫做 Tatu Ylonen 的人設計了 SSH 協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被洩露。

目前 SSH 協議已經在全世界廣泛被使用,且已經在成為各個 Linux 發行版的標配。


2. SSH 工作原理


在討論 SSH 的原理和使用前,我們需要分析一個問題:為什麼需要 SSH?

從 1.1 節 SSH 的定義中可以看出,SSH 和 Telnet、FTP 等協議主要的區別在於安全性。這就引出下一個問題:如何實現數據的安全呢?首先想到的實現方案肯定是對數據進行加密。加密的方式主要有兩種:

  1. 對稱加密(也稱為祕鑰加密)
  2. 非對稱加密(也稱公鑰加密)

所謂對稱加密,指加密解密使用同一套祕鑰。如下圖所示:


圖解 SSH 原理


圖1-1:對稱加密-Client端

圖解 SSH 原理


圖1-2:對稱加密-Server端

對稱加密的加密強度高,很難破解。但是在實際應用過程中不得不面臨一個棘手的問題:如何安全的保存密鑰呢?

尤其是考慮到數量龐大的 Client 端,很難保證密鑰不被洩露。一旦一個 Client端的密鑰被竊取,那麼整個系統的安全性也就不復存在。為了解決這個問題,非對稱加密應運而生。非對稱加密有兩個密鑰:“公鑰”“私鑰”

兩個密鑰的特性:公鑰加密後的密文,只能通過對應的私鑰進行解密。而通過公鑰推理出私鑰的可能性微乎其微。

下面看下使用非對稱加密方案的登錄流程:


圖解 SSH 原理


圖1-3:非對稱加密登錄流程

  1. 遠程 Server 收到 Client 端用戶 TopGun 的登錄請求,Server 把自己的公鑰發給用戶。
  2. Client 使用這個公鑰,將密碼進行加密。
  3. Client 將加密的密碼發送給 Server端。
  4. 遠程 Server 用自己的私鑰,解密登錄密碼,然後驗證其合法性。
  5. 若驗證結果,給 Client 相應的響應。
私鑰是 Server 端獨有,這就保證了 Client 的登錄信息即使在網絡傳輸過程中被竊據,也沒有私鑰進行解密,保證了數據的安全性,這充分利用了非對稱加密的特性。

這樣就一定安全了嗎?

上述流程會有一個問題:Client 端如何保證接受到的公鑰就是目標 Server 端的?

如果一個攻擊者中途攔截 Client 的登錄請求,向其發送自己的公鑰,Client 端用攻擊者的公鑰進行數據加密。攻擊者接收到加密信息後再用自己的私鑰進行解密,不就竊取了 Client 的登錄信息了嗎?這就是所謂的中間人攻擊。


圖解 SSH 原理


圖1-4:中間人攻擊

2.1 SSH 中是如何解決這個問題的?

2.1.1 基於口令的認證


從上面的描述可以看出,問題就在於如何對 Server 的公鑰進行認證?在 https中可以通過 CA 來進行公證,可是 SSH 的 Publish keyPrivate key 都是自己生成的,沒法公證。

只能通過 Client 端自己對公鑰進行確認。通常在第一次登錄的時候,系統會出現下面提示信息:

The authenticity of host 'ssh-server.example.com (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)?

上面的信息說的是:無法確認主機 ssh-server.example.com(12.18.429.21)的真實性,不過知道它的公鑰指紋,是否繼續連接?

之所以用 fingerprint 代替 key,主要是 key 過於長(RSA 算法生成的公鑰有1024 位),很難直接比較。所以,對公鑰進行 Hash 生成一個 128 位的指紋,這樣就方便比較了。

如果輸入 yes 後,會出現下面信息:

Warning: Permanently added 'ssh-server.example.com,12.18.429.21' (RSA) to the list of known hosts.

Password: (enter password)

該 host 已被確認,並被追加到文件 known_hosts 中,然後就需要輸入密碼,之後的流程就按照圖 1-3 進行。

2.1.2 基於公鑰認證


在上面介紹的登錄流程中可以發現,每次登錄都需要輸入密碼,很麻煩。SSH 提供了另外一種可以免去輸入密碼過程的登錄方式:公鑰登錄。流程如下:


圖解 SSH 原理


圖1-5:公鑰認證流程

  1. Client 將自己的公鑰存放在 Server 上,追加在文件 authorized_keys 中。注意:Client 端的 Public key 是 Client 手動 Copy 到 Server端的,SSH 建立連接過程中沒有公鑰的交換操作。
  2. Server 端接收到 Client 的連接請求後,會在 authorized_keys 中匹配到 Client 的公鑰 pubKey,並生成隨機數 R,用 Client 的公鑰對該隨機數進行加密得到 pubKey(R),然後將加密後信息發送給 Client。
  3. Client 端通過私鑰進行解密得到隨機數 R,然後對隨機數 R 和本次會話的 SessionKey 利用 MD5 生成摘要 Digest1,發送給 Server 端。
  4. Server 端會也會對 R 和 SessionKey 利用同樣摘要算法生成 Digest2。
  5. Server 端會最後比較 Digest1 和 Digest2 是否相同,完成認證過程。

注意:在步驟1中,Client 將自己的公鑰存放在 Server 上。需要用戶手動將公鑰 Copy 到 Server 上。這就是在配置 SSH 的時候進程進行的操作。下圖是 GitHub 上 SSH keys 設置視圖:



圖解 SSH 原理


GitHub 中 SSH keys 設置

在步驟 2 中,Server 端根據什麼信息在 authorized_keys 中進行查找的呢?主要是根據 Client 在認證的開始會發送一個 KeyID 給 Server,這個 KeyID 會唯一對應該 Client 的一個 PublicKey,Server 就是通過該 KeyID 在 authorized_keys 進行查找對應的 PublicKey。

3. SSH 實踐

3.1 生成密鑰操作

經過上面的原理分析,下面三行命令的含義應該很容易理解了:

$ ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
$ chmod 0600 ~/.ssh/authorized_keys

ssh-keygen 是用於生產密鑰的工具。

  • -t:指定生成密鑰類型(rsa、dsa、ecdsa 等)
  • -P:指定 passphrase,用於確保私鑰的安全
  • -f:指定存放密鑰的文件(公鑰文件默認和私鑰同目錄下,不同的是存放公鑰的文件名需要加上後綴 .pub)

首先看下面 ~/.ssh 中的四個文件:


圖解 SSH 原理


SSH 涉及文件

  1. id_rsa:保存私鑰
  2. id_rsa.pub:保存公鑰
  3. authorized_keys:保存已授權的客戶端公鑰
  4. known_hosts:保存已認證的遠程主機 ID(關於 known_hosts 詳情,見文末更新內容)

四個角色的關係如下圖所示:


圖解 SSH 原理


SSH 結構簡圖

需要注意的是:一臺主機可能既是 Client,也是 Server。所以會同時擁有authorized_keys 和 known_hosts。

3.2 登錄操作

# 以用戶名user,登錄遠程主機host
$ ssh user@host

# 本地用戶和遠程用戶相同,則用戶名可省去
$ ssh host

# SSH默認端口22,可以用參數p修改端口
$ ssh -p 2017 user@host

4. 其它一些補充


下面關於 SSH 的 known_hosts 機制的一些補充。

4.1 known_hosts 中存儲的內容是什麼?


known_hosts 中存儲是已認證的遠程主機 host key,每個 SSH Server 都有一個 secret, unique ID, called a host key

4.2 host key 何時加入 known_hosts 的?


當我們第一次通過 SSH 登錄遠程主機的時候,Client 端會有如下提示:

Host key not found from the list of known hosts.
Are you sure you want to continue connecting (yes/no)?

此時,如果我們選擇 yes,那麼該 host key 就會被加入到 Client 的known_hosts 中,格式如下:

# domain name+encryption algorithm+host key

example.hostname.com ssh-rsa AAAAB4NzaC1yc2EAAAABIwAAAQEA...

4.3 為什麼需要 known_hosts?

最後探討下為什麼需要 known_hosts,這個文件主要是通過 Client 和 Server的雙向認證,從而避免中間人(man-in-the-middle attack)攻擊,每次Client 向 Server 發起連接的時候,不僅僅 Server 要驗證 Client 的合法性,Client 同樣也需要驗證 Server 的身份,SSH Client 就是通過 known_hosts 中的 host key 來驗證 Server 的身份的。

這種方案足夠安全嗎?當然不,比如第一次連接一個未知 Server 的時候,known_hosts 還沒有該 Server 的 host key,這不也可能遭到中間人攻擊嗎?這可能只是安全性和可操作性之間的折中吧。

5. 總結


本文以圖文方式對 SSH 原理進行解析(主要指遠程登錄,沒有涉及端口轉發等功能)。同時分析了非對稱加密的特性,以及在實踐過程中如何對加密操作進行改進。

"

相關推薦

推薦中...