我們經常用的SSH,原來是這樣的

前言

在實際日常運維工作中,肯定是離不開SSH的,每天都在不停的使用SSH登陸這個主機,或者那個主機去處理各種問題。每天用的也很舒服,但是對於SSH後面的原理卻不甚瞭解,最近在看Ansible時,發現自己對SSH還有很多的迷惑點,對於我來說,一般不常用的迷惑點,我也就糊弄糊弄就過去了,畢竟對每個知識點進行放大,那都是一本學不完的天書,有些內容我們瞭解就好了,但是對於SSH,本想着也糊弄糊弄就過去吧,但是後來發現這樣行不通,這裏面好多的知識點直接影響着我日後的運維工作。於是乎,覺的有必要整理這樣的一篇文章來把SSH的原理好好的學習一下,也好讓後續自己的運維工作更得心應手,又或在教小弟時也能有點資本。

SSH是什麼?

簡單一點來說,SSH就是一種網絡協議,用於在網絡主機之間進行加密的一種協議。結合我們的日常工作來說,如果我從一臺服務器使用SSH協議登陸另一臺服務器,我們就認爲這樣的登陸是安全的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被泄露。

爲什麼要搞這麼個協議呢?其實,很久很久以前,互聯網通信都是明文的,一旦在中間環節被某些中間商截獲了,我們的通信內容就暴漏無疑。所以呢,芬蘭就有這麼一位叫做Tatu Ylonen的人設計了SSH協議,將信息加密,這樣就像上面說的,即使我們的登陸信息在中間被人截獲了,我們的密碼也不會被泄露。目前SSH協議已經在全世界廣泛被使用,且已經在成爲各個Linux發行版的標配。

原理解析

至於SSH的一些簡單用法,我這裏就不細說了,先通過一副時序圖看看SSH的密碼登陸原理。

從上圖中,可以看到我們使用SSH進行登陸時,主要分爲以下幾步:

  1. 用戶使用ssh user@host命令對遠程主機發起登陸;

  2. 遠程主機將自己的公鑰返回給請求主機;

  3. 請求主機使用公鑰對用戶輸入的密碼進行加密;

  4. 請求主機將加密後的密碼發送給遠程主機;

  5. 遠程主機使用私鑰對密碼進行解密;

  6. 最後,遠程主機判斷解密後的密碼是否與用戶密碼一致,一致就同意登陸,否則反之。

這個過程乍一看沒有任何問題,但是在實際工作中,卻是存在風險漏洞的。由於SSH不像https協議那樣,SSH協議的公鑰是沒有證書中心(CA)公證的,也就是說,都是自己簽發的。這就導致如果有人截獲了登陸請求,然後冒充遠程主機,將僞造的公鑰發給用戶,那麼用戶很難辨別真僞,用戶再通過僞造的公鑰加密密碼,再發送給冒充主機,此時冒充的主機就可以獲取用戶的登陸密碼了,那麼SSH的安全機制就蕩然無存了,這也就是我們常說的中間人攻擊。

既然存在這種問題,SSH就想了一個辦法來繞開這個問題,也就是我接下來要總結的known_hosts文件的作用。

known_hosts文件的作用

我們在使用SSH登陸遠程主機的時候,有時會看到這樣的提示:

The authenticity of host '192.168.1.4 (192.168.1.4)' can't be established.
ECDSA key fingerprint is SHA256:YMLLk0vyfeoY4rbRTnkMSxY11arS2S4qgVgvnwWpBFw.
ECDSA key fingerprint is MD5:82:75:be:8e:e7:26:ea:18:73:aa:fc:10:44:c8:4f:c3.
Are you sure you want to continue connecting (yes/no)?

上面這段話的意思是,無法確認192.168.1.4主機的真實性,只知道它的公鑰指紋,問你還想繼續連接嗎?這樣我們就可以看到,SSH是將這個問題拋給了SSH使用者,讓SSH使用者自己來確定是否相信遠程主機。但是這樣對於用戶來說,就存在一個難題,用戶怎麼知道遠程主機的公鑰指紋是多少;這的確是一個問題,此時就需要遠程主機必須公開自己的公鑰指紋,以便用戶自行覈對。

在經過用戶的風險衡量以後,用戶只需要輸入yes來決定接受這個遠程主機的公鑰。緊接着,系統會出現以下這樣的一句提示,表示遠程主機已經得到認可:

Warning: Permanently added '192.168.1.4' (ECDSA) to the list of known hosts.

接下來,用戶輸入遠程主機密碼即可完成整個登陸。那這個和我這裏要總結的known_hosts文件有什麼關係呢?請聽我慢慢道來。

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

但是由於known_hosts這個機制的存在,也會引起一些問題,比如遠程主機的重新裝操作系統了,遠程主機就會重新生成公鑰,如果我們再登陸遠程主機時,由於我們本地的known_hosts文件中記錄了原來的公鑰,此時就會提示指紋認證失敗的錯誤,這個時候我們只需要刪除本地的known_hosts文件即可。又比如,我們經常會寫一些自動化的腳本,會自動的登陸到遠程主機上去,但是這個known_hosts機制卻必須要我們手動輸入yes才能完成遠程登陸,這樣整個自動化登陸就無法完成了,但是我們可以通過修改/etc/ssh/ssh_config配置文件,跳過這個known_hosts的詢問機制,將# StrictHostKeyChecking ask修改爲StrictHostKeyChecking no即可。

公鑰免密登錄

在我們日常工作中,總是會掛很多的自動化腳本,比如自動的登陸到一臺遠程主機上進行一些操作,又比如Ansible就可以配置自動登陸到遠程主機,但是上面說到的SSH,都需要密碼登陸,那如何讓SSH免密登陸,實現我們的自動登陸需求呢?這就是這裏要將的公鑰免密登陸。

上圖就是SSh免密登陸原理圖,從上圖可以看出,SSH免密登陸的前提是使用ssh-keygen -t RSA生成公私祕鑰對,然後通過ssh-copy-id -i ~/.ssh/id_rsa.pub user@host命令將公鑰分發至遠程主機。接下來的每次免密登陸步驟如下:

  1. 用戶使用ssh user@host命令對遠程主機發起登陸;

  2. 遠程主機對用戶返回一個隨機串;

  3. 用戶所在主機使用私鑰對這個隨機串進行加密,並將加密的隨機串返回至遠程主機;

  4. 遠程主機使用分發過來的公鑰對加密隨機串進行解密;

  5. 如果解密成功,就證明用戶的登陸信息是正確的,則允許登陸;否則反之。

通過ssh-copy-id -i ~/.ssh/id_rsa.pub user@host命令分發的公鑰都會被保存至遠程主機的~/.ssh/authorized_keys文件中。

總結

雖然我們經常使用SSH,但是對於其中的一些原理性的東西卻不是很懂,很多時候就是因爲這些簡單的原理性的不懂,就讓我們的思維受限,讓我們的行動受限,因爲不懂,所以就怕操作,怕出錯。這篇文章就對SSH中的一些原理進行了總結,對於我們經常接觸的東西,比如known_hosts啊、SSH免密登陸啊,這些我們平常只知道用,卻不知道爲什麼是這樣子,在出現問題時,不知道爲什麼,只知道谷歌、百度好用;我希望通過我的這篇文章,能讓各位有緣的讀者明白、熟悉這些簡單的原理,讓大家在日後的工作中因爲懂,所以更放的開。好了,如果覺的還不錯,可以點擊下方的“在看”哦。

書籍推薦


人生是個圓,有的人走了一輩子也沒有走出命運畫出的圓圈,其實,圓上的每一個點都有一條騰飛的切線。

玩代碼、玩技術

長按識別二維碼,關注“果凍想”

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章