Lịch sử SSH: từ Telnet đến OpenSSH và hậu lượng tử
Năm 1995, vụ nghe lén mật khẩu ở Helsinki đã thúc đẩy SSH. Xem timeline đã kiểm chứng từ Telnet, rlogin đến OpenSSH và mặc định hậu lượng tử.
Lịch sử của SSH bắt đầu từ những mật khẩu bị đánh cắp
Lịch sử của SSH bắt đầu từ những mật khẩu bị đánh cắp. Trước 1995, đăng nhập vào một máy Unix từ xa nghĩa là dùng telnet hoặc rlogin. Cả hai đều gửi mật khẩu qua network dưới dạng văn bản rõ. Bất kỳ ai có thể theo dõi network traffic đều đọc được mật khẩu. Đến đầu những năm 1990, việc này đã diễn ra trên quy mô lớn.
SSH là giải pháp của một người cho vấn đề đó. Nó được viết vào 1995 và phát hành miễn phí. Giao thức này đã được xây dựng lại một lần kể từ đó. Chương trình mà hầu hết mọi người đang chạy hiện nay là một fork của một fork. Các mốc thời gian dưới đây quan trọng vì mỗi bước đều là phản hồi cho một lỗi cụ thể.
Telnet và rlogin thực sự đã gửi gì
Telnet được định nghĩa trong RFC 854, do Jon Postel và Joyce Reynolds công bố vào tháng 5 năm 1983. Telnet mô tả một phiên terminal chạy trên TCP và hoàn toàn không có mã hóa. Mọi byte bạn nhập, kể cả password, đều được truyền dưới dạng byte thuần mà bất kỳ thiết bị nào trên đường truyền cũng có thể đọc.
rlogin xuất phát từ Berkeley Unix và được mô tả sau đó trong RFC 1282 (BSD Rlogin, B. Kantor, tháng 12 năm 1991). Nó bổ sung một thứ còn nguy hiểm hơn password dạng rõ: cơ chế tin cậy dựa trên host. Server có thể được cấu hình để chấp nhận login từ một host được chỉ định mà không cần password. RFC này có một phần mang tên "A Cautionary Tale", trong đó viết rằng: "Bỏ qua xác thực bằng password đối với các host được tin cậy sẽ mở quyền truy cập vào TẤT CẢ hệ thống được cấu hình như vậy khi chỉ một hệ thống bị xâm nhập." RFC cũng lưu ý rằng cơ chế tin cậy dựa trên hostname, nên việc DNS (domain name system) bị xâm nhập hoặc địa chỉ bị giả mạo có thể vô hiệu hóa cơ chế này.
Cả hai thiết kế đều phù hợp với mạng nơi chúng ra đời. Ethernet thời kỳ đầu là môi trường dùng chung: mọi máy trong cùng một segment đều nhận được mọi frame và được kỳ vọng sẽ bỏ qua những frame không gửi đến mình. Khi một máy ngừng bỏ qua các frame đó, tức chuyển sang promiscuous mode, nó có thể thấy traffic của mọi máy khác. Nếu một trường đại học cấp shell account cho hàng nghìn sinh viên, chỉ một account bị xâm nhập cũng có thể trở thành công cụ thu thập password của cả một khoa.
Khuyến cáo năm 1994 không có bản sửa lỗi
Ngày 3 tháng 2 năm 1994, CERT công bố khuyến cáo CA-94:01, “Các cuộc tấn công giám sát mạng đang diễn ra”. Khuyến cáo cho biết kẻ xâm nhập đã thu thập thông tin truy cập của hàng chục nghìn hệ thống trên Internet. Công cụ được sử dụng đã đưa network interface vào promiscuous mode và ghi lại phần mở đầu của mọi phiên telnet, rlogin và FTP mới. Phần này chứa username và password.
CERT khuyến cáo các site thay đổi password của mọi account có thể truy cập qua mạng. Nếu đối chiếu khuyến cáo này với cách các protocol hoạt động, vấn đề sẽ rất rõ: lần đầu password mới được sử dụng, nó vẫn truyền qua cùng đường mạng dưới dạng clear text. Không thể sửa lỗi này bên trong telnet hoặc rlogin, vì cả hai protocol đều không có chỗ để triển khai cơ chế bảo vệ đó.
Vì sao một cuộc tấn công nghe lén ở Helsinki tạo ra SSH
Năm 1995, mạng tại Đại học Công nghệ Helsinki hứng chịu một cuộc tấn công nghe lén mật khẩu đúng kiểu mà CERT đã mô tả. Tatu Ylönen, một nhà nghiên cứu tại đó, đã viết một phần mềm thay thế và phát hành dưới dạng freeware vào tháng 7 năm 1995. Ông đặt tên cho nó là Secure Shell.
Hai quyết định thiết kế đã làm nên nền tảng của nó. Phiên làm việc được mã hóa, nên một kẻ nghe lén trên segment không thu được thông tin hữu ích. Server xác thực danh tính bằng key, nên client có thể biết mình đã kết nối đúng máy hay chưa. Đây chính là lỗ hổng mà cơ chế tin cậy hostname của rlogin để lại.
SSH cũng lan rộng vì các command của nó khớp với những command người dùng đã quen gõ. ssh thay cho rsh và rlogin, còn scp thay cho rcp. Việc chuyển sang SSH chỉ thay đổi thói quen, không thay đổi workflow. Đến cuối năm 1995, cộng đồng người dùng đã đạt khoảng 20,000 người tại năm mươi quốc gia. Tháng 12 năm đó, Ylönen thành lập SSH Communications Security để phát triển và bán phần mềm.
Từ một bản phát hành miễn phí đến sản phẩm thương mại
Khi SSH trở thành một hoạt động kinh doanh, giấy phép của mã nguồn đã thay đổi. Các bản phát hành sau đó kèm theo những điều khoản hạn chế việc người khác có thể làm với mã nguồn, và bản phát hành cuối cùng mà mọi người có thể tự do sử dụng lại là ssh 1.2.12. Điều đó không có gì sai. Nó chỉ có nghĩa là phiên bản SSH mà phần còn lại của thế giới có thể tiếp tục xây dựng dựa trên đó đã ngừng được phát triển, trong khi quá trình phát triển vẫn tiếp tục ở nơi mà thế giới đó không thể theo kịp. Giấy phép quyết định mã nguồn nào được duy trì, một xu hướng đáng tìm hiểu trong cách giấy phép mã nguồn mở định hình hạ tầng hiện đại.
Vì sao OpenBSD fork OpenSSH vào năm 1999
Đầu năm 1999, Björn Grönvall quay lại bản release miễn phí cuối cùng đó và bắt đầu sửa lỗi. Phiên bản của ông có tên OSSH và chỉ hỗ trợ protocol SSH 1.3.
Project OpenBSD tiếp nhận OSSH và xây dựng lại nó. Theo ghi chép của chính project, Theo de Raadt, Niels Provos, Markus Friedl, Bob Beck, Aaron Campbell và Dug Song đã làm công việc làm sạch, audit và mở rộng code. Kết quả là OpenSSH 1.2.2, được phát hành cùng OpenBSD 2.6 vào ngày 1 tháng 12 năm 1999.
Vì sao một fork do một project operating system nhỏ thực hiện lại xuất hiện trên gần như mọi máy? Vì những gì OpenBSD cần ở nó. OpenBSD phát hành một base system đã được audit, được thiết kế để an toàn với cấu hình mặc định. Vì vậy, remote login được mã hóa phải nằm trong base system đó và sử dụng một licence không kèm hạn chế. Code đã được audit dưới một licence không hạn chế chính là thứ mọi vendor operating system khác cũng cần. Damien Miller, Philip Hands và những người khác gần như ngay lập tức bắt đầu một portable branch. Đây là nguồn gốc của p trong một version như 10.5p1. OpenBSD phát triển phiên bản clean, còn portable branch bổ sung phần glue cho mọi môi trường khác. Cách Unix tách thành các system mà chúng ta sử dụng ngày nay là lý do phần glue đó cần thiết.
Hỗ trợ protocol version thứ hai được bổ sung sau đó. OpenSSH 2.0 được phát hành cùng OpenBSD 2.7 vào ngày 15 tháng 6 năm 2000.
Vì sao SSH-2 là một protocol mới thay vì chỉ tăng số phiên bản
SSH-1 bảo vệ tính toàn vẹn của encrypted stream bằng CRC-32, một checksum được thiết kế để phát hiện lỗi truyền dữ liệu thay vì chống lại attacker. Năm 1998, Ariel Futoransky và Emiliano Kargieman của CORE SDI đã chỉ ra hậu quả. Khi dùng cipher mode CBC hoặc CFB cùng kiểm tra CRC-32, attacker chỉ cần biết ít nhất 16 byte plaintext là có thể chèn ciphertext do mình chọn, khiến phía nhận chấp nhận dữ liệu đó là hợp lệ. Điều này cho phép chạy command trên server.
Lỗ hổng nằm trong protocol nên không thể sửa mà vẫn giữ compatibility. Thay vào đó, các implementation được phát hành kèm một detector: đoạn code trong file có tên deattack.c, cố gắng nhận diện cuộc tấn công ngay khi nó xảy ra. Tháng 2 năm 2001, detector này được phát hiện có một integer overflow riêng, CVE-2001-0144. Lỗ hổng cho phép remote code execution trên các server và client đã cài patch. Một thiết kế không thể sửa triệt để sẽ tích lũy các patch, và chính những patch đó lại mang theo bug mới.
SSH-2 được xây dựng trong một IETF working group có tên secsh và được công bố dưới dạng RFC vào tháng 1 năm 2006: kiến trúc trong RFC 4251, transport layer trong RFC 4253, user authentication trong RFC 4252 và connection layer trong RFC 4254. Việc chia thành các layer là phần quan trọng, vì mỗi layer sau đó có thể được thay thế độc lập. Phần lớn lịch sử sau đó là quá trình thay thế này.
Có 2 thay đổi nổi bật. Tính toàn vẹn được chuyển từ CRC-32 sang HMAC (hash-based message authentication code), dùng shared secret làm key. Vì vậy, attacker không thể giả mạo packet nếu không tính được MAC. Cơ chế key agreement cũng chuyển sang Diffie-Hellman. Trong SSH-1, client chọn session key rồi gửi key đó sau khi mã hóa bằng RSA key của server. Vì vậy, bất kỳ ai lấy được các private key đó sau này đều có thể giải mã session đã ghi lại. Diffie-Hellman tạo ra một secret mới cho mỗi session và secret này không bao giờ được truyền đi. Do đó, việc ghi lại traffic rồi lấy được host key sau này cũng không mang lại dữ liệu gì. Tính chất này được gọi là forward secrecy.
SSH-2 không có wire compatibility với SSH-1. Vì vậy, số protocol được thay đổi thay vì chỉ tăng số thập phân.
Vì sao SSH-1 bị loại bỏ thay vì sửa lỗi
Việc loại bỏ diễn ra qua ba bản phát hành OpenSSH. Phiên bản 7.0, vào ngày 11 August 2015, tắt protocol 1 theo mặc định ngay khi biên dịch. Phiên bản 7.4, vào ngày 19 December 2016, loại bỏ hỗ trợ protocol này trên server. Phiên bản 7.6, vào ngày 3 October 2017, tiếp tục xóa phần client cùng các tùy chọn cấu hình và tài liệu liên quan.
Giữ protocol này dưới dạng tùy chọn cho thiết bị cũ sẽ dễ sử dụng hơn, nhưng detector CRC-32 giải thích vì sao lựa chọn đó bị từ chối. Có thể khai thác lỗi tràn chỉ vì code của protocol 1 vẫn được biên dịch, dù code này nằm trong một nhánh mà hầu hết quản trị viên tin là không được sử dụng trên hệ thống của họ. Code đã được phát hành vẫn có thể bị truy cập. Code đã bị xóa thì không thể.
Vì sao kết nối SSH đầu tiên cảnh báo về host key
Mã hóa cho biết network traffic được giữ riêng tư. Nó không cho biết ai đang ở đầu bên kia. Nếu kẻ tấn công nằm trên đường truyền và trả lời thay cho server của bạn, bạn sẽ có một phiên được mã hóa hoàn toàn với kẻ tấn công. Đây là kiểu tấn công machine-in-the-middle. SSH xử lý việc này bằng host key: server chứng minh rằng nó đang giữ phần private của một key pair, còn client kiểm tra key đó với giá trị đã ghi nhận lần trước. Nếu muốn tìm hiểu cơ chế của chính kết nối này, hãy xem điều gì xảy ra khi bạn mở một kết nối SSH.
Ở lần kết nối đầu tiên không có lần trước, nên client không có gì để so sánh và phải hỏi bạn:
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])?Trả lời yes sẽ lưu key đó vào ~/.ssh/known_hosts. Ở mọi lần kết nối sau, client sẽ so sánh với giá trị đã lưu. Nếu không khớp, chương trình sẽ hiển thị cảnh báo nghiêm trọng nhất:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!Cách hiểu chính xác về prompt đầu tiên là protocol đang thừa nhận điểm yếu duy nhất của nó. Trust on first use nghĩa là kết nối đầu tiên chỉ an toàn ở mức độ của network mà bạn dùng để kết nối. Bạn có thể loại bỏ khoảng trống này. Hãy đọc fingerprint từ console của nhà cung cấp hoặc build log của server trước khi kết nối. Bạn cũng có thể publish fingerprint trong DNS dưới dạng bản ghi SSHFP (RFC 4255), nhưng chỉ nên làm vậy khi đã có DNSSEC. Hoặc ký host key bằng certificate authority (CA) của riêng bạn để client trust CA thay vì từng key riêng lẻ. Trên thực tế, phần lớn mọi người chấp nhận prompt mà không kiểm tra. Cần thẳng thắn thừa nhận điều đó.
Khóa công khai đã thay thế password như thế nào
Xác thực bằng khóa công khai đã có từ những bản phát hành SSH đầu tiên, nhưng vẫn mất nhiều năm mới trở thành cách dùng thông thường. Cơ chế này bất đối xứng: client chứng minh mình giữ private key bằng cách ký một challenge, còn private key không bao giờ rời khỏi client. Password thì ngược lại. Dù SSH truyền password bên trong encrypted channel, server vẫn nhận được secret thực tế. Vì vậy, nếu server bị breach hoặc do kẻ xấu kiểm soát, kẻ đó sẽ giữ được thông tin có thể tái sử dụng để tấn công bạn ở nơi khác.
Lý do thứ hai là bài toán xác suất. Bất kỳ server nào mở port 22 trên một public address đều nhận các lần thử đăng nhập tự động suốt ngày đêm, và password là một chuỗi có thể đoán được. Key không thể bị đoán theo bất kỳ cách thực tế nào. Thiết lập PasswordAuthentication no loại bỏ toàn bộ nhóm tấn công này. Vì vậy, thiết lập này luôn có mặt trong mọi hardening checklist. Cách tạo và rotation key được trình bày trong Kiến thức cơ bản về quản lý SSH key, còn các thiết lập phía server nằm trong hardening SSH trên VPS.
Danh sách thuật toán SSH liên tục thay đổi
Giao thức phân lớp cho phép loại bỏ thuật toán mà không cần tạo giao thức mới. OpenSSH đã tận dụng khả năng này một cách đều đặn, và các mốc phát hành cho thấy tốc độ thay đổi.
Ed25519 xuất hiện trong OpenSSH 6.5 vào ngày 30 January 2014, cùng với cipher chacha20-poly1305 và định dạng private key được bảo vệ bằng bcrypt. Chữ ký Ed25519 tạo nonce cho từng chữ ký theo cách xác định, nên bộ tạo số ngẫu nhiên yếu tại thời điểm ký không thể làm lộ private key. Đây chính xác là cách private key DSA và ECDSA đã bị khôi phục trong các sự cố thực tế.
DSA đi theo hướng ngược lại. OpenSSH 7.0 vô hiệu hóa ssh-dss host key và user key trong lúc chạy vào năm 2015, vì thuật toán này bị giới hạn ở private key 160-bit và SHA-1. Version 9.8, vào ngày 1 July 2024, vô hiệu hóa DSA tại thời điểm biên dịch. Version 10.0, vào ngày 9 April 2025, loại bỏ DSA, theo cách diễn đạt của dự án là "hoàn tất quá trình loại bỏ bắt đầu từ năm 2015". Mười năm từ lúc bị vô hiệu hóa đến khi bị xóa.
RSA không biến mất, nhưng định dạng chữ ký cũ của nó thì có. OpenSSH 8.8, vào ngày 26 September 2021, mặc định ngừng chấp nhận chữ ký RSA được tạo bằng SHA-1. Ghi chú phát hành nêu rõ lý do: SHA-1 đã bị phá vỡ về mặt mật mã, và có thể tạo collision với chosen-prefix với chi phí dưới 50,000 USD. Nếu bạn từng gặp sign_and_send_pubkey: no mutual signature supported khi kết nối đến một server cũ, đó chính là thay đổi này. Key của bạn vẫn hợp lệ. Thuật toán chữ ký mà đầu bên kia yêu cầu thì không.
Quy trình tương tự hiện đang áp dụng cho key exchange, lần này được thực hiện trước khi mối đe dọa xuất hiện. Lưu lượng được ghi lại hôm nay có thể được lưu trữ rồi giải mã nhiều năm sau bởi bên đầu tiên sở hữu máy tính lượng tử đủ khả năng, nên cơ chế thỏa thuận key phải thay đổi trước khi máy như vậy tồn tại. OpenSSH 9.0, vào ngày 8 April 2022, đặt hybrid key exchange làm mặc định: sntrup761x25519-sha512@openssh.com kết hợp một thuật toán hậu lượng tử với cơ chế trao đổi X25519, nên kết quả không yếu hơn phần cổ điển nếu thuật toán mới không đáp ứng được kỳ vọng. OpenSSH 9.9, vào ngày 19 September 2024, bổ sung mlkem768x25519-sha256, được xây dựng trên ML-KEM (module lattice key encapsulation mechanism), do NIST chuẩn hóa vào năm 2024. OpenSSH 10.0 đặt thuật toán này làm mặc định cho key agreement, và trang hậu lượng tử của dự án giải thích lý do. OpenSSH 10.1, vào ngày 6 October 2025, bắt đầu cảnh báo khi đầu bên kia không hỗ trợ thuật toán này:
** 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.Cảnh báo này được bật mặc định và được điều khiển bằng tùy chọn WarnWeakCrypto trong ssh_config. Ý nghĩa thực tế của cảnh báo và cách xử lý server kích hoạt cảnh báo được trình bày trong các mặc định mới cho key exchange SSH hậu lượng tử.
Lịch sử này có ý nghĩa gì đối với server trước mặt bạn
Lệnh bạn gõ hầu như không thay đổi kể từ năm 1995. Gần như mọi thành phần bên dưới đã được thay thế: kiểm tra tính toàn vẹn, trao đổi key, các thuật toán chữ ký và chính code base. Điều đó chỉ có thể thực hiện được vì mỗi lần thay thế đều kết thúc bằng việc chủ động loại bỏ thành phần cũ, và mỗi lần loại bỏ đều làm hỏng một thứ gì đó đối với một số người dùng.
Vì vậy, bảo mật SSH của bạn phần lớn được quyết định bởi phiên bản đang dùng. Các thiết lập mặc định chứa sẵn quyết định về những thuật toán được cung cấp, những thuật toán bị từ chối và các cảnh báo bạn nhìn thấy. Một server cũ vẫn tiếp tục cung cấp bất kỳ thuật toán nào mà bản release của nó còn cho phép, đồng thời tiếp tục hạ mức thương lượng để tương thích với client cũ. Tính đến August 2026, bản release hiện tại là OpenSSH 10.5, được phát hành vào 11 August 2026. Khoảng cách giữa phiên bản này và phiên bản trên một máy đã không được ai chạm đến trong ba năm chính là mức độ của vấn đề. Kiểm tra phiên bản thuộc mười phút đầu tiên khi thiết lập một VPS mới.
FAQ
Ai đã tạo ra SSH và vì sao?
Tatu Ylönen, một nhà nghiên cứu tại Đại học Công nghệ Helsinki, đã viết SSH vào năm 1995 sau một cuộc tấn công sniffing mật khẩu trên mạng của trường. Các công cụ đăng nhập từ xa thời đó, telnet và rlogin, gửi mật khẩu qua mạng dưới dạng văn bản có thể đọc được. Vì vậy, bất kỳ ai monitor một segment dùng chung đều có thể thu thập thông tin xác thực khi chúng đi qua. Ông phát hành chương trình dưới dạng freeware vào tháng 7 năm 1995. Đến cuối năm đó, chương trình có khoảng 20,000 người dùng tại 50 quốc gia. Tháng 12 năm 1995, ông thành lập SSH Communications Security.
SSH-1 và SSH-2 khác nhau thế nào?
Đây là 2 protocol khác nhau và không tương thích trên wire. SSH-1 là một protocol đơn khối, dùng CRC-32 để kiểm tra tính toàn vẹn và yêu cầu client gửi session key được mã hóa bằng RSA key của server. SSH-2 chia chức năng thành transport layer, authentication layer và connection layer (RFC 4251 đến 4254, tháng 1 năm 2006). SSH-2 dùng HMAC để kiểm tra tính toàn vẹn và tạo session key bằng Diffie-Hellman. Vì vậy, traffic đã ghi lại vẫn được bảo mật ngay cả khi host key bị đánh cắp về sau. SSH-1 bị loại khỏi OpenSSH theo từng giai đoạn, kết thúc ở version 7.6 vào tháng 10 năm 2017.
Vì sao OpenSSH thay thế implementation SSH ban đầu?
Quá trình phát triển implementation ban đầu chuyển thành một sản phẩm thương mại với licence hạn chế. Release cuối cùng có thể tái sử dụng tự do là ssh 1.2.12. Đầu năm 1999, Björn Grönvall khôi phục release đó thành OSSH. Sau đó, team OpenBSD fork OSSH thành OpenSSH. OpenSSH được phát hành cùng OpenBSD 2.6 vào ngày 1 tháng 12 năm 1999. OpenBSD cần code đã được audit với licence không hạn chế cho base system. Hai đặc điểm này cho phép mọi hệ điều hành khác sử dụng cùng implementation thông qua portable branch.
Vì sao SSH hỏi về host key trong lần đầu tôi kết nối?
Vì client chưa từng thấy server đó và không có key nào để đối chiếu. Chỉ mã hóa thôi không thể phân biệt server hợp lệ với một máy đang nằm giữa đường truyền. Vì vậy, SSH nhận diện server bằng key và ghi lại thông tin đã nhận được trong ~/.ssh/known_hosts. Kết nối đầu tiên là thời điểm duy nhất không có giá trị đã lưu để kiểm tra. Vì thế client yêu cầu bạn xác nhận. Hãy so sánh fingerprint với fingerprint lấy từ console của provider hoặc trực tiếp từ server. Hãy coi mọi message REMOTE HOST IDENTIFICATION HAS CHANGED về sau là một sự kiện thực sự cho đến khi bạn giải thích được nguyên nhân.
Vì sao các SSH key cũ ngừng hoạt động sau khi upgrade?
Vì OpenSSH loại bỏ các algorithm theo một schedule đã công bố. Key DSA (ssh-dss) bị disable mặc định trong OpenSSH 7.0 vào năm 2015 và bị remove hoàn toàn trong OpenSSH 10.0 vào ngày 9 tháng 4 năm 2025. RSA key vẫn hoạt động, nhưng chữ ký dùng SHA-1 bị disable mặc định trong OpenSSH 8.8 vào tháng 9 năm 2021. Khi bạn kết nối đến server cũ, lỗi này xuất hiện dưới dạng sign_and_send_pubkey: no mutual signature supported. Ed25519 key, có từ OpenSSH 6.5 vào tháng 1 năm 2014, tránh được cả 2 vấn đề này.