SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-08-07

SSH key: Cách tạo, bảo vệ và thu hồi đúng cách

Tìm hiểu cách quản lý SSH key trên Ubuntu 24.04: dùng một key ed25519 cho mỗi thiết bị, permissions sshd yêu cầu, config Host và cách thu hồi key bị mất.

Cách SSH key hoạt động

SSH key là một cặp file: private key được giữ trên thiết bị của bạn và public key được sao chép vào mọi server mà bạn muốn đăng nhập. Khi bạn kết nối, server dùng public key để gửi một challenge mà chỉ private key tương ứng mới có thể trả lời. Private key không bao giờ rời khỏi thiết bị của bạn, nên không có secret nào được truyền qua network và server bị breach cũng không có gì hữu ích để đánh cắp. Đó là lý do key an toàn hơn password. Quản lý SSH key đúng cách tập trung vào 4 thói quen: dùng một key cho mỗi thiết bị, đặt permissions đúng theo yêu cầu của sshd, dùng file ~/.ssh/config để không phải nhập lại options, và biết cách xóa key ngay khi laptop bị mất.

Hướng dẫn này trình bày từng thói quen trên Ubuntu 24.04. Tuy nhiên, gần như mọi nội dung đều áp dụng cho bất kỳ Linux server nào và mọi phiên bản OpenSSH gần đây.

Trước khi bắt đầu, cần thống nhất một điểm về thuật ngữ để tránh các lỗi thực tế. Public key không phải secret. Bạn có thể dán nó vào ticket, gửi qua email hoặc công khai nó; không ai có thể đăng nhập chỉ bằng key này. Private key mới là secret. Bất kỳ ai sao chép được file đó và biết passphrase của nó, nếu có, đều có quyền như bạn trên các server của bạn.

Tạo key: ed25519 là lựa chọn mặc định phù hợp

Trên máy tính của bạn, không phải trên server, hãy chạy:

ssh-keygen -t ed25519 -C "laptop"

-t ed25519 chọn loại key. Ed25519 là lựa chọn mặc định hiện đại: key ngắn, nhanh và được mọi bản phát hành OpenSSH kể từ 2014 hỗ trợ. Chỉ dùng ssh-keygen -t rsa -b 4096 khi bạn phải kết nối đến một thiết bị cũ không hiểu ed25519. -C "laptop" đặt comment. Comment không có tác dụng về mặt mật mã, nhưng sau hai năm nó giúp bạn nhận ra key này nằm trên thiết bị nào trong file authorized_keys của server. Vì vậy, hãy đặt tên cho thiết bị chứa key.

ssh-keygen hỏi nơi lưu key. Chấp nhận giá trị mặc định, ~/.ssh/id_ed25519. Sau đó, lệnh hỏi passphrase. Hãy đặt passphrase; phần về passphrase bên dưới giải thích vì sao việc này không làm bạn tốn thêm công sức hằng ngày. Bạn sẽ có hai file: ~/.ssh/id_ed25519 là private key và ~/.ssh/id_ed25519.pub là public key. Xem public key:

cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptop

Đây là một dòng gồm loại key, dữ liệu key và comment của bạn. Đây là dòng sẽ được thêm vào các server của bạn.

Mỗi thiết bị một key, không phải mỗi server một key

Câu hỏi mọi người thường hỏi đầu tiên là: có cần tạo key mới cho từng server không? Không. Hãy tạo một key cho mỗi thiết bị bạn dùng để nhập lệnh, rồi đặt public key đó trên mọi server mà thiết bị cần truy cập. Key xác định thiết bị. File authorized_keys trên mỗi server là danh sách các thiết bị được phép truy cập.

Đây là mô hình có thể mở rộng, còn các phương án khác sẽ gặp lỗi theo những cách dễ đoán. Nếu tạo một key cho mỗi server, laptop kết nối đến 20 server sẽ phải chứa 20 private key, và bạn sẽ không còn biết key nào thuộc server nào. Dùng chung một key cho tất cả thiết bị còn tệ hơn: khi laptop bị đánh cắp, bạn không thể thu hồi quyền của laptop mà vẫn giữ quyền cho desktop, vì cả hai đang giữ cùng một private key. Khi đó, bạn phải thay key trên mọi nơi và phân phối key mới đến tất cả thiết bị cùng lúc.

Với mô hình mỗi thiết bị một key, khi mất laptop, bạn chỉ cần xóa một dòng trên mỗi server: xóa dòng của laptop khỏi authorized_keys, còn mọi thiết bị khác vẫn hoạt động. Comment bạn đặt bằng -C giúp dễ tìm đúng dòng đó.

Quy tắc phía sau mô hình này là: private key được tạo trên một thiết bị và không còn được dùng khi thiết bị đó bị loại bỏ. Không bao giờ sao chép private key sang máy thứ hai và không bao giờ upload private key lên server. Khi một thiết bị mới cần truy cập, hãy tạo một key mới trên chính thiết bị đó.

Đặt public key lên server

Cách đơn giản là dùng ssh-copy-id, được tích hợp trong OpenSSH:

ssh-copy-id matt@10.0.0.10

Lệnh này đăng nhập bằng phương thức vẫn còn hoạt động, thường là password, thêm public key của bạn vào ~/.ssh/authorized_keys trên server, đồng thời tạo directory và file với permission đúng nếu chúng chưa tồn tại. Kiểm tra bằng cách mở một SSH session mới: server phải cho phép bạn đăng nhập mà không hỏi password của account. Nếu key có passphrase, máy của bạn có thể hỏi passphrase đó; prompt này xuất hiện ở máy cục bộ và không phải password của server.

Khi password login đã bị tắt, ssh-copy-id không thể đăng nhập, vì vậy bạn phải tự thêm dòng này. Đăng nhập bằng một session vẫn còn hoạt động hoặc dùng web console của nhà cung cấp, rồi chạy lệnh sau trên server:

mkdir -p ~/.ssh && chmod 700 ~/.ssh
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIF3k2s0vQx7GdKQhX1yBz... laptop" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

Dán public key thật của bạn vào bên trong dấu ngoặc kép, giữ nguyên toàn bộ dòng đơn từ id_ed25519.pub. authorized_keys chứa mỗi dòng một public key và là toàn bộ cơ sở dữ liệu quyền truy cập: thêm một thiết bị nghĩa là thêm một dòng, còn thu hồi một thiết bị nghĩa là xóa một dòng. Trên server mới, bước này nằm trong 10 phút đầu khi tạo VPS mới, ngay trước khi bạn tắt password login.

Quyền khiến đăng nhập bằng key bị lỗi

Đây là nguyên nhân phổ biến nhất khiến đăng nhập bằng key thất bại. Lỗi này không hiển thị rõ ở phía client. sshd chạy với StrictModes yes theo mặc định trên Ubuntu 24.04. Vì vậy, sshd từ chối sử dụng file authorized_keys nếu người dùng khác có thể chỉnh sửa file đó. Nếu file, thư mục ~/.ssh hoặc thư mục home của bạn có thể bị bất kỳ ai ngoài bạn ghi vào, sshd sẽ bỏ qua key và chuyển sang yêu cầu mật khẩu. Client không hiển thị lý do. (OpenSSH trên Ubuntu chỉ cho phép đúng một trường hợp ngoại lệ hẹp: file có quyền ghi bởi group riêng của chính bạn, và không có người dùng nào khác thuộc group đó. Không nên dựa vào ngoại lệ này; hãy dùng các mode bên dưới.) Lý do chỉ xuất hiện trong log của server:

sudo grep 'Authentication refused' /var/log/auth.log

Trên image tối giản không có rsyslog, sẽ không có auth.log. Dòng log tương tự nằm trong journal: sudo journalctl -u ssh | grep 'Authentication refused'.

Authentication refused: bad ownership or modes for file /home/matt/.ssh/authorized_keys

Cách sửa gồm 2 thay đổi quyền và kiểm tra ownership. Chạy các lệnh này trên server với user bị ảnh hưởng:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chown -R matt:matt ~/.ssh

Quy tắc cần nhớ: 700 cho thư mục .ssh, 600 cho mọi thứ bên trong thư mục đó. Các số này cũng áp dụng trên máy tính của bạn, vì client cũng kiểm tra quyền. Nếu user khác có thể đọc private key, ssh sẽ từ chối key ngay lập tức. Lần này lỗi sẽ được hiển thị rõ:

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/matt/.ssh/id_ed25519' are too open.

chmod 600 ~/.ssh/id_ed25519 sẽ sửa lỗi này.

~/.ssh/config: không phải nhập lại option

Một file ~/.ssh/config trên máy tính của bạn cho phép đặt tên ngắn cho từng server và ghi nhớ các option bạn thường phải nhập. Tạo file này với quyền 600, rồi thêm một block Host cho mỗi server:

Host web1
    HostName 10.0.0.10
    User matt
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Host db1
    HostName 10.0.0.11
    User matt
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Bây giờ ssh web1 thay thế cho ssh -p 22 matt@10.0.0.10. Bạn có thể dùng cùng tên ngắn đó trong scp, rsyncgit vì tất cả đều đọc file này. HostName là địa chỉ thật, User giúp bạn không phải nhập tên account, còn IdentityFile cố định key mà client sẽ cung cấp.

IdentitiesOnly yes cần được giải thích riêng vì nó khắc phục một lỗi dễ gây nhầm lẫn. Khi agent đang giữ nhiều key, client sẽ lần lượt cung cấp từng key, còn server tính mỗi lần cung cấp không đúng là một lần thử thất bại. Nếu có đủ nhiều key được load, bạn sẽ nhận Received disconnect: Too many authentication failures trước khi client thử đúng key. IdentitiesOnly yes buộc client chỉ cung cấp key được nêu trong IdentityFile, nên lỗi này không thể xảy ra.

Mật khẩu bảo vệ và ssh-agent

Passphrase mã hóa file private key trên ổ đĩa. Nếu không có passphrase, bất kỳ ai sao chép được file đều có thể dùng ngay; nếu có passphrase, file bị đánh cắp sẽ vô dụng cho đến khi passphrase bị đoán ra. Với key trên laptop, đây chính xác là lớp bảo vệ bạn cần, vì laptop có thể bị đánh cắp và bản sao lưu của laptop có thể bị lộ.

Lý do passphrase hầu như không gây bất tiện trong thực tế là ssh-agent. Agent giữ key đã giải mã trong memory, nên bạn chỉ nhập passphrase một lần trong mỗi phiên đăng nhập và mọi kết nối sau đó đều được thiết lập ngay. Hầu hết bản phân phối Linux cho desktop và macOS đã chạy sẵn agent. Nạp key vào agent bằng lệnh:

ssh-add ~/.ssh/id_ed25519

ssh-add -l liệt kê các key mà agent hiện đang giữ. Lưu ý: agent forwarding (ssh -A) cho phép server từ xa dùng agent của bạn để xác thực đến server khác trong khi bạn đang kết nối. Vì vậy, chỉ bật tính năng này khi kết nối đến các server mà bạn hoàn toàn tin cậy, và mặc định nên tắt nó.

Luân phiên và thu hồi: quy trình xử lý laptop bị mất

Thu hồi một SSH key thông thường chỉ là xóa dòng chứa key đó khỏi authorized_keys trên mọi server đang có key. Bạn không cần thông báo cho certificate authority và cũng không phải chờ đến ngày hết hạn. Ngay khi dòng đó bị xóa, các lần đăng nhập mới bằng key này sẽ fail.

Hãy thực hiện quy trình này ngay khi chưa có sự cố khẩn cấp. Chọn một server, mở ~/.ssh/authorized_keys và tìm key theo comment của nó. Xóa dòng bằng editor hoặc lọc dòng đó theo comment:

grep -v ' laptop$' ~/.ssh/authorized_keys > ~/.ssh/authorized_keys.tmp
mv ~/.ssh/authorized_keys.tmp ~/.ssh/authorized_keys

Sau đó, xác nhận từ thiết bị vừa bị thu hồi rằng đăng nhập đã fail, rồi xác nhận từ một thiết bị khác rằng đăng nhập vẫn hoạt động. Lưu ý: xóa key không đóng các session đang mở, vì key chỉ được kiểm tra khi đăng nhập. Nếu bạn đang thu hồi quyền của một thiết bị bị đánh cắp, hãy kiểm tra thêm who trên server và kết thúc mọi session bạn không nhận ra.

Luân phiên key cũng dùng thao tác tương tự nhưng theo thứ tự khác: tạo key mới trên thiết bị, cài đặt key bằng ssh-copy-id, xác nhận key mới đăng nhập được, rồi xóa dòng chứa key cũ. Hãy thực hiện khi thiết bị được chuyển cho người khác, khi key có thể đã bị lộ hoặc khi một người rời team. Làm thủ công trên hai server thì không sao; trên hai mươi server, đây là việc dành cho automation. Quản lý nhiều Linux server hướng dẫn cách đẩy cùng một trạng thái authorized_keys đến toàn bộ fleet.

Không nên làm gì

  • Không dùng chung một private key cho tất cả thiết bị. Khi đó, bạn không thể thu hồi riêng một thiết bị bị đánh cắp mà không thay key trên mọi nơi.
  • Không commit private key vào git repository, kể cả repository private. Các công cụ quét tự động theo dõi repository public và thử các key bị lộ chỉ trong vài phút sau khi push. Nếu repository được chuyển sang public về sau, toàn bộ lịch sử của repository cũng bị lộ.
  • Không upload private key của laptop lên một server để server đó truy cập một server khác. Hãy tạo một key riêng ngay trên server và chỉ cấp quyền cho key đó đúng tại nơi cần dùng.
  • Không paste private key vào chat, email hoặc ticket. Public key, tức file .pub, là phần duy nhất được chia sẻ.

Sau khi key đăng nhập ổn định, hãy tắt xác thực bằng password để các lần thử đoán liên tục nhằm vào server không thể thành công. Cấu hình drop-in cho việc này nằm trong Hardening SSH trên VPS.

FAQ

Khóa SSH hoạt động thế nào mà không cần gửi mật khẩu?

Server lưu public key của bạn trong ~/.ssh/authorized_keys. Khi đăng nhập, server gửi một challenge; client dùng private key để ký challenge, rồi server xác minh chữ ký bằng public key. Private key không bao giờ rời khỏi thiết bị của bạn, nên không có gì để chặn bắt trên đường truyền và cũng không có gì có thể tái sử dụng để đánh cắp từ server. Một server bị breach chỉ làm lộ các public key, không thể dùng chúng để đăng nhập ở bất kỳ đâu.

Tôi có nên dùng cùng một khóa SSH cho tất cả server không?

Dùng một key trên nhiều server là đúng, miễn là key đó chỉ nằm trên một thiết bị. Quy tắc là mỗi thiết bị một key, không phải mỗi server một key: public key của laptop được đặt trên mọi server mà laptop cần truy cập, còn desktop có key riêng. Cách này giúp thu hồi key đơn giản, vì khi mất một thiết bị, bạn chỉ cần xóa một dòng xác định được trên mỗi server; các thiết bị khác vẫn hoạt động.

Thư mục .ssh và authorized_keys cần có permission thế nào?

Đặt 700 cho ~/.ssh600 cho authorized_keys cũng như mọi private key; các file này phải thuộc sở hữu của account sử dụng chúng. sshd mặc định chạy với StrictModes yes, nên nếu file hoặc home directory có thể bị bất kỳ ai ngoài bạn ghi vào, sshd sẽ âm thầm bỏ qua key của bạn. Dấu vết duy nhất là Authentication refused: bad ownership or modes trong auth log hoặc journal của server.

Tôi xóa một key SSH khỏi server bằng cách nào?

Xóa dòng chứa key đó khỏi ~/.ssh/authorized_keys trong account đã được cấp quyền sử dụng key. Tìm đúng dòng dựa vào comment, tức nhãn nằm sau phần key material. Các lần đăng nhập mới bằng key đó sẽ fail ngay, nhưng những session đang mở vẫn tiếp tục, nên nếu thiết bị bị đánh cắp, hãy kết thúc cả session đang hoạt động của thiết bị đó. Lặp lại trên mọi server đã được sao chép key này.

Tôi có cần đặt passphrase cho SSH key không?

Nếu key nằm trên laptop hoặc desktop thì có. Passphrase mã hóa file key, nên bản sao bị đánh cắp hoặc bị lộ sẽ không thể tự sử dụng; còn ssh-agent giúp bạn chỉ phải nhập passphrase một lần trong mỗi session thay vì mỗi lần kết nối. Các key dùng cho automation không có người giám sát trên server thường không có passphrase, vì không có người để nhập passphrase; hãy bảo vệ chúng bằng cách hạn chế những gì target account được phép thực hiện.