CentOS 7 下安全配置 SSH (一)

SSH 通常是我們進入新伺服器的第一個應用程式,它也取代了 telnet 和 rsh 成為管理伺服器的最主要介面。儘管 SSH 預設使用加密通訊,登入的密碼和通訊內容都不容易被偷窺,預設的設定大致上安全,可惜由於需要兼顧舊用戶和舊系統,一些過時和不安全的選項仍然被開啟着,在國家級黑客橫行無忌的年代,系統中任何一顆鬆掉的螺絲都會致命,所以我們將會討論如何加強 SSH 的安全性。這一篇只討論基本的安全配置,比較容易理解,過程也比較簡單,對用戶的負面影響也比較少,較進階和較具爭議性的安全配置將會留待下一篇討論。

以下的方法,一部分已經在「安裝 CentOS 7 後必做的七件事」中討論過,不過為了完整起見,我會重複解說 SSH 相關的部分,希望大家包涵,不過內容會比較詳盡,例如會加入對用戶體驗的影響,增加技術討論的篇幅,和比較支持與反對方的意見等等。在該篇文章中與 SSH 無關的部分例如更改 root 密碼等等,將不會重複討論,但他們對系統的安全性同樣重要,請大家不要忽視。

1. 使用第二代通訊協定

SSH 的通訊協定分為第一代和第二代,不用多說第二代有更多功能、選項、和更高的安全性,它是在 2006 正式由 IETF 發表,至今已有十年。由於兩代 SSH 協定並不兼容,我們只能二選其一,CentOS 7 的 SSH 預設使用第二代協定,所以無需做任何設定,但我建議在設定檔中明確寫清楚,開啟 /etc/ssh/sshd_config,尋找:

改為:

跟着輸入以下指令重新啟動 sshd

完成後不要登出系統,使用另一個視窗嘗試用普通帳號 SSH 登入。

2. 不容許空白密碼

其中一個登入 SSH 的方法是輸入帳號名稱和密碼,不過當 CentOS 7 新增一個帳號的時候,可以不設定初始密碼,登入的時候只需輸入帳號名稱,這顯然十分不安全,所以我們應該禁止這類型的帳號登入 SSH,CentOS7 的 SSH 預設禁止這類型的帳號登入,但我建議在設定檔中明確寫清楚,開啟 /etc/ssh/sshd_config,尋找:

改為:

3. 禁止 root 使用 SSH 登入

CentOS 7 的 SSH 預設容許任何帳號登入,包括 root 和普通帳號,為了避免 root 帳號被暴力入侵,我們必須禁止 root 帳號的 SSH 功能,事實上 root 也沒有必要 SSH 登入伺服器,因為只要使用 susudo 指令(當然需要輸入 root 的密碼)普通帳號便可以擁有 root 的權限。開啓 /etc/ssh/sshd_config,尋找:

修改為:

最後輸入以下指令重新啟動 sshd

這樣黑客要取得 root 的權限,必須先破解一個普通用戶帳號,然後再破解 root 的密碼,難度增加了。

完成後不要登出系統,使用另一個視窗嘗試用普通帳號 SSH 登入,退出後再嘗試用 root 帳號 SSH 登入。

這一項設定只會影響需要使用 root 權限工作的人,所以影響的人數十分少,影響也很輕微,但對安全性卻有極大幫助。

4. 使用非常規的 SSH 端口

SSH 預設使用端口(port) 22,這是在 IANA 註冊的官方端口,但沒有人說 SSH 不能使用其他端口,很多黑客專門向伺服器的 22 端口發動攻擊,即使你的伺服器固若金湯、牢不可破,但是要系統日以繼夜接受攻擊,消耗的系統資源(網絡、處理器、記憶體等等)也不會少,何況它是否真的牢不可破還說不定呢!所以有必要讓 SSH 使用其他端口,只讓有權使用 SSH 的用戶知道。

開啓 /etc/ssh/sshd_config,尋找:

修改為:

你可以把 10837 改為任何 102465535 之間的數字,若果怕與某些系統服務發生衝突,可以參考一下這裏

跟著重新啟動 sshd

然後是設定防火牆,CentOS 7 的內核已經有防火牆 netfilter,但你的系統未必安裝了用戶界面,較前版本的 CentOS 預設使用 iptables,但 CentOS 7 開始使用效能更高、穩定性更好的 firewalld。習慣使用 iptables 的管理員仍然可以在 CentOS 7 安裝和使用 iptables,但必須注意 iptablesfirewalld 不能同時運作。

如果伺服器尚未安裝 firewalld,可以使用以下指令安裝,不確定是否已經安裝的話也可以輸入這個指令,它會告訴你已經安裝然後退出。

跟著啟動:

設定 firewalld 的方法有兩個,第一個是修改 firewalld 有關 sshd 的設定,把端口 22 改為 10837,這是正統的做法,但步驟比較多;第二個是要求 firewalld 開啓端口 10837,不指定它屬於哪一個服務(service),這個做法通常處理臨時的端口開啓/封鎖,步驟簡單,但是日後你要是忘記了這個端口為甚麼開啟了呢?什麼時候開啟的呢?為了哪一項服務開啟呢?可能有點麻煩。我兩種方法都會介紹一下,但作為專業的系統管理員(即使不是真正的專業,也應該具備這樣的心態),我推薦使用第 一種方法。

設定防火牆方法一:

複製 firewalld 有關 sshd 的設定檔案:

開啓 /etc/firewalld/services/ssh.xml,尋找:

修改為:

儲存後重新載入 firewalld

設定防火牆方法二:

輸入以下指令:

就是這樣簡單!

不論使用哪種方法,完成後不要登出系統,使用另一個視窗嘗試登入,例如:

不少人對更改 SSH 端口的有效性有異議,主要的反對意見認為鐵了心要駭入你的伺服器的人,不會只嘗試端口 22 後便放棄,一定會掃描所有 65,536 個 TCP 端口(port scanning),編寫一個掃描 TCP 端口的程式很簡單,執行起來也很快速,除非你不使用 SSH,否則一定會被他們找到你使用的端口,然後發動攻擊,所以更改 SSH 端口無助加強安全性。另一方面,用戶每次登入 SSH 都要加上 -p 10837 這個參數,也添加麻煩。

我同意這些論點,更改 SSH 端口無助防止有技術、有決心、有資源的黑客,但是它至少阻擋一些隨意找一個伺服器,然後在端口 22 碰碰運氣的小伙子,別低估這些小伙子的數量,這些十來歲還在讀中學或者大學的小伙子的數量是十分驚人的,而且藉著自動 ip 掃描的程式,他們可以在短時間內掃描大量開啟了端口 22 的伺服器 ,更改 SSH 的端口可以避免成為他們的攻擊對象。總的來說,這是防範低階黑客的有效手段。

更改 SSH 端口的另一個好處,是大幅減少 SSH 日誌(log)的長度,當你用人手翻閱日誌查找不尋常的網絡活動時,便了解它的可貴。一些查閱日誌的工具例如 fail2ban 等也可因此而提升效能。

5. 啟用公鑰驗證

現在只有普通帳號才能透過 SSH 登入伺服器,但是 SSH 提供一個更先進更安全的驗證方法:公鑰驗證法。

首先每一名用戶建立一對加密鑰匙(密鑰和公鑰),密鑰儲存在日常使用的電腦,公鑰則儲存在伺服器,使用 SSH 聯繫到伺服器的時候,電腦會把一些建立連線請求的資料,其中包括帳號名稱和公鑰,並且把部分資料用密鑰製作數碼簽署,一股腦兒送到伺服器,伺服器檢查自己的「公鑰庫」是否包含送來的公鑰,有的話再驗證數碼簽署,成功的話便直接登入伺服器,無需輸入帳號密碼。

第一步在日常使用的電腦上使用 ssh-keygen 指令建立一對加密鑰匙,它會詢問儲存加密鑰匙的檔案名稱,和把鑰匙加密的密碼,檔案名稱使用預設的路徑和名稱便可以:

建立帳號的 RSA 加密鑰匙

這個指令會創造兩個檔案,一個名為 id_rsa,是你的 RSA 密鑰,另一個是 id_rsa.pub,是你的 RSA 公鑰。這兩條鑰匙的預設長度是 2048 bit,安全程度達 112 bit,估計在 2030 年前都不可能暴力破解,可說十分安全(這純碎是數學上的預測,不考慮硬件技術的突破、加密算法研究的突破、硬件瑕疵等因素),如果你不放心,可以使用 -b 參數設定鑰匙的長度,例如:

有些人認為太長的鑰匙拖慢了加密/解密的過程,因而減慢了通訊的速度,那是對加密通訊的無知做成的誤解!公鑰加密法只是用來建立通訊,過程中雙方會協商對稱加密法(例如 AES)的鑰匙,此後 SSH 只會使用對稱加密法來加密通訊的內容。所以公鑰加密法鑰匙長度對速度的影響,只發生在開始的階段,此後的加密/解密的工作都由效能遠遠優勝的對稱加密法負責。

你也可以把加密算法從 RSA 改為更先進、效能更高的橢圓曲線算法(elliptic curve crytography),只要把上面指令中的 rsa 改為 ed25519 便可以了,ed25519 的鑰匙長度固定是 256 bit,安全程度相當於 128 bit,由於長度固定,所以無須使用 -b 指定長度。

公鑰必需上傳到伺服器並且附加於用戶帳號裏面的 ~/.ssh/authorized_keys 檔案中,這個檔案儲存所有可透過 SSH 登入到這一個帳號的公鑰。

SSH 的設定檔 /etc/ssh/sshd_config 中可以使用 PubkeyAuthentication 來啟用/停用公鑰驗證法,沒有設定的話 CentOS 7 的 SSH 預設啟用這個方法,你也可以加入這一行明確啟用它:

如果你有兩台或以上電腦需要使用 SSH 登入伺服器,便要在每一台電腦重複以上步驟,很多懶惰的人把這一對加密鑰匙(公鑰和密鑰)複製到其他電腦,這樣做的確可以從不同的電腦登入伺服器,但卻提高了加密鑰匙被盜取的風險,違反了公鑰驗證的原意。

有些人建議使用公鑰驗證法後,密碼登入的方法便應該停用,因為這是一個比較容易被暴力破解的方法,方法是在設定檔 /etc/ssh/sshd_config 中尋找:

把它改為:

如果你打算只使用公鑰驗證法,這是對的。不過我在下一篇文章將會討論雙重驗證法,即是公鑰驗證法和密碼驗證法同時使用,屆時我們仍然要開啟密碼驗證法,倒不如暫時把它保留著。

在日常使用電腦中的加密鑰匙應該以穩當的密碼保護,必須明白你的電腦並不是絕對安全的,例如你的朋友可能會借你的電腦檢查電郵;當你離開位子上廁所而屏幕保護程式啟動之前,誰人接觸過你的電腦?你的手提電腦也有可能被盜取或遺失,諸如此類的情況多不勝數,倘若你的 SSH 密鑰沒有密碼保護,等於你的伺服器沒有密碼保護。

公鑰驗證法比密碼登入法安全的原因,是用暴力破解公鑰/密鑰近乎不可能,尤其是你使用的 RSA 鑰匙長度達到 2048 bit 或以上,相當於黑客要暴力測試 2^112 個密碼,以現代的電腦技術,即使具備國家級的電腦設備也不可能破解。相反地,暴力破解你的登入密碼便容易得多了,假設你精心挑選了一個 8 個字符,包含大小寫英文字母、數字和標點符號,並且完全隨機產生的密碼,安全性也只有大約 48 bit,相當於黑客要暴力測試 2^48 個密碼,即使是一台桌面電腦也可以輕易做到。

使用公鑰驗證法後,伺服器不容易被暴力入侵,但儲存在桌面電腦或手提電腦內的密鑰又怎麼樣呢?它們的安全性取決於那些電腦的安全性,和保護密鑰的密碼安全性。有些人認為公鑰驗證法只是把風險從伺服器轉移到桌面和手提電腦,安全性沒有提高,某些情況下反而下降了。所以有人提出多重驗證(multi-factor authentication)概念,我們將會在第二部分詳細討論。

6. 限制可登入 SSH 的用戶

審視一下哪些帳號需要使用 SSH 登入伺服器,只讓這些帳號透過 SSH 登入,可以減少被攻擊的和被攻陷的機會。假如伺服器只容許 peter 和 jane 兩個帳號登入,可以在 /etc/ssh/sshd_config 加入:

帳號名稱之間用空白字符分隔,帳號名稱可以使用通配字符 *?,不過我不建議這樣做,因為

  1. 你可能不小心容許了一些不該使用 SSH 的帳號登入。
  2. 將來新增了一些不該使用 SSH,但巧合地匹配這些模式的帳號,讓他們擁有登入 SSH 權限。

跟着輸入以下指令重新啟動 sshd

完成後不要登出系統,嘗試使用 peter 或者 jane 帳號在另一個視窗登入,退出後再嘗試用其他帳號登入。

除了 AllowUsers 之外,也可以使用 DenyUsers 明確拒絕某些帳號登入,例如:

如果伺服器設定了用戶群組,也可以用群組名稱來授權/拒絕 SSH 登入,例如:

7. 停用不需要的驗證方法

CentOS 7 的 SSH 提供九種帳戶驗證方法:

驗證方法

SSH 協定版本

設定檔案中沒有指定時的預設值 CentOS 7 的 SSH 預設值
ChallengeResponseAuthentication 1, 2 yes no
GSSAPIAuthentication 2 no yes
HostbasedAuthentication 2 no no
KbdInteractiveAuthentication 1, 2 yes* no
KerberosAuthentication 1, 2 no no
PasswordAuthentication 1, 2 yes yes
PubkeyAuthentication 2 yes yes
RhostsRSAAuthentication 1 no no
RSAAuthentication 1 no no
* 如果設定檔案沒有指定 KbdInteractiveAuthentication 的值,它將會與 ChallengeResponseAuthentication 的值相同。

啟用不需要的驗證法等於設立一道我們不會使用的門,儘管這道門關著,但它始終是一個安全隱患,所以我們應該只啟用需要的驗證法。

假如你只使用公鑰驗證法,請把所有其他驗證法明確設定為 no,不要依賴 SSH 的預設值。前面第五節已經介紹過公鑰驗證法和啟用它的方法,啟用/停用其他驗證法的方法也差不多,這裡不打算逐一說明。

我建議你最少要啟用公鑰驗證法 (PubkeyAuthentication yes),若果你打算結合密碼驗證法實現多重驗證,可以保留密碼驗證法 (PasswordAuthentication yes),其他驗證法除非真的有需要,否則都應該停用 (例如 GSSAPIAuthentication no)。

若果你不使用外掛驗證模組 (PAM – Pluggable Authentication Module),應該一併停用 PAM,不過如果系統正在運行 SELinux,停用 PAM 而沒有加入適當的 SELinux 規則,會引致不可預知的結果,所以在 SELinux 環境下可以保留使用 PAM。CentOS 7 的 SSH 預設啟用 PAM,需要停用的話可以在 /etc/ssh/sshd_config 中尋找:

改為:

跟着輸入以下指令重新啟動 sshd

一如既往,完成後不要登出系統,嘗試在另一個視窗登入。

總結

以上是比較簡單和容易理解的設定,如果你有任何問題或指正,歡迎在下面迴響中提出和討論。下一篇將討論比較複雜,必較具爭議性,和對用戶體驗有較大影響的設定。

CentOS 7 下安全配置 SSH (一) 有 “ 4 則迴響 ”

    1. 當然有,第二篇已草擬多時,由於篇幅較長,技術細節比較多,加上小弟的工作有比較繁忙,所以一拖再拖,但會於短期內發佈。

    1. 為甚麼要這樣做呢?沒有兩個系統是相同的,所以也不會有一個「萬用設定檔」適合所有系統。優秀的管理員應該理解每一項設定的技術細節,賦予最合乎系統利益的數值,這是我花這麼多功夫寫這兩篇文章的用意。不客氣說句,從網上抄寫拼貼別人的程式、設定檔,不願意花時間精神學習技術內容的,都屬於尸位素餐的管理員。

發表迴響

你的電子郵件位址並不會被公開。