SSH bị brute-force là chuyện xảy ra hàng ngày trên mọi server có IP public. Nếu bạn chạy grep 'Failed password' /var/log/auth.log | wc -l mà thấy con số vài nghìn — chúc mừng, bạn đang bị quét liên tục rồi đó.
Mình từng dính một lần vào năm đầu làm sysadmin: server Ubuntu mặc định port 22, password auth bật, không có gì thêm. Mất cả buổi chiều mới debug ra — root login đã bị compromise từ lúc nào không biết, attacker đang chạy cryptominer âm thầm từ 3 giờ sáng. Check log thấy hơn 40.000 failed attempt trong 48 giờ. Bài học đó đắt hơn bất kỳ khóa học bảo mật nào.
Bài này không phải lý thuyết. Mình đi thẳng vào từng lựa chọn: cái nào hiệu quả thật sự, cái nào mất công mà ít tác dụng, và thứ tự nên làm ra sao.
So sánh các hướng tiếp cận bảo mật SSH
Mình đã thử qua đủ kiểu. Có 4 hướng phổ biến — và không phải cái nào cũng đáng đầu tư như lý thuyết vẫn nói:
1. Đổi port SSH (Security by Obscurity)
Ưu điểm: Giảm ngay lượng log spam. Script kiddie dùng tool quét port 22 mặc định sẽ tự động bỏ qua bạn.
Nhược điểm: Không an toàn hơn thật sự. Scanner như Shodan hay Masscan quét toàn bộ 65.535 port trong vài phút. Đây là lớp giảm nhiễu, không phải bảo mật thật.
Kết luận: Làm được thì làm, nhưng đừng dừng ở đây.
2. Tắt password auth, dùng SSH key
Ưu điểm: Loại bỏ hoàn toàn brute-force password. Đây là thay đổi có tác động lớn nhất với chi phí thấp nhất.
Nhược điểm: Cần quản lý key cẩn thận. Mất private key mà không có backup là mất quyền truy cập luôn.
Kết luận: Bắt buộc phải làm. Ưu tiên số 1, không bàn cãi.
3. Fail2ban / rate limiting
Ưu điểm: Tự động ban IP sau 3–5 lần thử sai trong vòng 10 phút. Hiệu quả với các script quét đơn giản.
Nhược điểm: Botnet phân tán từ hàng nghìn IP khác nhau thì Fail2ban cũng bó tay. Thêm dependency, thêm thứ cần maintain.
Thực tế: Nên có, nhưng là lớp thứ 2 — sau khi đã tắt password auth.
4. Firewall whitelist IP
Ưu điểm: Cực kỳ hiệu quả nếu bạn truy cập từ vài IP cố định. Không có gì qua được firewall chặn từ đầu.
Nhược điểm: IP động — mobile, cafe, khách sạn — là vấn đề ngay. Cần VPN hoặc jump host để làm triệt để.
Kết luận: Lý tưởng cho server production. Khó áp dụng nếu bạn hay làm việc từ nhiều địa điểm.
Thứ tự ưu tiên: Làm gì trước?
Đây là thứ tự mình hay làm, từ tác động cao xuống thấp dần:
- Tắt root login + tắt password auth + bật SSH key
- Giới hạn user được phép SSH
- Đổi port (tùy chọn, chủ yếu để giảm log noise)
- Cài Fail2ban
- Firewall giới hạn IP (nếu workflow cho phép)
Triển khai thực tế
Bước 1: Tạo SSH key pair và upload lên server
Chạy lệnh này trên máy local — không phải trên server:
# Tạo key pair với ed25519 (mạnh hơn RSA 2048)
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519
# Copy public key lên server
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-server-ip
# Test thử trước khi tắt password auth!
ssh -i ~/.ssh/id_ed25519 user@your-server-ip
Quan trọng: Test kết nối bằng key TRƯỚC khi tắt password auth. Bỏ qua bước này, bạn sẽ tự khóa mình ra ngoài.
Bước 2: Hardening file cấu hình SSH
sudo nano /etc/ssh/sshd_config
Các dòng cần thay đổi hoặc thêm vào:
# Tắt root login
PermitRootLogin no
# Tắt password authentication
PasswordAuthentication no
# Trên OpenSSH 9.0+, ChallengeResponseAuthentication đổi tên thành KbdInteractiveAuthentication
ChallengeResponseAuthentication no
UsePAM no
# Chỉ cho phép SSH key
PubkeyAuthentication yes
# Giới hạn user SSH (thay 'youruser' bằng username thực)
AllowUsers youruser
# Đổi port (tùy chọn)
# Port 2222
# Giảm timeout và số lần thử
LoginGraceTime 30
MaxAuthTries 3
MaxSessions 5
# Tắt các tính năng ít dùng, nhiều rủi ro
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
# Lưu ý: directive 'Protocol 2' đã bị xóa từ OpenSSH 7.6+ — không cần thêm
Kiểm tra syntax rồi mới reload — theo đúng thứ tự này:
# Kiểm tra config trước khi apply
sudo sshd -t
# Nếu không có lỗi, mới reload
sudo systemctl reload sshd
Bước 3: Cài và cấu hình Fail2ban
sudo apt install fail2ban -y # Ubuntu/Debian
# hoặc
sudo dnf install fail2ban -y # RHEL/AlmaLinux
Tạo file cấu hình local riêng — đừng chỉnh file gốc, nó sẽ bị overwrite khi update package:
sudo nano /etc/fail2ban/jail.local
[sshd]
enabled = true
port = ssh
# Nếu bạn đổi port: port = 2222
logpath = %(sshd_log)s
maxretry = 3
bantime = 3600
findtime = 600
ignoreip = 127.0.0.1/8 ::1 YOUR_HOME_IP
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# Kiểm tra status
sudo fail2ban-client status sshd
Bước 4: Firewall cơ bản với UFW
# Cho phép SSH (nếu đổi port thì thay 22 bằng port mới)
sudo ufw allow 22/tcp
# Hoặc giới hạn chỉ từ IP cụ thể
sudo ufw allow from 1.2.3.4 to any port 22
sudo ufw enable
sudo ufw status verbose
Kiểm tra lại sau khi setup
Xong rồi chưa nghỉ vội — chạy checklist này để chắc chắn mọi thứ đang hoạt động đúng:
# Xem ai đang đăng nhập thành công
last -n 20
# Xem các attempt thất bại gần đây
grep 'Failed password\|Invalid user' /var/log/auth.log | tail -20
# Kiểm tra Fail2ban đang hoạt động
sudo fail2ban-client status
# Xem port SSH đang listen
ss -tlnp | grep ssh
Một lệnh mình hay dùng để audit nhanh cấu hình SSH:
sudo sshd -T | grep -E 'permitrootlogin|passwordauthentication|pubkeyauthentication|allowusers'
Output mẫu khi đã hardened đúng:
permitrootlogin no
passwordauthentication no
pubkeyauthentication yes
allowusers youruser
Những lỗi thường gặp khi hardening SSH
- Tắt password auth khi chưa upload key: Kết quả là bị lock out. Luôn test key auth trước.
- Quên thêm IP vào
ignoreipcủa Fail2ban: Bạn tự ban chính mình sau vài lần type sai password. - Chỉnh
/etc/ssh/sshd_confignhưng không reload: Config chưa áp dụng — bạn tưởng xong nhưng chẳng có gì thay đổi cả. - Dùng RSA 1024: Yếu từ lâu rồi. Dùng ed25519 hoặc ít nhất RSA 4096.
Tổng kết
Ba thứ bắt buộc — không cần bàn cãi — nếu server đang có SSH mở ra internet: tắt root login, tắt password auth, bật SSH key. Ba việc đó chiếm 90% hiệu quả bảo mật. Phần còn lại chỉ là tăng cường thêm.
Fail2ban và firewall whitelist hữu ích, nhưng đừng trông cậy vào chúng như biện pháp chính. Attacker có đủ kiên nhẫn và botnet để vượt qua rate limit. Nhưng không ai brute-force được private key ed25519 — cần hàng tỷ năm tính toán để thử hết không gian khóa 256-bit.

