SSH密鑰登陸流程分析

本文首發於 https://jaychen.ccgit

做者 jaychengithub

寫一篇短文,介紹 ssh 密鑰登陸遠程服務器流程和注意事項。ubuntu

登陸流程

密鑰登陸比密碼登陸安全,主要是由於他使用了非對稱加密,登陸過程當中須要用到密鑰對。整個登陸流程以下:安全

  1. 遠程服務器持有公鑰,當有用戶進行登陸,服務器就會隨機生成一串字符串,而後發送給正在進行登陸的用戶。
  2. 用戶收到遠程服務器發來的字符串,使用與遠程服務器公鑰配對的私鑰對字符串進行加密,再發送給遠程服務器。
  3. 服務器使用公鑰對用戶發來的加密字符串進行解密,獲得的解密字符串若是與第一步中發送給客戶端的隨機字符串同樣,那麼判斷爲登陸成功。

整個登陸的流程就是這麼簡單,可是在實際使用 ssh 登陸中還會碰到一些小細節,這裏演示一遍 ssh 遠程登陸來展現下這些細節問題。bash

生成密鑰對

使用 ssh-keygen 就能夠直接生成登陸須要的密鑰對。ssh-keygen 是 Linux 下的命令,不添加任何參數就能夠生成密鑰對。服務器

➜  ~ ssh-keygen
Generating public/private rsa key pair.

Enter file in which to save the key (/home/jaychen/.ssh/id_rsa):   #1
Enter passphrase (empty for no passphrase):                        #2
Enter same passphrase again:                                       #3
複製代碼

執行 ssh-keygen 會出現如上的提示,在 #1 處這裏提示用戶輸入生成的私鑰的名稱,若是不填,默認私鑰保存在 /home/jaychen/.ssh/id_rsa 文件中。這裏要注意兩點:markdown

  • 生成的密鑰,會放在執行 ssh-keygen 命令的用戶的家目錄下的 .ssh 文件夾中。即 $HOME/.ssh/ 目錄下。
  • 生成的公鑰的文件名,一般是私鑰的文件名後面加 .pub 的後綴。

#2 處,提示輸入密碼,注意這裏的密碼是用來保證私鑰的安全的。若是填寫了密碼,那麼在使用密鑰進行登陸的時候,會讓你輸入密碼,這樣子保證了若是私鑰丟失了不至於被惡意使用。話是這麼說,可是平時使用這裏我都是直接略過。ssh

#3 是重複 #2 輸入的密碼,這裏就不廢話了。加密

生成密鑰以後,就能夠在 /home/jaychen/.ssh/ 下看到兩個文件了(我這裏會放在 /home/jaychen 下是由於我使用 jaychen 用戶來執行 ssh-keygen 命令)spa

➜  .ssh ls
total 16K
drwx------ 2 jaychen jaychen 4.0K 12月  7 17:57 .
drwx------ 9 jaychen jaychen 4.0K 12月  7 18:14 ..
-rw------- 1 jaychen jaychen 1.7K 12月  7 17:57 id_rsa.github
-rw-r--r-- 1 jaychen jaychen 390 12月  7 17:57 id_rsa.github.pub

複製代碼

生成的私鑰還要注意一點:私鑰的權限應該爲 rw-------,若是私鑰的權限過大,那麼私鑰任何人均可以讀寫就會變得不安全。ssh 登陸就會失敗。

首次 ssh 登陸

登陸遠程服務器的命令是

ssh 登陸用戶@服務器ip
複製代碼

這裏開始要注意兩個用戶的概念:

  • 本地執行這條命令的用戶,即當前登陸用戶,我這裏演示的用戶名稱是 jaychen。
  • 要登陸到遠程服務器的用戶。

在開始登陸以前,咱們要首先要把生成公鑰上傳到服務器。

公鑰的內容要保存到要登陸的用戶的家目錄下的 .ssh/authorized_keys 文件中。假設你以後要使用 root 用戶登陸遠程服務器,那麼公鑰的內容應該是保存在 /root/.ssh/authorized_keys中。注意 authorized_keys 文件是能夠保存多個公鑰信息的,每一個公鑰以換行分開。

上傳完畢以後,執行

ssh root@遠程服務器 ip
複製代碼

這個時候,如上面說的,遠程服務器會發送一段隨機字符串回來,這個時候須要使用私鑰對字符串進行加密。而這個私鑰會去執行該命令的用戶的家目錄下的 .ssh 目錄讀取私鑰文件,默認私鑰文件爲 id_rsa 文件。即 $HOME/.ssh/id_rsa 文件。假設在生成密鑰的時候對私鑰進行了加密,那麼這個時候就須要輸入密碼。

上面的流程用戶登陸的時候是不會感知的,ssh 在背後完成了全部的校驗操做,若是密鑰匹配的話,那麼用戶就能夠直接登陸到遠程服務器,可是若是是首次登陸的話,會出現相似下面的提示:

➜  .ssh ssh root@192.168.1.1
The authenticity of host '192.168.1.1 (192.168.1.1)' can't be established. ECDSA key fingerprint is SHA256:61U/SJ4n/QdR7oKT2gaHNuGxhx98saqMfzJnzA1XFZg. Are you sure you want to continue connecting (yes/no)? 複製代碼

這句話的意思是,遠程服務器的真實身份沒法校驗,只知道公鑰指紋(公鑰的 MD5 值)爲 61U/SJ4n/QdR7oKT2gaHNuGxhx98saqMfzJnzA1XFZg,是否真的要創建鏈接。出現上面的提示是由於避免存在中間人攻擊

中間人攻擊

中間人攻擊的前提是,你第一次登陸一臺遠程服務器,你除了用戶名、用戶名對應的公鑰私鑰以及服務器 ip 以外,對遠程服務器絲絕不瞭解的狀況下。假設你 ssh 遠程登陸 192.168.1.1 的遠程主機,在鏈接過程當中被第三者攔截,第三者假冒本身爲 192.168.1.1 的主機,那麼你就會直接鏈接到其餘人的服務器上。這就是中間人攻擊。

爲了不中間人攻擊,ssh 在首次登陸的時候會返回公鑰指紋,用戶須要本身手動去比對你要登陸的遠程服務器的公鑰的公鑰指紋和 ssh 返回的公鑰指紋是否同樣

通過比較公鑰指紋,確認該服務器就是你要登陸的服務器,輸入 yes 以後就能夠成功登陸。整個登陸流程結束。

known_hosts 文件

第一次登陸以後,在本機的 $HOME/.ssh/ 目錄下就會生成一個 known_hosts 的文件,內容相似下面

➜  .ssh cat known_hosts

192.168.1.1 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOPKYWolOYTDevvBR6GV0rFcI0z/DHZizN5l/ajApsgx+UcOOh51liuyBRRCIyF+BR56Le0lP0Pn6nzvLjbqMqg=
複製代碼

這個文件記錄了遠程主機 ip 和遠程主機對應的公鑰指紋,那麼在下次登陸的時候,遠程主機發送過來的公鑰指紋,直接和 known_hosts 文件中對應 ip 的公鑰指紋比較便可。

config 配置

不少時候,咱們開發可能須要鏈接多臺遠程服務器,而且須要配置 git 服務器的私鑰。那麼這麼多的服務器不能共用一套私鑰,不一樣的服務器應該使用不一樣的私鑰。可是咱們從上面的鏈接流程能夠看到,ssh 默認是去讀取 $HOME/.ssh/id_rsa 文件做爲私鑰登陸的。若是想要不一樣的服務器使用不一樣的私鑰進行登陸,那麼須要在 .ssh 目錄下編寫 config 文件來進行配置。

config 的配置很簡單,只要指明哪一個用戶登陸哪臺遠程服務器須要使用哪一個私鑰便可。下面給出一個配置示例。

Host github.com
	User jaychen
	IdentityFile ~/.ssh/id_rsa.github
Host 192.168.1.1
	User ubuntu
	IdentityFile ~/.ssh/id_rsa.xxx
複製代碼

上面 config 文件字段含義以下:

  • Host 指明瞭遠程主機的 ip,除了使用 ip 地址,也能夠直接使用網址。
  • User 指的是登陸遠程主機的用戶。
  • IdentityFile 指明使用哪一個私鑰文件。

編寫好 config 文件以後,須要把 config 文件的權限改成 rw-r--r--。若是權限過大,ssh 會禁止登陸。

相關文章
相關標籤/搜索