- Chứng chỉ SSH giải quyết sự phiền toái của cơ chế xác thực SSH dựa trên khóa công khai truyền thống và cung cấp độ tin cậy tự động giữa client và server
- Được hỗ trợ từ OpenSSH 5.4, CA (tổ chức chứng thực) ký khóa người dùng và khóa host để có thể xác thực mà không cần sửa
authorized_keys
- Chứng chỉ có thể bao gồm thời hạn hiệu lực, người dùng được phép (principal), IP truy cập, lệnh bắt buộc (force-command) v.v. để hỗ trợ kiểm soát truy cập chi tiết
- Loại bỏ quy trình TOFU (Trust on First Use), cho phép kết nối an toàn khi khóa host thay đổi mà không xuất hiện cảnh báo
- Nếu tận dụng máy chủ hoặc công cụ ký tự động, có thể tự động hóa quản lý SSH trong môi trường máy chủ quy mô lớn và nâng cao bảo mật
Tổng quan về chứng chỉ SSH và giới hạn của xác thực SSH dựa trên khóa truyền thống
- Khi kết nối SSH, cần kiểm tra dấu vân tay khóa host (fingerprint) của server truy cập lần đầu; nhưng đa số người dùng không xác minh mà chỉ nhập ‘yes’, tức sử dụng mô hình TOFU (Trust on First Use)
- Quản trị viên có thể tự kiểm tra dấu vân tay của server hoặc xác minh bằng lệnh
ssh-keygen -l -f /etc/ssh/ssh_host_ed25519_key
- Xác thực dựa trên khóa công khai cho phép đăng nhập không cần mật khẩu, nhưng phải phân phối khóa công khai vào file
authorized_keys của từng server
- Dùng SSH agent (
ssh-agent) có thể lưu khóa riêng trong bộ nhớ để xác thực nhiều lần mà không cần nhập lặp lại
- Giới hạn của cách làm cũ
- Cần sao chép khóa công khai lên server cho từng người dùng
- Khi khóa host thay đổi, phía client sẽ xuất hiện thông báo cảnh báo
- Việc quản lý độ tin cậy bất tiện do TOFU
Chứng chỉ SSH và tổ chức chứng thực (CA)
- Chứng chỉ SSH (Certificate) được hỗ trợ từ OpenSSH 5.4 (tháng 3 năm 2010), là cấu trúc mở rộng của định dạng khóa SSH hiện có
- SSH CA được tạo thành từ một cặp khóa SSH, trong đó khóa công khai đóng vai trò gốc tin cậy
- Các ưu điểm chính
- Không cần sửa file
authorized_keys trên server
- Không có cảnh báo khi thay khóa host
- Loại bỏ quy trình TOFU để hiện thực độ tin cậy tự động
- Có thể đưa vào chứng chỉ người dùng được phép (principal), IP được phép, thời hạn hiệu lực, lệnh bắt buộc (force-command) v.v.
- Tự động chặn truy cập khi chứng chỉ hết hạn
Quy trình thiết lập SSH CA và ký
- Trên hệ thống CA, tạo cặp khóa CA bằng thuật toán ECDSA
ssh-keygen -t ecdsa -C "SSH CA" -f CA/ssh-ca
- Người dùng gửi khóa công khai của mình (
*.pub) cho CA, sau đó CA ký (sign) khóa đó để phát hành chứng chỉ (*-cert.pub)
- Ví dụ:
ssh-keygen -s CA/ssh-ca -I "Jane Jolie" -n jane -z 001 -V +1w jane.pub
- Cấu hình server
- Lưu khóa công khai CA vào
/etc/ssh/ssh-ca.pub và thêm thiết lập TrustedUserCAKeys
- Ký khóa host của server bằng CA (
ssh-keygen -h -s CA/ssh-ca ...) rồi đăng ký trong mục HostCertificate
- Cấu hình client
- Thêm một dòng
@cert-authority vào file known_hosts
- Ví dụ:
@cert-authority *.example.com $(cat CA/ssh-ca.pub)
Kết nối và xác minh dựa trên chứng chỉ SSH
- Người dùng đăng nhập bằng chứng chỉ đã ký cùng với khóa riêng (
ssh -i jane -l jane alice.example.com)
- Trong log của server sẽ ghi lại ID, số sê-ri (serial), dấu vân tay CA của chứng chỉ
- Có thể thêm nhiều hostname hoặc IP làm principal trong chứng chỉ
- Nếu cố đăng nhập bằng người dùng không nằm trong principal được chỉ định của chứng chỉ, sẽ xuất hiện lỗi “Certificate invalid: name is not a listed principal”
- Có thể thiết lập lệnh bắt buộc (force-command) hoặc IP được phép (source-address) trong chứng chỉ để kiểm soát truy cập chi tiết
Danh sách kiểm tra và xử lý sự cố
-
Các mục cần kiểm tra phía server
- Thiết lập
TrustedUserCAKeys và sự tồn tại của khóa công khai CA
- Khóa host đã được ký và
HostCertificate đã được chỉ định
- Cần khởi động lại
sshd
-
Các mục cần kiểm tra phía client
- Khóa người dùng phải được CA ký
- Mục
@cert-authority trong known_hosts phải khớp với principal
- Khi chứng chỉ hết hạn sẽ hiện thông báo “Certificate invalid: expired”
- Nếu điều kiện ràng buộc của chứng chỉ không khớp, hệ thống sẽ yêu cầu nhập mật khẩu
- Khi thêm chứng chỉ vào SSH agent thì cả khóa và chứng chỉ đều được đăng ký (
ssh-add jane)
- Có thể dùng tùy chọn (
-O) khi ký để điều khiển chức năng
- Ví dụ: dùng
-O clear để xóa mọi quyền, sau đó chỉ cho phép permit-agent-forwarding, permit-port-forwarding
Tự động hóa chứng chỉ khóa host
- Dùng module Python sshkey-tools và BottlePy để triển khai máy chủ ký tự động (hkbot)
- Chạy
hkbot.py trên server CA, sau đó tự động ký khi tải khóa công khai host lên qua HTTP request
- Trên client, có thể tự động cài đặt bằng lệnh
curl -F hostkey=@/etc/ssh/ssh_host_ed25519_key.pub http://CA:8870 | sh
- Chỉnh sửa
/etc/ssh/sshd_config, kiểm tra rồi áp dụng bằng systemctl restart sshd
- Sau đó khi kết nối SSH, có thể tự động tin cậy và đăng nhập dựa trên chứng chỉ
Tóm tắt ưu điểm của chứng chỉ SSH
- Không cần TOFU, có độ tin cậy tự động giữa client và server
- Có thể cấp chứng chỉ ngắn hạn để kiểm soát truy cập tạm thời
- Tự động chặn truy cập khi chứng chỉ hết hạn, không cần dọn
authorized_keys
- Có thể thiết lập chính sách chi tiết như lệnh bắt buộc, giới hạn PTY, kiểm soát IP truy cập
- Có thể đơn giản hóa quản lý môi trường máy chủ quy mô lớn bằng công cụ tự động hóa
- Giới thiệu dự án liên quan: Smallstep SSH
Tài liệu tham khảo thêm
Cập nhật
- SSH CA đặc biệt hữu ích trong môi trường sở hữu server riêng và có quyền root
- Trong hệ thống nhiều người dùng, cách dùng
known_hosts và authorized_keys truyền thống vẫn cần thiết
- Bản thảo chuẩn hóa định dạng chứng chỉ SSH:
draft-miller-ssh-cert-06
1 bình luận
Ý kiến trên Hacker News
Thật ngạc nhiên là mọi người vẫn còn dùng mật khẩu SSH
Đặc biệt trong môi trường doanh nghiệp lớn, nhiều chính sách mật khẩu chồng chéo khiến ngay cả việc chỉ đăng nhập vào máy chủ cũng mất nhiều thời gian
Vì thế dù có bảo họ dùng khóa bằng ssh-keygen, đa số vẫn chỉ nghĩ “để lúc nào đó làm” rồi cuối cùng không làm
Nhưng ngoài thực tế, rất dễ rơi vào tình trạng quản lý hỗn loạn như dùng một khóa chung cho nhiều máy chủ hoặc chia sẻ khóa cho nhau
Mật khẩu ít nhất có ưu điểm là đơn giản
Không có mật khẩu, nhưng khi đăng nhập phải chạm Yubikey vật lý
Cứ vài tháng lại có người “khám phá” lại chứng chỉ SSH rồi viết blog về nó
Tôi cũng từng viết một bài liên quan từ 15 năm trước, nhưng giờ nhìn lại thì còn thiếu sót
Ngay cả kỹ sư bảo mật đôi khi cũng quên rằng họ đang dùng xác thực bằng khóa chứ không phải chứng chỉ SSH
Việc quản lý thủ công khóa trên nhiều máy chủ quá phiền phức
Giờ tôi đang cân nhắc liệu chuyển đổi lúc này có còn đáng giá không
Cách TOFU(Trust On First Use) đơn giản nhưng đi khá xa
Với các máy chủ của tôi, chỉ cần tự xác minh khóa máy chủ một lần là đủ
Trong môi trường doanh nghiệp lớn, chỉ cần đăng danh sách khóa công khai của các máy chủ nội bộ lên một website nội bộ được ký SSL
Nhưng trong môi trường có quá nhiều máy chủ hoặc thay đổi thường xuyên thì chứng chỉ tốt hơn hẳn, và TOFU có giới hạn ở nhiều mặt
Tôi cũng ước trình duyệt có chức năng thông báo khi khóa TLS của máy chủ thay đổi
Hầu hết chỉ gõ “yes” rồi bỏ qua
Ở công ty, chúng tôi lãng phí cực nhiều thời gian và tiền bạc vì kiểm tra SSL của Zscaler
Mỗi khi hiện lỗi “self-signed certificate in certificate chain” là lại đau đầu
Nó cài chứng chỉ gốc riêng, khóa cứng cấu hình trình duyệt để không thể dùng proxy
Dù sửa file cấu hình của Firefox hay Chrome, nó cũng lập tức ghi đè lại
Thậm chí muốn tắt trong GUI còn phải có mật khẩu của IT
Chỉ khá hơn antivirus Cybereason một chút
Nó phá hỏng toàn bộ các giao thức dựa trên HTTP
Hàng loạt công cụ như Git, RubyGems, go mod, Nix đều bị lỗi
Nhà cung cấp thì bảo là “minh bạch”, nhưng thực tế hoàn toàn không phải vậy
Chẩn đoán vấn đề mất hàng giờ, và đa số quản trị viên không biết mức độ phá hoại của nó
Bài viết chỉ nói đến ưu điểm của chứng chỉ CA, nhưng rõ ràng cũng có nhược điểm
Tôi chưa từng gặp vấn đề bảo mật nào do TOFU gây ra
Nếu chứng chỉ SSH có nhược điểm thì tôi muốn biết cụ thể là gì
Nếu muốn tăng bảo mật thì có thể trao đổi khóa công khai qua kênh an toàn như USB
Dù dùng chứng chỉ thì cuối cùng vẫn phải trải qua quy trình tương tự, chỉ là chủ thể quản lý được chuyển từ người dùng sang quản trị viên
Với tổ chức quy mô lớn, chứng chỉ có thể hữu ích, nhưng mức độ bảo mật nói chung là như nhau
Chỉ cần đưa vào script cài đặt hoặc image triển khai là được
TOFU chỉ có ý nghĩa khi truy cập vào một máy đã được thiết lập sẵn
Trong môi trường dev/stg của chúng tôi, mỗi ngày cài lại một nửa số máy
Nhờ chứng chỉ máy chủ SSH, việc không phải xóa known_hosts hay giữ nguyên khóa trở nên tiện hơn rất nhiều
Tôi đang làm một dự án cá nhân tên là Sshifu
Đây là công cụ giúp đăng nhập bằng chứng chỉ SSH và SSO một cách dễ dàng
Cài sshifu-server trên máy chủ để dùng như CA, rồi cấu hình để từng máy chủ SSH tin CA này
Người dùng chỉ cần đăng nhập bằng lệnh
npx sshifulà xongXem kho GitHub
Trong môi trường vận hành thực tế, truy cập dựa trên chứng chỉ dẫn tới các vấn đề quản lý phức tạp
Nhiều vấn đề phát sinh như chứng chỉ hết hạn, xóa người dùng, hay đăng nhập khi máy chủ gặp sự cố
Userify đã xử lý các vấn đề kiểu này suốt 15 năm, và việc xây dựng hạ tầng xác thực SSH ổn định chưa bao giờ là đơn giản
Tôi đã thêm hỗ trợ chứng chỉ SSH vào pico.sh, và nó rất hữu ích vì có thể triển khai kiểm soát truy cập kiểu RBAC
Xem tài liệu
Trong production, chứng chỉ SSH lại tập trung hóa độ phức tạp và khiến vấn đề lớn hơn
Một CA duy nhất phải luôn sẵn sàng, và nếu gặp sự cố thì toàn bộ truy cập sẽ bị chặn
Còn có nhiều vấn đề thực tế khác như điều chỉnh TTL, quản lý root of trust, khó debug
Cuối cùng mọi người lại đưa cache hoặc agent trở lại
Ngược lại, chúng tôi để mỗi node đồng bộ thông tin người dùng qua HTTPS vào authorized_keys cục bộ
Cách này vẫn giữ được kiểm soát tập trung nhưng sự cố được khoanh vùng cục bộ
Userify hiện dùng cách này, và xử lý không chỉ xác thực mà cả quản lý quyền hạn
Chỉ riêng chứng chỉ thì không giải quyết được các vấn đề như tạo người dùng, vai trò sudo, hay dọn dẹp thư mục home