Sổ tay kỹ thuật

SSH certificate với CA – ssh-keygen -s, TrustedUserCAKeys, principals, host cert

how-to#ssh#pki#linux#security· cập nhật 2026-11-06

Dùng khi số server/người dùng lớn và không muốn phát tán authorized_keys hay known_hosts nữa, chuyển sang SSH certificate ngắn hạn do CA nội bộ ký.

Sửa trang này
Mục lục

Tóm tắt: Tạo hai CA key (user CA và host CA). Ký public key của user bằng ssh-keygen -s user_ca -I <id> -n <principals> -V +8h; server tin user CA qua TrustedUserCAKeys và giới hạn principal bằng AuthorizedPrincipalsFile. Ký host key bằng -h; client tin host CA bằng dòng @cert-authority trong known_hosts. Thu hồi bằng KRL (RevokedKeys). Cấu hình sshd nền tảng xem SSH hardening.

Luồng hoạt động

flowchart LR U["User: id_ed25519.pub"] -->|"gửi public key"| CA["User CA (ssh-keygen -s)"] CA -->|"id_ed25519-cert.pub (8h, principals)"| U U -->|"ssh: key + cert"| S["sshd"] S --> T{"Ký bởi TrustedUserCAKeys?"} T -->|"có, còn hạn, không bị revoke"| P{"Principal có trong file của user đích?"} P -->|có| OK[Đăng nhập] P -->|không| NO[Từ chối] T -->|không| NO

So với authorized_keys:

authorized_keys SSH certificate
Thêm người mới Sửa file trên mọi server Ký cert, server không đổi
Hết quyền Xoá key khỏi mọi server Cert tự hết hạn (TTL ngắn)
Host key TOFU, cảnh báo khi đổi host key Client tin host CA, không hỏi fingerprint
Ràng buộc from=, command= trong từng dòng Trong cert: principal, thời hạn, source-address, force-command

Cấu hình

Tạo CA (trên máy CA, tách khỏi server thường)

ssh-keygen -t ed25519 -f user_ca -C "user-ca@example.com"   # đặt passphrase
ssh-keygen -t ed25519 -f host_ca -C "host-ca@example.com"

Ai có user_ca (private) thì đăng nhập được mọi server tin CA đó. Giữ offline/HSM hoặc dùng CA có quản lý (Vault SSH secrets engine, step-ca). Chỉ user_ca.pub và host_ca.pub được phát đi.

Ký cert cho user

ssh-keygen -s user_ca -I "alice@example.com-2026-11-06" -n alice,netops -V +8h id_ed25519.pub
# -> tạo id_ed25519-cert.pub cạnh key, ssh client tự dùng
ssh-keygen -L -f id_ed25519-cert.pub      # xem Key ID, Serial, Valid, Principals, Extensions
Tuỳ chọn Ý nghĩa
-I <key_id> Danh tính ghi vào log sshd, đặt dễ truy vết (email + ngày)
-n alice,netops Principals: tên user hoặc "vai trò" mà cert được dùng
-V +8h, -V -5m:+1d Thời hạn (lùi 5 phút để tránh lệch đồng hồ)
-z 1042 Serial, dùng khi thu hồi theo serial
-O source-address=198.51.100.0/24 Chỉ dùng được từ dải này
-O force-command="/usr/local/bin/backup" Cert chỉ chạy được một lệnh
-O no-port-forwarding, -O no-agent-forwarding Bỏ extension tương ứng

Server tin user CA

/etc/ssh/sshd_config.d/20-ca.conf
TrustedUserCAKeys /etc/ssh/user_ca.pub
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
RevokedKeys /etc/ssh/revoked.krl
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
sudo install -d -m 755 /etc/ssh/auth_principals
echo netops | sudo tee /etc/ssh/auth_principals/deploy   # ai có principal "netops" được vào user deploy
echo alice  | sudo tee /etc/ssh/auth_principals/alice
sudo ssh-keygen -k -f /etc/ssh/revoked.krl                 # KRL rỗng, tránh sshd từ chối mọi key vì thiếu file
sudo sshd -t && sudo systemctl reload ssh

Không có AuthorizedPrincipalsFile thì sshd yêu cầu tên user đích nằm trong principals của cert. Có file thì chỉ principal liệt kê trong file mới hợp lệ, nhờ đó map vai trò → user.

Host certificate

# Ký host key của server (chạy trên máy CA, sau khi lấy ssh_host_ed25519_key.pub về)
ssh-keygen -s host_ca -I bastion01 -h -n bastion01.example.com,203.0.113.30 -V +52w ssh_host_ed25519_key.pub
~/.ssh/known_hosts (client) hoặc /etc/ssh/ssh_known_hosts
@cert-authority *.example.com,203.0.113.* ssh-ed25519 <nội-dung-host_ca.pub>

Principals của host cert phải khớp đúng tên/IP mà client gõ. Kết hợp ProxyJump xem SSH config và jump host.

Thu hồi

ssh-keygen -k -u -f /etc/ssh/revoked.krl alice-cert.pub      # thu hồi một cert/key (-u: cập nhật KRL có sẵn)
printf 'serial: 1042\n' > revoke.txt
ssh-keygen -k -u -s user_ca.pub -f /etc/ssh/revoked.krl revoke.txt   # thu hồi theo serial của CA
ssh-keygen -Q -f /etc/ssh/revoked.krl alice-cert.pub         # kiểm tra: in REVOKED, exit 1

Phân phối KRL tới mọi server (Ansible), sshd đọc lại file theo từng kết nối, không cần reload.

Lỗi thường gặp

Triệu chứng Nguyên nhân Cách xử lý
Permission denied (publickey), log Certificate invalid: name is not a listed principal Principal không khớp user đích / file principals Ký lại với -n đúng hoặc sửa auth_principals/<user>
Log Certificate invalid: expired hoặc not yet valid Hết hạn hoặc lệch đồng hồ Ký lại; kiểm tra NTP; dùng -V -5m:+8h
Client vẫn hỏi xác nhận fingerprint Thiếu HostCertificate trên server hoặc pattern @cert-authority không khớp tên gõ ssh -v xem có Server host certificate; sửa principals/pattern
Mọi user đều bị từ chối sau khi thêm RevokedKeys File KRL không tồn tại/không đọc được Tạo KRL rỗng bằng ssh-keygen -k -f
Cert hợp lệ nhưng không port-forward được Ký kèm -O no-port-forwarding hoặc AllowTcpForwarding no Ký lại hoặc nới Match trong sshd
Agent không dùng cert Chỉ add private key, cert không cùng tên <key>-cert.pub ssh-add ~/.ssh/id_ed25519 khi file cert nằm cạnh; hoặc CertificateFile trong ~/.ssh/config

Tham khảo

  • man ssh-keygen (mục CERTIFICATES, KEY REVOCATION LISTS)
  • man sshd_config (TrustedUserCAKeys, AuthorizedPrincipalsFile, RevokedKeys, HostCertificate)
  • man sshd (mục SSH_KNOWN_HOSTS FILE FORMAT, @cert-authority)