Chỉ dùng SSH Key chưa chắc đã an toàn tuyệt đối. Nếu máy cá nhân dính malware hoặc ai đó vô tình đẩy private key lên GitHub, server của bạn sẽ gặp nguy hiểm ngay lập tức. Bật xác thực 2 yếu tố (2FA) ngay ở tầng SSH là cách nhanh và tin cậy nhất để chặn đứng nguy cơ này.
Quick start: Thiết lập SSH 2FA trong 5 phút
Các bước dưới đây áp dụng trực tiếp cho Ubuntu 20.04, 22.04 và 24.04 LTS.
Bước 1: Cài đặt PAM module Google Authenticator
Cập nhật danh sách package rồi cài thư viện PAM tương ứng:
sudo apt update
sudo apt install libpam-google-authenticator -y
Bước 2: Khởi tạo secret key và mã QR
Chạy lệnh dưới đây với chính user bạn muốn áp dụng 2FA (không thêm sudo):
google-authenticator
Hệ thống sẽ đưa ra 5 câu hỏi cấu hình tương tác. Bạn lần lượt chọn như sau:
- Do you want authentication tokens to be time-based (y/n)? → Chọn
yđể dùng mã TOTP theo thời gian. - Màn hình sẽ in ra mã QR, Secret Key và 5 mã cứu hộ (emergency scratch codes, mỗi mã 8 chữ số). Mở app Google Authenticator, 2FAS hoặc Aegis quét mã QR ngay. Đừng quên copy 5 mã cứu hộ cất vào password manager.
- Do you want me to update your “~/.google_authenticator” file (y/n)? → Chọn
yđể ghi file cấu hình. - Do you want to disallow multiple uses of the same authentication token (y/n)? → Chọn
yđể chặn tấn công replay. Mỗi mã 6 số chỉ dùng được đúng 1 lần trong 30 giây. - Increase the time-skew window (y/n)? → Chọn
n. Lựa chọn này giữ cửa sổ kiểm tra ở mức mặc định (30 giây), tránh nới rộng thời gian cho kẻ tấn công. - Enable rate-limiting (y/n)? → Chọn
yđể giới hạn tối đa 3 lần thử đăng nhập sai trong 30 giây.
Bước 3: Cấu hình PAM (Pluggable Authentication Modules)
Mở file cấu hình PAM của SSH daemon:
sudo nano /etc/pam.d/sshd
Chèn thêm dòng này vào cuối file:
auth required pam_google_authenticator.so nullok
Mẹo: Tham số nullok rất quan trọng. Nó cho phép user nào chưa chạy lệnh google-authenticator vẫn đăng nhập bình thường bằng mật khẩu/key, không lo bị khóa tài khoản ngoài ý muốn khi đang triển khai từng người.
Bước 4: Cập nhật SSH daemon config
Mở tiếp file cấu hình OpenSSH:
sudo nano /etc/ssh/sshd_config
Tìm và đổi giá trị hai thông số sau thành yes:
KbdInteractiveAuthentication yes
UsePAM yes
(Lưu ý: Trên các bản Ubuntu cũ trước 22.04, directive này mang tên ChallengeResponseAuthentication yes).
Bước 5: Restart SSH service và kiểm tra
sudo systemctl restart ssh
Cảnh báo quan trọng: Đừng vội đóng tab terminal hiện tại. Hãy mở một cửa sổ mới rồi test đăng nhập:
ssh username@your_server_ip
Server sẽ yêu cầu nhập Verification code: trước khi mở shell làm việc.
Hiểu nhanh cơ chế hoạt động
Quá trình xác thực 2FA qua SSH diễn ra qua hai lớp:
- OpenSSH Server (sshd): Nhận kết nối và bàn giao tiến trình hỏi danh tính cho PAM qua cơ chế
KbdInteractiveAuthentication. - PAM Module (libpam-google-authenticator): Đọc file
~/.google_authenticatortrong thư mục home. Module tính toán mã OTP dựa trên thuật toán TOTP (RFC 6238) bằng cách băm Secret Key tĩnh với timestamp hiện tại (chu kỳ 30 giây). Nếu 6 chữ số khớp với mã trên app di động, phiên SSH được chấp thuận.
Cấu hình nâng cao: Bắt buộc đồng thời SSH Key + Mã 2FA
Mặc định, khi xác thực thành công bằng SSH Key, OpenSSH sẽ bỏ qua bước nhập OTP. Để máy chủ đạt chuẩn an toàn cao nhất, bạn cần ép người dùng thỏa mãn cả hai: vừa có Private Key, vừa có mã TOTP.
Đầu tiên, mở /etc/pam.d/sshd. Comment dòng @include common-auth lại để server không bắt gõ password tài khoản Ubuntu khi đã có SSH Key:
# @include common-auth
auth required pam_google_authenticator.so
Kế tiếp, chỉnh /etc/ssh/sshd_config để định nghĩa chuỗi xác thực bắt buộc:
PubkeyAuthentication yes
KbdInteractiveAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
Kiểm tra cú pháp cấu hình SSH trước khi áp dụng để tránh lỗi syntax:
sudo sshd -t && sudo systemctl restart ssh
Lúc này, client phải xác thực SSH Key thành công trước. Ngay sau đó server mới hiện prompt Verification code:. Thiếu một trong hai yếu tố, kết nối sẽ bị ngắt lập tức.
Miễn trừ 2FA khi truy cập qua mạng nội bộ hoặc VPN
Nếu bạn muốn bắt buộc 2FA khi dev SSH từ Internet, nhưng cho phép bỏ qua OTP khi đã kết nối WireGuard / OpenVPN công ty, hãy dùng block Match trong /etc/ssh/sshd_config:
# Mặc định bắt buộc Key + 2FA cho toàn bộ kết nối bên ngoài
AuthenticationMethods publickey,keyboard-interactive
# Miễn trừ OTP cho dải IP VPN nội bộ (chỉ cần SSH Key)
Match Address 10.8.0.0/24,192.168.1.0/24
AuthenticationMethods publickey
Kinh nghiệm thực tế & Cách tránh bị lock khỏi server
- Luôn treo 1 session cứu hộ: Khi sửa
/etc/pam.d/hoặc/etc/ssh/sshd_config, hãy giữ nguyên một phiên SSH có quyền root. Nếu tab mới không đăng nhập được, bạn vẫn còn session cũ để sửa sai ngay. - Đồng bộ đồng hồ hệ thống bằng NTP: TOTP tính toán theo timestamp 30 giây. Lệch quá 30 giây giữa server và điện thoại sẽ khiến mã OTP liên tục báo sai. Kiểm tra bằng lệnh:
timedatectl status
# Cần đảm bảo: "NTP service: active" và "System clock synchronized: yes"
- Lưu trữ 5 mã Emergency Scratch Codes: Khi mất điện thoại hoặc hỏng app, 5 mã này là phao cứu sinh duy nhất. Mỗi mã chỉ dùng được 1 lần, hãy lưu vào 1Password, Bitwarden hoặc Vault của team.
- Xóa 2FA khi bị kẹt: Nếu mất điện thoại và không còn mã backup, bạn hãy vào Web Console của nhà cung cấp VPS (AWS EC2 Serial Console, DigitalOcean Droplet Console hoặc Proxmox) và xóa file cấu hình:
sudo rm /home/username/.google_authenticator

