SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-09-11

SSH 歷史:從 telnet、rlogin 到 OpenSSH

1995 年赫爾辛基的密碼嗅探攻擊促成 SSH。本文整理從 telnet、rlogin 到 OpenSSH 與後量子預設值的可驗證時間軸。

SSH 的歷史起點

SSH 的歷史始於密碼遭竊。在 1995 年以前,登入遠端 Unix 機器通常使用 telnet 或 rlogin,而這兩者都會將密碼以可讀文字傳送到網路上。任何能監看網路傳輸的人都能讀取密碼;到了 1990 年代初期,確實有人大規模進行這類攻擊。

SSH 是一個人為了解決這個問題,在 1995 年撰寫並免費提供的方案。此後,該協定曾重新設計一次,而如今幾乎所有人使用的程式,都是某個分支的分支。以下日期很重要,因為每個步驟都是針對特定故障所提出的回應。

telnet 與 rlogin 實際傳送的內容

Telnet 定義於 RFC 854,由 Jon Postel 與 Joyce Reynolds 於 1983 年 5 月發布。它描述透過 TCP 傳輸的終端機工作階段,完全沒有任何加密。你輸入的每個位元組,包括密碼在內,都會以純文字位元組傳送,路徑上的任何裝置都能讀取。

rlogin 源自 Berkeley Unix,之後記載於 RFC 1282(BSD Rlogin,B. Kantor,1991 年 12 月)。它加入了比可讀取的密碼更嚴重的功能:以主機為基礎的信任。伺服器可以設定為接受來自指定主機的登入,完全不要求密碼。RFC 中有一節名為「警示故事」,其中指出:「略過來自受信任主機的密碼驗證後,只要其中一台主機遭到入侵,所有採用此設定的系統都會暴露。」該文件也指出,這項信任是以主機名稱為依據,因此 DNS(domain name system)遭到入侵或位址遭到偽造時,就能繞過這項機制。

這兩種設計都適合其誕生時的網路環境。早期的 Ethernet 是共享媒介:區段上的每台機器都會收到每個 frame,並預期忽略未傳送給自己的 frame。若某台機器停止忽略這些 frame,也就是進入 promiscuous mode,就能看到其他所有機器的網路流量。再加上大學向數千名學生提供 shell 帳號,只要一個帳號遭到入侵,就可能成為收集整個系所密碼的工具。

1994 年發布但沒有修補程式的公告

1994 年 2 月 3 日,CERT 發布公告 CA-94:01〈持續進行的網路監控攻擊〉。公告指出,入侵者已取得網際網路上數萬個系統的存取資訊。他們使用的工具會將網路介面設為 promiscuous mode,並記錄每個新 telnet、rlogin 與 FTP 工作階段的開頭部分;其中包含使用者名稱與密碼。

CERT 建議各網站變更所有可透過網路存取之帳戶的密碼。將這項建議放回這些通訊協定的運作方式來看,問題很明顯:新密碼在首次使用時,仍會透過同一條網路以明文傳送。telnet 或 rlogin 本身沒有可用的修補方式,因為這兩種通訊協定都沒有可放置修補機制的位置。

為何赫爾辛基的嗅探攻擊促成了 SSH

1995 年,赫爾辛基科技大學的網路遭到 CERT 所描述類型的密碼嗅探攻擊。當時任職於該校的研究人員 Tatu Ylönen 撰寫了替代方案,並在 1995 年 7 月以免費軟體形式發布。他將其命名為 Secure Shell。

這套方案依靠兩項設計決策。工作階段會加密,因此在網段上監聽的攻擊者無法取得有用資訊。伺服器則使用金鑰證明身分,因此用戶端可以確認是否連線到正確的機器;這正是 rlogin 的主機名稱信任機制所留下的漏洞。

它也因為命令符合使用者原本已輸入的命令而快速普及。ssh 取代了 rshrloginscp 取代了 rcp。切換所需改變的是使用習慣,而不是工作流程。到 1995 年底,使用者已遍及 50 個國家,總數約達 20,000 人。同年 12 月,Ylönen 創立 SSH Communications Security,著手開發並銷售這套軟體。

從免費發布版本到商業產品

隨著 SSH 成為一項商業業務,原始碼的授權條款也隨之變更。後續版本加入了限制他人使用程式碼方式的條款,而任何人都能自由重複使用的最後一個版本是 ssh 1.2.12。這本身並無不當之處。這只代表世界其他地方能以此為基礎建置的 SSH 版本不再持續更新,而開發工作仍在外界無法跟進的地方繼續進行。授權條款決定哪些程式碼能夠延續,這種模式值得參閱開放原始碼授權如何形塑現代基礎架構

OpenBSD 為何在 1999 年分支出 OpenSSH

1999 年初,Björn Grönvall 回頭採用最後一個免費版本,開始修正其中的錯誤。他的版本稱為 OSSH,且只支援 SSH 1.3 協定。

OpenBSD 專案採用了 OSSH,並重新建置它。根據該專案自己的說明,Theo de Raadt、Niels Provos、Markus Friedl、Bob Beck、Aaron Campbell 與 Dug Song 負責清理、稽核及擴充程式碼。成果是 OpenSSH 1.2.2,並於 1999 年 12 月 1 日隨 OpenBSD 2.6 發布。

為何一個小型作業系統專案的分支,最後會出現在幾乎每台機器上?原因在於 OpenBSD 對它的需求。OpenBSD 提供經過稽核的基礎系統,目標是在預設設定下保持安全。因此,加密遠端登入功能必須納入基礎系統,並採用不附帶限制的授權。其他作業系統廠商同樣需要經過稽核且採用不受限制授權的程式碼。Damien Miller、Philip Hands 等人幾乎立即開始開發可移植分支,這就是像 10.5p1 這類版本中的 p 來源。OpenBSD 開發乾淨的版本,可移植分支則為其他環境加入必要的整合程式碼。Unix 分裂成今日所使用各種系統的過程,正是這些整合程式碼存在的原因。

之後加入了對第 2 版協定的支援。OpenSSH 2.0 於 2000 年 6 月 15 日隨 OpenBSD 2.7 發布。

為何 SSH-2 是新協定,而不是版本遞增

SSH-1 使用 CRC-32 保護加密串流的完整性。CRC-32 的設計目的是偵測傳輸錯誤,而不是抵禦攻擊者。1998 年,CORE SDI 的 Ariel Futoransky 和 Emiliano Kargieman 證明了這項設計的代價。在 CBC 或 CFB 密碼模式搭配 CRC-32 檢查時,攻擊者只要知道明文中少至 16 bytes 的內容,就能插入接收端會當成真實資料接受的自選密文,這表示攻擊者可以在伺服器上執行命令。

這項缺陷存在於協定本身,因此無法修正而不破壞相容性。實作改為加入偵測器。這段程式碼位於名為 deattack.c 的檔案中,會嘗試在攻擊發生時辨識攻擊。2001 年 2 月,該偵測器被發現本身含有整數溢位漏洞 CVE-2001-0144。這讓攻擊者能夠對包含該修補程式的伺服器和用戶端進行遠端程式碼執行。無法修復的設計會不斷累積修補程式,而修補程式也會帶來自己的錯誤。

SSH-2 由名為 secsh 的 IETF 工作小組制定,並於 2006 年 1 月以 RFC 形式發布:架構定義於 RFC 4251,傳輸層定義於 RFC 4253,使用者驗證定義於 RFC 4252,連線層定義於 RFC 4254。分層是其中的關鍵,因為每一層都能單獨替換。這段歷史的其餘部分,大多就是這些替換逐步發生的過程。

其中有兩項變更特別重要。完整性保護從 CRC-32 改為使用共享秘密金鑰的 HMAC(雜湊式訊息驗證碼),因此無法計算 MAC 的攻擊者就無法偽造封包。金鑰協商也改用 Diffie-Hellman。在 SSH-1 中,用戶端選擇工作階段金鑰,並使用伺服器的 RSA 金鑰加密後傳送。因此,任何日後取得這些私密金鑰的人,都能解密已記錄的工作階段。Diffie-Hellman 會為每個工作階段產生新的秘密,且不會傳送該秘密。因此,即使現在記錄網路流量,日後再竊取主機金鑰,也無法取得任何資訊。這項特性稱為前向保密。

SSH-2 與 SSH-1 不具備任何線路相容性。因此變更的是協定編號,而不是小數版本。

為何移除 SSH-1,而不是修復它

移除 SSH-1 歷經三個 OpenSSH 版本。7.0 版本於 2015 年 8 月 11 日在編譯時預設停用 protocol 1。7.4 版本於 2016 年 12 月 19 日移除伺服器端支援。7.6 版本則於 2017 年 10 月 3 日連用戶端部分一併刪除,包括相關設定選項與文件。

為舊設備保留選用功能會是較友善的做法,但 CRC-32 偵測器說明了為何拒絕這項選擇。只有在編譯時納入 protocol 1 程式碼,才能觸及這個溢位問題;而這段程式碼位於大多數系統管理員認為已停用的執行路徑中。已發布的程式碼就可能被觸及。刪除的程式碼則無法被觸及。

為什麼第一次 SSH 連線會警告主機金鑰

加密表示網路流量是私密的,但無法證明連線另一端的身分。如果攻擊者位於傳輸路徑中,並代替伺服器回應,您仍會與攻擊者建立完全加密的工作階段。這稱為中間人攻擊。SSH 以主機金鑰處理這個問題:伺服器證明自己持有金鑰組中的私密金鑰,而用戶端會將該金鑰與上次記錄的內容比對。若要了解連線本身的運作方式,請參閱開啟 SSH 連線時會發生什麼事

第一次連線時沒有上次的記錄。因此,用戶端沒有可供比對的內容,必須詢問您:

The authenticity of host 'vps.example.com (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:BQ0Qs2jVXhH2lPZ2rM0aQ0mQ8f9pQ0m3nH0oQ1bYqkE.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?

回答 yes 會將該金鑰儲存在 ~/.ssh/known_hosts。之後每次連線都會與儲存的值比對。若不一致,程式會顯示最嚴重的警告訊息:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!

第一次提示的正確解讀是:通訊協定承認第一次連線是唯一較脆弱的時刻。首次使用時信任表示,第一次連線的安全性取決於建立連線時所使用的網路。您可以降低這項風險。連線前,先從服務供應商的主控台或伺服器的建置日誌讀取指紋。也可以依 RFC 4255 將指紋發布為 DNS 中的 SSHFP 記錄,但只有在使用 DNSSEC 時才值得這麼做。另一種方式是使用您自己的憑證授權單位(CA)簽署主機金鑰,讓用戶端信任 CA,而不是逐一信任每個金鑰。實務上,多數人會未經查核便接受提示,這點應該如實看待。

公鑰如何取代密碼

公鑰驗證從早期 SSH 版本就已存在,但多年後才成為一般做法。這項機制採用非對稱方式:用戶端透過簽署 challenge,證明自己持有私鑰,而私鑰不會離開用戶端。密碼的情況則相反。即使 SSH 將密碼放在加密通道中傳送,伺服器仍會收到實際的 secret。因此,遭入侵或具惡意的伺服器,最終會持有可在其他地方冒用的憑證。

第二個原因是計算能力。任何在公開位址開放 22 埠的伺服器,都會全天候收到自動化登入嘗試,而密碼是可以猜測的字串。公鑰在實務上無法被猜出。設定 PasswordAuthentication no 可消除整類攻擊,因此會出現在每份伺服器強化檢查清單中。這也會移除過去在公鑰發生問題時可用的備援方式。因此,在真正被鎖在伺服器外之前,請先學會分辨所有會回報 Permission denied (publickey) 的不同故障。不使用密碼也代表需要累積多把金鑰;持有十幾把金鑰的 agent 會依序提供每一把,直到伺服器達到嘗試次數上限並中斷連線。這就是即使已載入正確金鑰,登入仍可能因 Too many authentication failures 而失敗的原因。金鑰的產生與輪替請參閱SSH 金鑰管理基礎,伺服器端設定請參閱強化 VPS 上的 SSH

SSH 演算法清單為何持續變動

分層式協定可在不建立新協定的情況下淘汰演算法。OpenSSH 持續運用這項彈性,從各版本的發布日期即可看出變動速度。

Ed25519 隨 OpenSSH 6.5 於 30 January 2014 引入,同時加入 chacha20-poly1305 cipher,以及由 bcrypt 保護的 private key format。Ed25519 signature 會以確定性方式產生每次簽章使用的 nonce,因此簽章當下即使 random number generator 不安全,也不會洩漏 private key。DSA 和 ECDSA private key 在實際事件中遭到復原,正是因為這類問題。

DSA 則走向另一條路。OpenSSH 7.0 於 2015 在執行期間停用 ssh-dss host 和 user key,因為該演算法的 private key 受限於 160-bit,且只能使用 SHA-1。Version 9.8 於 1 July 2024 在編譯期間停用 DSA。Version 10.0 於 9 April 2025 移除 DSA,並以該專案的說法「完成始於 2015 年的淘汰程序」。從停用到刪除,共經過十年。

RSA 並未消失,但舊的 signature format 已遭淘汰。OpenSSH 8.8 於 26 September 2021 起,預設不再接受使用 SHA-1 產生的 RSA signature。發布說明明確指出原因:SHA-1 在密碼學上已遭破解,而且產生 chosen-prefix collision 的成本已低於 USD 50,000。如果你曾在連線至舊伺服器時遇到 sign_and_send_pubkey: no mutual signature supported,那就是這項變更。你的 key 沒有問題。問題在於對端要求使用的 signature algorithm。

相同的程序目前也套用至 key exchange,而且這次是在威脅成形前提前處理。今天擷取的 network traffic,可能在多年後由最先取得實用 quantum computer 的人儲存並解密。因此,key agreement 必須在這類機器出現前完成變更。OpenSSH 9.0 於 8 April 2022 將 hybrid key exchange 設為預設值:sntrup761x25519-sha512@openssh.com 將 post-quantum algorithm 與 X25519 exchange 配對,因此即使新演算法表現不佳,結果也不會比 classical part 更弱。OpenSSH 9.9 於 19 September 2024 加入 mlkem768x25519-sha256,其基礎為 ML-KEM(module lattice key encapsulation mechanism),並由 NIST 於 2024 標準化。OpenSSH 10.0 將其設為 key agreement 的預設值,該專案的 post-quantum 頁面說明了相關理由。OpenSSH 10.1 於 6 October 2025 起,在對端無法使用此功能時開始顯示警告:

** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded.

此警告預設啟用,並由 WarnWeakCrypto 中的 ssh_config 選項控制。其實際意義,以及如何處理觸發此警告的伺服器,請參閱post-quantum SSH key exchange 預設值

這段歷史對眼前伺服器的意義

自 1995 年以來,你輸入的指令幾乎沒有改變。但底層幾乎都已經替換:完整性檢查、金鑰交換、簽章演算法,以及程式碼本身。這之所以可行,是因為每次替換最後都會刻意移除舊功能,而每次移除都會導致部分使用者或系統出現問題。

因此,SSH 的安全性主要取決於版本。預設值決定提供哪些演算法、拒絕哪些演算法,以及顯示哪些警告。舊版伺服器會持續提供其版本仍允許的項目,也會為了配合舊版用戶端而持續協商降級。截至 2026 年 8 月,目前版本為 OpenSSH 10.5,發布日期為 2026 年 8 月 11 日。這個版本與一台三年來無人維護的機器所使用版本之間的差距,就是問題的規模。確認版本應列入新 VPS 上線後的前 10 分鐘檢查事項

FAQ

SSH 是誰建立的?為什麼?

Helsinki University of Technology 研究人員 Tatu Ylönen 在 1995 年建立 SSH,起因是該大學網路遭到密碼側錄攻擊。當時的遠端登入工具 telnet 和 rlogin 會以可讀文字在網路上傳送密碼,因此任何監控共享網段的人都能在憑證傳輸時收集這些資訊。他在 1995 年 7 月以免費軟體形式發布該程式。同年年底,該程式約有 20,000 名使用者,分布於五十個國家;1995 年 12 月,他成立 SSH Communications Security。

SSH-1 與 SSH-2 有何差異?

兩者是不同的協定,線路格式彼此不相容。SSH-1 是單一整合式協定,使用 CRC-32 確保完整性,並由用戶端將工作階段金鑰以伺服器的 RSA 金鑰加密後傳送。SSH-2 將功能分為傳輸層、驗證層與連線層(RFCs 4251 至 4254,2006 年 1 月),使用 HMAC 確保完整性,並以 Diffie-Hellman 衍生工作階段金鑰。因此,即使之後主機金鑰遭竊,被記錄的網路流量仍維持私密。SSH-1 分階段退出 OpenSSH,最後一個支援版本是 2017 年 10 月的 7.6。

OpenSSH 為何取代原始 SSH 實作?

原始 SSH 的開發後來轉為商業產品,並採用限制較多的授權;最後一個可自由重複使用的版本是 ssh 1.2.12。1999 年初,Björn Grönvall 將該版本重新開發為 OSSH,OpenBSD 團隊再從 OSSH 分支出 OpenSSH;OpenSSH 隨 OpenBSD 2.6 於 1999 年 12 月 1 日發布。OpenBSD 需要經過稽核且採用不受限制授權的程式碼,才能納入其基礎系統。這兩項特性也讓其他作業系統能透過 portable 分支發布相同的實作。

SSH 為何在我第一次連線時詢問主機金鑰?

因為用戶端從未看過該伺服器,也沒有任何金鑰可供比對。單靠加密無法區分真實伺服器與位於連線路徑中間的主機,因此 SSH 會以金鑰識別伺服器,並將看到的內容記錄在 ~/.ssh/known_hosts。第一次連線時沒有已儲存的值可供檢查,所以用戶端會改為詢問你。請將指紋與從供應商主控台或伺服器本身取得的指紋比對。之後若出現 REMOTE HOST IDENTIFICATION HAS CHANGED 訊息,在能夠說明原因前,都應視為真實的安全事件。

為何升級後較舊的 SSH 金鑰會停止運作?

因為 OpenSSH 會依照已公布的時程淘汰演算法。DSA(ssh-dss)金鑰在 2015 年的 OpenSSH 7.0 中預設停用,並在 2025 年 4 月 9 日的 OpenSSH 10.0 中完全移除。RSA 金鑰仍可使用,但 OpenSSH 8.8 在 2021 年 9 月預設停用以 SHA-1 產生的簽章;連線至舊伺服器時,這通常會顯示為 sign_and_send_pubkey: no mutual signature supported。Ed25519 金鑰自 2014 年 1 月的 OpenSSH 6.5 起即可使用,可避開這兩項問題。