linux上ssh免密登陸原理及實現

由於個人服務器集羣須要回收日誌到中央進行統一處理,因此須要創建ssh互信關係實現免密登陸。關於ssh的使用你們可能都很熟悉了,咱們今天主要來說下ssh鏈接和免密登陸的原理。php

scp 傳輸文件

scp(secure copy)linux系統下基於ssh登陸進行安全的遠程文件拷貝的命令。html

# 傳遞文件到遠程
scp local_file remote_username@remote_ip:remote_file
# 傳遞文件夾到遠程
scp -r local_folder remote_username@remote_ip:remote_folder 
# 複製遠程文件到本地,只是調換下文件參數位置便可
scp remote_username@remote_ip:remote_file local_file
遠程拷貝的命令還有 rsyncscp消耗資源少,不會提升多少系統負荷,在這一點上, rsync就遠遠不及它了。 rsyncscp會快一點,但當小文件多的狀況下, rsync會致使硬盤 I/O很是高,而 scp基本不影響系統正常使用。

scp類似的命令是cp,可是cp只能本機拷貝而不能跨服務器,所以須要與ssh合做構成scp命令。linux

咱們直接使用scp來跨機器拷貝文件,會提示輸入密碼:git

# 提示輸入server端服務器的work用戶密碼
[work@client.com ~]$ scp test.php work@server.com:/home/work
work@server.com's password:

緣由就在於,scp是先使用ssh鏈接服務端機器後,再使用網絡來執行遠程拷貝(cp)算法

能夠參考ssh的過程:shell

# 一樣的提示輸入server端服務器的work用戶密碼
[work@client.com ~]$ ssh work@server.com
work@server.com's password:

ssh 加密信息

Secure Shell(安全外殼協議,簡稱 SSH)是一種加密的網絡傳輸協議,可在不安全的網絡中爲網絡服務提供安全的傳輸環境。 SSH經過在網絡中建立安全隧道來實現 SSH客戶端與服務器之間的鏈接。雖然任何網絡服務均可以經過 SSH實現安全傳輸, SSH最多見的用途是遠程登陸系統,人們一般利用 SSH來傳輸命令行界面和遠程執行命令。

SSHTelnet/rlogin等非安全shell的替代品,這些協議採用明文傳輸,會引入許多的安全性問題:
圖片描述
如圖所示,telnet使用23號端口,全部的信息,包括用戶名和密碼都是明文傳輸;而ssh使用22號端口,全部的信息都會被加密傳輸,安全性獲得了很大的提升。vim

ssh使用十分簡單,選擇以什麼用戶鏈接哪臺機器,而後輸入密碼便可:安全

$ssh user@hostname
user@hostname's password:

對稱加密和非對稱加密

ssh的主要有點就是安全性,安全性依賴於加密方式,如今主要的加密方式有兩種:對稱加密和非對稱加密。服務器

對稱加密

圖片描述
對稱加密使用同一個密鑰來進行加密和解密,這樣在傳輸時是安全可靠的,可是如何安全的保存密鑰呢,在集羣中,客戶端的數量巨大,一旦任意一個客戶端的密鑰被竊取,那麼整個系統的安全性也不復存在。網絡

非對稱加密

因爲對稱加密的這個弊端,產生了非對稱加密,非對稱加密中有兩個密鑰:公鑰和私鑰。公鑰由私鑰產生,但卻沒法推算出私鑰;公鑰加密後的密文,只能經過對應的私鑰來解密。

非對稱加密的登陸流程:
圖片描述

初始狀態:topgun終端要登陸Server服務器,發起鏈接請求ssh work@server.com

  1. 服務端運行有ssh服務,並持續監聽22號端口,所以能夠生成一對公鑰和私鑰;此時將公鑰返回給客戶端
  2. 客戶端使用公鑰,對登陸密碼進行加密,(如服務器work用戶密碼爲xxx),生成公鑰加密字符串
  3. 客戶端將公鑰加密字符串發送給服務端
  4. 服務端使用私鑰,解密公鑰加密字符串,獲得原始密碼
  5. 校驗密碼是否合法(此爲本機work密碼)
  6. 返回登陸結果給客戶端:成功登陸或密碼錯誤

在非對稱加密中,因爲只有公鑰會被傳輸,而私鑰是服務端本地保存,所以即使公鑰被監聽,也沒法拿到原始密碼,從而登陸服務器。

中間人攻擊

在非對稱加密中能夠有效保護登陸密碼不被泄漏,但這是在創建鏈接到真實服務器的狀況下。設想一下,若是供給者並不監聽密碼或公鑰,而是直接假裝成服務器呢:
圖片描述
在該示例圖中,存在Hacker服務器劫持了你的ssh建連請求(如經過DNS劫持等方式),致使你與Hacker機器的鏈接一切正常,所以它能拿到你的明文密碼,並經過明文密碼來攻擊真實的服務端。

那麼SSH採用了非對稱的加密方式,是怎麼解決這個問題的呢?

[work@client.com: ~]$ ssh work@server.com
The authenticity of host 'server.com (10.10.10.24)' can't be established.
RSA key fingerprint is ad:2e:92:41:6f:31:b1:c1:35:43:eb:df:f1:18:a1:c1.
Are you sure you want to continue connecting (yes/no)?  yes
Warning: Permanently added 'server.com,10.10.10.24' (RSA) to the list of known hosts.
Password: (enter password)

在這個認證信息中,能夠看到提示:沒法確認主機server.com (10.10.10.24)的真實性,不過知道它的公鑰指紋,是否繼續鏈接?

輸入yes繼續鏈接後,就會確認該服務器爲可信任服務器,而後添加到known_hosts文件中,下次不用再次確認,而後跳轉到輸入密碼的驗證階段。這種簡單粗暴的方式至關於讓咱們肉眼比對來判斷目標服務器是不是真實服務器,我以爲並非最理想的方式,但願後續會有更完美的認證方式。

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

SSH免密登陸

咱們已經掌握如何使用ssh登陸遠程服務器了,可是每次登陸都要輸入密碼,比較麻煩。ssh提供一種免密登陸的方式:公鑰登陸。

圖片描述

  1. 在客戶端使用ssh-keygen生成一對密鑰:公鑰+私鑰
  2. 將客戶端公鑰追加到服務端的authorized_key文件中,完成公鑰認證操做
  3. 認證完成後,客戶端向服務端發起登陸請求,並傳遞公鑰到服務端
  4. 服務端檢索authorized_key文件,確認該公鑰是否存在
  5. 若是存在該公鑰,則生成隨機數R,並用公鑰來進行加密,生成公鑰加密字符串pubKey(R)
  6. 將公鑰加密字符串傳遞給客戶端
  7. 客戶端使用私鑰解密公鑰加密字符串,獲得R
  8. 服務端和客戶端通訊時會產生一個會話ID(sessionKey),用MD5R和SessionKey進行加密,生成摘要(即MD5加密字符串)
  9. 客戶端將生成的MD5加密字符串傳給服務端
  10. 服務端一樣生成MD5(R,SessionKey)加密字符串
  11. 若是客戶端傳來的加密字符串等於服務端自身生成的加密字符串,則認證成功
  12. 此時不用輸入密碼,即完成建連,能夠開始遠程執行shell命令了

實現免密登陸

ssh-genkey是生成密鑰的工具,執行完成後生成公鑰和密鑰,這兩個文件會默認保存在~/.ssh/路徑下。經常使用的參數爲:

  • -t: 指定生成密鑰類型(rsa、dsa)。默認爲rsa
  • -f: 指定存放私鑰的文件,公鑰文件名爲私鑰文件名加.pub後綴。默認爲id_rsa
  • -P: 指定passphrase(私鑰的密碼),用於確保私鑰的安全。默認爲空
  • -C: 備註。默認爲user@hostname

咱們直接執行來生成密鑰,全部的參數均可覺得空,也就是一直回車確認:

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/work/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in id_rsa.
Your public key has been saved in id_rsa.pub.
The key fingerprint is:
74:17:74:38:b2:c7:70:fd:1d:33:eb:e2:71:71:cc:11 work@client.com

此時,生成的文件在~/.ssh/目錄下,咱們會看到這些文件:

id_rsa    // 私鑰文件  
id_rsa.pub    // 公鑰文件
authorized_keys    // 存放客戶端公鑰的文件
known_hosts    // 確認過公鑰指紋的可信服務器列表的文件
config    // 指定不一樣域名使用哪一個密鑰的配置文件

由於一臺機器即能是客戶端,又能是服務端,所以同時存在authorized_keys(在該機器爲服務端時使用)和Known_hosts(在該機器爲客戶端時使用)。

咱們的服務器會有不少的用戶,若是全部的用戶都用同一份密鑰,可能就沒辦法劃分權限或者區分用戶,如多個用戶提交git就須要按照用戶名來生成密鑰,用於區分用戶。同時你可能也但願針對不一樣的服務器使用不一樣的密鑰對,所以須要config配置文件來配置針對不一樣服務器的配置:

$vim ~/.ssh/config
Host a.baidu.com
User work
IdentityFile ~/.ssh/id_rsa

Host b.baidu.com
User zhaoshuaiqiang
IdentityFile ~/.ssh/zhaoshuaiqiang

這樣在鏈接不一樣的服務器時,就會使用不一樣的密鑰文件來登陸。

在客戶端生成密鑰對以後,將公鑰追加到服務器的authorized_keys文件中便可。

...
 15 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAn30bjwtkLW82vTlLMQnI/a42J2g7o+HBCpSzBgNG+xfZuSNQOAU8+FNKQvriT4AL7ToiTtrZDLOEGqyQzaxQejuNnWG6aQ9ETh96qXhVLecWidaBieFGuv+F
    uXz6x551xtFXx64AzG+706dhnv1nOACYlrnfvXhi5kZzWzprET+CxMIeYhJQwwc19pF5zCWeU9QUvd1mOu0n8JVycevmuXRdVx9WpXq2+aaaaaaaa3uYGMBxvSLtT40O1AiEZ+k9EeYCnTEV
    tnGoVWCyxpwv6rR/GDOtJL/d+/Wb6I0HEKxxe087yZz8GWpQN5TEIAjq3oEjI/aiGw== work@a.baidu.com
 16 ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzRmK+CAVLnryXqQwweu8Yji8bGAvqzf8PSDzYn1nmE6ZeDkBbrWvFlVZ2yOip3IX8RjvuPc28mTCr0LsIOOmpvET0SzOkt0hzLBPiyCN/QvbKU/RbUv8v5y2
    hEAlbUkMEzv7qOHQEruGEvA5y99gf/nYjK5OFKVpmg838OScUV3i88Xbqk8rtcuRZHWuZLnuB5spBsEE5r1UrnH/Ik7frZr8Vb4X6aZWbAp1yc0SqZ8JXVbmOiakqq0WqkLm+zqhEwr+Ooh2guH23x9zjMqY
    Uy+aaaaaBEBC+LepCvskArBt/SRwJDJkcItz8T7kBC3CP0Y0X4hB+6k6/yM/pup5w== work@b.baidu.com

此時,便可免密登陸服務器。

私鑰的安全性

假設你已經實現了服務器集羣的免密登陸,那麼若是你的一臺客戶端被攻擊成功了,那麼整個集羣的安全性便蕩然無存了。所以,咱們有時還須要對密鑰作安全性保障,即設置私鑰密碼:

// 使用rsa方法加密,生成test密鑰對,私鑰密碼爲123456
ssh-keygen -t rsa -f test -P 123456

此時,各機器仍然是免密登陸,可是須要你輸入私鑰密碼:

$ssh work@a.baidu.com
Enter passphrase for key '/home/work/.ssh/test':

參考資料

  1. RUNOOB-Linux scp命令:http://www.runoob.com/linux/l...
  2. linux-doc scp跨機遠程拷貝:https://linuxtools-rst.readth...
  3. 維基百科 Secure Shell:https://zh.wikipedia.org/wiki...
  4. 簡書 圖解SSH原理:https://www.jianshu.com/p/334...
  5. CSDN scp在linux中實現兩臺主機傳件--互信無需輸入密碼: https://blog.csdn.net/posonri...
相關文章
相關標籤/搜索