ssh的理解和使用

ls ~/.ssh/            
config   id_rsa    id_rsa.pub   known_hosts   test.crt   test.key   testenc.key

SSH

SSH 爲 Secure Shell 的縮寫,由 IETF 的網絡小組( Network Working Group)所制定;SSH 爲創建在應用層基礎上的安全協議。SSH 是目前較可靠,專爲遠程登陸會話和其餘網絡服務提供安全性的協議。利用 SSH 協議能夠有效防止遠程管理過程當中的信息泄露問題。SSH最初是UNIX系統上的一個程序,後來又迅速擴展到其餘操做平臺。 SSH在正確使用時可彌補網絡中的漏洞。SSH客戶端適用於多種平臺。幾乎全部 UNIX平臺—包括 HP-UX、Linux、AIX、Solaris、Digital UNIX、Irix,以及其餘平臺,均可運行SSH。

SSH只是一種協議,存在多種實現,既有商業實現,也有開源實現。本文針對的實現是OpenSSH,它是自由軟件,應用很是普遍。SSH在Linux Shell中的用法。若是要在Windows系統中使用SSH,會用到另外一種軟件PuTTYhtml

基本的用法

SSH主要用於遠程登陸。假定你要以用戶名user,登陸遠程主機host,只要一條簡單命令就能夠了。linux

$ ssh user@host

若是本地用戶名與遠程用戶名一致,登陸時能夠省略用戶名。git

$ ssh host

SSH的默認端口是22,也就是說,你的登陸請求會送進遠程主機的22端口。使用p參數,能夠修改這個端口。github

$ ssh -p 2222 user@host

上面這條命令表示,ssh直接鏈接遠程主機的2222端口。算法

鏈接方式

SSH之因此可以保證安全,緣由在於它採用了公鑰加密。shell

整個過程是這樣的:ubuntu

  1. 遠程主機收到用戶的登陸請求,把本身的公鑰發給用戶。
  2. 用戶使用這個公鑰,將登陸密碼加密後,發送回來。
  3. 遠程主機用本身的私鑰,解密登陸密碼,若是密碼正確,就贊成用戶登陸。

安全隱患

上面所述的 SSH登入過程自己是安全的,可是實施的時候存在一個風險:若是有人截獲了登陸請求,而後冒充遠程主機,將僞造的公鑰發給用戶,那麼用戶很難辨別真僞。由於不像https協議,SSH協議的公鑰是沒有證書中心(CA)公證的,也就是說,都是本身簽發的。安全

能夠設想,若是攻擊者插在用戶與遠程主機之間(好比在公共的wifi區域),用僞造的公鑰,獲取用戶的登陸密碼。再用這個密碼登陸遠程主機,那麼SSH的安全機制就蕩然無存了。這種風險就是著名的"中間人攻擊"Man-in-the-middle attack)。服務器

第一次登入

爲了應對上述的中間人攻擊,在用戶第一次登陸對方主機,系統會出現下面的提示:網絡

$ ssh user@host

  The authenticity of host 'host (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)?

這段話的意思是,沒法確認host主機的真實性,只知道它的公鑰指紋,問你還想繼續鏈接嗎?

所謂"公鑰指紋",是指公鑰長度較長(這裏採用RSA算法,長達1024位),很難比對,因此對其進行MD5計算,將它變成一個128位的指紋。上例中是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)? yes

系統會出現一句提示,表示host主機已經獲得承認。

Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.

而後,會要求輸入密碼。

Password: (enter password)

若是密碼正確,就能夠登陸了。

當遠程主機的公鑰被接受之後,它就會被保存在文件$HOME/.ssh/known_hosts之中。下次再鏈接這臺主機,系統就會認出它的公鑰已經保存在本地了,從而跳過警告部分,直接提示輸入密碼。

每一個SSH用戶都有本身的known_hosts文件,此外系統也有一個這樣的文件,一般是/etc/ssh/ssh_known_hosts,保存一些對全部用戶均可信賴的遠程主機的公鑰。

config配置

在經過known_hosts的記錄遠程主機的公鑰可信度以後,每次登錄都須要書寫一堆 登錄命令 ,爲了簡而書寫,能夠經過config文件來進行配置,配置前咱們登錄:

ssh username@hostname -p port

而後輸入密碼;在創建配置文件,touch ~/.ssh/config配置後,咱們只須要輸入鏈接帳戶的別名便可

ssh 別名

配置方法:

在.ssh/config中配置,若是沒有config,建立一個便可,而後將下面的(別名,主機名,端口,用戶名替換便可),端口若是默認22能夠不要,刪除那行便可。
Host 別名
    Hostname 主機名
    Port 端口
    User 用戶名
    IdentifyFile 指定的私鑰地址

配置好以後,就能夠直接ssh 別名鏈接了,不須要輸入一長串,可是仍是有一個問題,就是仍是須要輸入密碼。解決辦法就是將咱們的公鑰拷貝到鏈接的機器上來免密登錄就能夠了【config文件中的字段IdentifyFile就是制定了和公鑰配對的私鑰,已達到免密登入的便捷】。

免密登入【公鑰登陸】

使用密碼登陸,每次都必須輸入密碼,很是麻煩。好在SSH還提供了公鑰登陸,能夠省去輸入密碼的步驟。

所謂"公鑰登陸",原理很簡單,就是用戶將本身的公鑰儲存在遠程主機上。登陸的時候,遠程主機會向用戶發送一段隨機字符串,用戶用本身的私鑰加密後,再發回來。遠程主機用事先儲存的公鑰進行解密,若是成功,就證實用戶是可信的,直接容許登陸shell,再也不要求密碼。

這種方法要求用戶必須提供本身的公鑰。若是沒有現成的,能夠直接用ssh-keygen生成一個:

$ ssh-keygen

運行上面的命令之後,系統會出現一系列提示,能夠一路回車。其中有一個問題是,要不要對私鑰設置口令(passphrase),若是擔憂私鑰的安全,這裏能夠設置一個。

運行結束之後,在$HOME/.ssh/目錄下,會新生成兩個文件:id_rsa.pubid_rsa。前者是你的公鑰,後者是你的私鑰。

這時再輸入下面的命令,將公鑰傳送到遠程主機host上面:

$ ssh-copy-id user@host

好了,今後你再登陸,就不須要輸入密碼了【ssh-copy-id這個命令可能有問題,ssh-copy-id可能的問題】。

若是仍是不行,就打開遠程主機的/etc/ssh/sshd_config這個文件,檢查下面幾行前面"#"註釋是否取掉。

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys

而後,重啓遠程主機的ssh服務。

  // ubuntu系統
  service ssh restart

  // debian系統
  /etc/init.d/ssh restart

authorized_keys文件

遠程主機將用戶的公鑰,保存在登陸後的用戶主目錄的$HOME/.ssh/authorized_keys文件中。公鑰就是一段字符串,只要把它追加在authorized_keys文件的末尾就好了。

這裏不使用上面的ssh-copy-id命令,改用下面的命令,解釋公鑰的保存過程:

$ ssh user@host 'mkdir -p .ssh && chmod 700 ~/.ssh && cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub

這條命令由多個語句組成,依次分解開來看:

  1. "$ ssh user@host",表示登陸遠程主機;
  2. 單引號中的mkdir .ssh && cat >> .ssh/authorized_keys,表示登陸後在遠程shell上執行的命令:
  3. "$ mkdir -p .ssh"的做用是,若是用戶主目錄中的.ssh目錄不存在,就建立一個;
  4. 'cat >> .ssh/authorized_keys' < ~/.ssh/id_rsa.pub的做用是,將本地的公鑰文件~/.ssh/id_rsa.pub,重定向追加到遠程文件authorized_keys的末尾【須要注意, .ssh/authorized_keys這個文件可能沒有,執行touch .ssh/authorized_keys,有了authorized_keys以後,權限可能須要修改,chmod 640 ~/.ssh/authorized_keys,而後纔是把公鑰追加進去】。
最好把權限設置上
$ chmod 600 ~/.ssh/authorized_keys
$ chmod 700 ~/.ssh

寫入authorized_keys文件後,公鑰登陸的設置就完成了。

跳板機登入

在不少時候,咱們的本地機器是沒法直接訪問遠程主機的,而是經過跳板機來完成的,A是本地機器,B是跳板機,C是線上機器。

+-----+             +-----+             +-----+
|     |             |     |             |     |
|  A  +-----------> |  B  +-----------> |  C  |
|     |             |     |             |     |
+-----+             +-----+             +-----+

而在這種過程中,咱們不得不輸入兩次密碼【可能密碼還不同】,不管是scp獲取文件仍是登入都變得繁瑣,爲了可以直接A->C

+-----+             +-----+             +-----+ 
|     |             |     |             |     | 
|  A  +-------------------------------> |  C  |
|     |             |     |             |     | 
+-----+             +-----+             +-----+

這就是經過「ProxyCommand」選項,機器A可以靈活使用任意代理機制與機器C上的SSH Server端口創建鏈接,接着機器A上的SSH Client再與該鏈接進行數據交互,從而機器A上的SSH Client與機器C上的SSH Server之間創建了與通常「直接SSH鏈接」不太同樣的「間接SSH鏈接」。不過因爲「間接SSH鏈接」的透明性,邏輯上可認爲機器A上的SSH Client與機器C上的SSH Server創建了「直接SSH鏈接」。

clipboard.png

本機、跳板機、目標機器三者已經作過公鑰認證(若是不作密鑰認證就會提示分別輸入跳板機和目標機器的密碼,須要多輸入兩次密碼比較繁瑣);下面的案例前提都是咱們能夠免密登入跳板機;

$ mkdir -p ~/.ssh/persist
$ scp 用戶名@跳板機:~/.ssh/id_rsa ~/.ssh/id_rsa.cn6  #拷貝跳板機的密鑰到本地,不一樣的跳板機能夠起不一樣的名字,好比id_rsa.cn8
# 能夠是刪除跳板機上的祕鑰對設置的密碼,從新生成無密碼祕鑰對,也能夠跳過這一步。
$ cd .ssh
$ ssh-keygen -p
Enter file in which the key is : id_rsa.cn6 # 輸入剛纔的拷貝的密鑰文件名
Enter old passphrase: # 輸入passphrase
Key has comment 'id_rsa.cn6'
Enter new passphrase (empty for no passphrase): # 直接回車
Enter same passphrase again: # 直接回車
Your identification has been saved with the new passphrase.

方案都是使用ssh ProxyCommand:

ProxyCommand ssh proxyserver -W [%h]:%p

ProxyCommand ssh proxyserver nc -q0 %h %p 2> /dev/null

ProxyCommand ssh proxyserver exec nc -q0 %h %p 2> /dev/null

%h[host]和%p[port]被SSH客戶端替換以指示預期目的地,ProxyCommand基本思路:SSH能夠調用外部應用程序,指望它與目標主機創建鏈接。創建鏈接後,應用程序必須使用stdin / stdout公開鏈接。

代理機制一"ssh -W" mode

ProxyCommand選項值形式爲[OpenSSH 5.3以上才支持]

ssh -W C:CPort -l USER -i PRIVATE_KEY -p BPort B

原理:ssh命令自提供的代理機制,在機器A上另外單獨創建與B的SSH鏈接(使用-l USER -i PRIVATE_KEY -p BPort B這些參數),並在B端創建端口映射監聽終端信息,然後B端與機器C上的SSH Server端口(即「C:CPort」)創建ssh鏈接,在C上創建端口映射監聽終端信息,並在C端發起和B端的其餘連接【tcp/socket】,將C端的標準輸入輸入映射到B端,供B和A的ssh鏈接使用。

假定A上ssh_config配置文件內容以下:

Host B
    HostName %h
    User dsl
    Port 1046
    IdentityFile ~/.ssh/id_rsa.cn6

Host C
    HostName %h
    User dsl 
    Port 1046
    IdentityFile ~/.ssh/id_rsa.cn6
    ProxyCommand ssh -W %h:%p B

在A上執行ssh C命令,發現A與C成功創建SSH鏈接。根據以上所述,A機器經過ssh鏈接了B機器,而後B機器連接C機器,同時,須要C機器經過鏈接在stdin/stdout上與B創建通訊,而後將通訊結果返回給A。

常使用代理製劑二netcat

在最開始的時候,-W參數尚未引入,可使用nc實現【因此兩個很相似,之是方式略有不一樣,特別是B端和C端的nc的連接是由B端發起的,而不是C端發起】,ProxyCommand選項值形式爲

nc -X 5 -x B:BPort C CPort
ProxyCommand nc %h %p

原理:利用nc | netcat命令,在登陸代理機器B後,B機器須要經過nc創建和機器C的連接,經過鏈接在stdin/stdout上與C創建通訊後,而後將通訊結果返回給A。

假定A上ssh_config配置文件內容以下:

Host B
    HostName %h
    User dsl
    Port 1046
    IdentityFile ~/.ssh/id_rsa.cn6
Host C
    HostName %h
    User dsl 
    Port 1046
    IdentityFile ~/.ssh/id_rsa.cn6
    ProxyCommand ssh B exec nc %h %p 2> /dev/null

全文參考:
SSH原理與運用,
proxycommand
支持跳板機間接連接線上機,
SSH穿越跳板機:一條命令跨越跳板機直接登錄遠程計算機
使用SSH ProxyCommand 配置跳板機登陸生產環境機器
ssh 如何快速免密碼登陸服務器
What is the difference between ssh proxycommand -W, nc, exec nc
如何透過 SSH 代理穿越跳板機
Netcat with SSH Port Forwarding

相關文章
相關標籤/搜索