Lập trình 18 PHÚT ĐỌC 19 lượt xem

Cách Cấu Hình SSH và Quản Lý Server Từ Xa An Toàn 2026

Author
Lê Minh Trung
Tác giả
26/04/2026

Mỗi ngày có hàng triệu cuộc tấn công brute-force nhắm vào các server Linux chạy SSH với cấu hình mặc định. Nếu server của bạn đang dùng port 22, password authentication, và root login được bật, bạn chỉ còn là vấn đề thời gian trước khi bị compromise. Cấu hình SSH đúng cách không chỉ là best practice, nó là yêu cầu tối thiểu cho bất kỳ server nào expose ra internet. Bài viết này hướng dẫn toàn bộ quy trình quản lý server từ xa an toàn bằng SSH, từ tạo SSH key pair, hardening sshd_config, đến thiết lập fail2ban và 2FA, với các lệnh cụ thể có thể copy-paste và chạy ngay trên Ubuntu/Debian và CentOS/RHEL.

Tại Sao SSH Mặc Định Là Không An Toàn?

Một server Ubuntu mới deploy với SSH mặc định sẽ nhận được hàng trăm đến hàng nghìn login attempt mỗi giờ từ các botnet tự động trên toàn thế giới. Chạy lệnh này trên server mới của bạn để tự thấy:

# Xem failed login attempts
sudo journalctl -u ssh --no-pager | grep "Failed password" | wc -l

# Hoặc trên hệ thống dùng auth.log
sudo grep "Failed password" /var/log/auth.log | wc -l

SSH mặc định nguy hiểm vì 4 lý do chính: (1) Dùng port 22 phổ biến, mọi scanner đều target port này đầu tiên. (2) Cho phép password authentication, dễ bị brute-force. (3) Cho phép root login trực tiếp, nếu bị compromise thì game over ngay. (4) Không có rate limiting mặc định, một IP có thể thử không giới hạn lần.

Checklist Bảo Mật SSH Hoàn Chỉnh: 8 Bước Theo Thứ Tự

Bước 1: Tạo SSH Key Pair Trên Máy Client

SSH key authentication an toàn hơn password vì: key 4096-bit RSA hoặc Ed25519 không thể brute-force trong thời gian thực tế, private key không bao giờ rời khỏi máy client của bạn, và passphrase bảo vệ key ngay cả khi máy client bị lấy cắp.

Tạo Ed25519 Key (Khuyến Nghị 2026)

# Ed25519 là thuật toán được khuyến nghị năm 2026
# Nhanh hơn RSA, key ngắn hơn nhưng bảo mật tương đương
ssh-keygen -t ed25519 -C "[email protected]" -f ~/.ssh/id_ed25519

# Nếu server cũ chưa hỗ trợ Ed25519, dùng RSA 4096
ssh-keygen -t rsa -b 4096 -C "[email protected]" -f ~/.ssh/id_rsa_server

# Luôn đặt passphrase khi được hỏi
# Passphrase bảo vệ private key nếu máy bị lấy cắp

Copy Public Key Lên Server

# Cách 1: Dùng ssh-copy-id (đơn giản nhất)
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server-ip

# Cách 2: Manual nếu ssh-copy-id không available
cat ~/.ssh/id_ed25519.pub | ssh user@server-ip \
  "mkdir -p ~/.ssh && chmod 700 ~/.ssh && \
   cat >> ~/.ssh/authorized_keys && \
   chmod 600 ~/.ssh/authorized_keys"

# Verify key đã được copy thành công
ssh -i ~/.ssh/id_ed25519 user@server-ip

Cấu Hình SSH Client (~/.ssh/config)

# Thêm vào ~/.ssh/config để không phải gõ options mỗi lần
Host myserver
    HostName 203.0.113.10
    User deploy
    IdentityFile ~/.ssh/id_ed25519
    Port 2222
    ServerAliveInterval 60
    ServerAliveCountMax 3

Host staging
    HostName 203.0.113.20
    User ubuntu
    IdentityFile ~/.ssh/id_ed25519_staging
    Port 2222

Sau khi cấu hình, thay vì gõ ssh -i ~/.ssh/id_ed25519 -p 2222 [email protected], bạn chỉ cần gõ ssh myserver.

Bước 2: Hardening sshd_config Trên Server

Đây là bước quan trọng nhất. Backup file config trước khi chỉnh sửa:

# LUÔN backup trước khi edit
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# Mở để edit
sudo nano /etc/ssh/sshd_config
# hoặc
sudo vim /etc/ssh/sshd_config

Các Dòng Cấu Hình Quan Trọng

# ============================================
# SSH HARDENING CONFIG - codewithtrung.cv
# ============================================

# 1. Đổi port mặc định (không phải silver bullet
#    nhưng giảm đáng kể noise từ automated scanners)
Port 2222

# 2. Chỉ cho phép IPv4 nếu không dùng IPv6
#AddressFamily inet

# 3. QUAN TRỌNG: Tắt root login hoàn toàn
PermitRootLogin no

# 4. QUAN TRỌNG: Tắt password authentication
#    Chỉ sau khi đã verify SSH key hoạt động!
PasswordAuthentication no
ChallengeResponseAuthentication no

# 5. Tắt empty password
PermitEmptyPasswords no

# 6. Chỉ cho phép SSH protocol version 2
Protocol 2

# 7. Giới hạn số lần auth thất bại
MaxAuthTries 3

# 8. Giới hạn số session đồng thời
MaxSessions 5

# 9. Timeout idle session (giây)
ClientAliveInterval 300
ClientAliveCountMax 2

# 10. Tắt X11 forwarding nếu không cần
X11Forwarding no

# 11. Tắt agent forwarding nếu không cần
AllowAgentForwarding no

# 12. Chỉ cho phép user cụ thể SSH vào
# AllowUsers deploy ubuntu your-username
# AllowGroups sshusers

# 13. Chỉ dùng thuật toán mạnh
# (Cần OpenSSH 6.3+ cho các ciphers dưới đây)
KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512
Ciphers [email protected],[email protected]
MACs [email protected],[email protected]

# 14. Log level để detect suspicious activity
LogLevel VERBOSE

# 15. Tắt DNS lookup để tăng tốc connection
UseDNS no

Validate và Restart SSH Service

# QUAN TRỌNG: Test config trước khi restart
# Lỗi syntax trong sshd_config có thể lock bạn ra khỏi server
sudo sshd -t

# Nếu không có output lỗi, restart service
sudo systemctl restart sshd

# Verify service đang chạy
sudo systemctl status sshd

# KHÔNG đóng session hiện tại
# Mở terminal MỚI để test connection trước
ssh -p 2222 your-user@server-ip

Cảnh báo quan trọng: Không bao giờ đóng SSH session đang có trước khi test session mới hoạt động. Nếu có lỗi và bạn đã đóng session cũ, bạn sẽ bị lock out hoàn toàn và phải access qua console của VPS provider (DigitalOcean, Vultr, AWS EC2 console).

Bước 3: Đổi Port SSH và Cấu Hình Firewall

UFW (Ubuntu/Debian)

# Cài đặt UFW nếu chưa có
sudo apt install ufw -y

# QUAN TRỌNG: Allow SSH port MỚI trước khi enable UFW
# Thay 2222 bằng port bạn đã chọn trong sshd_config
sudo ufw allow 2222/tcp comment 'SSH custom port'

# Allow các service cần thiết khác
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'

# Enable UFW
sudo ufw enable

# Kiểm tra rules
sudo ufw status verbose

# Nếu cần xóa port 22 cũ (sau khi verify port mới hoạt động)
sudo ufw delete allow 22/tcp

firewalld (CentOS/RHEL/Rocky Linux)

# Thêm port SSH mới
sudo firewall-cmd --permanent --add-port=2222/tcp

# Xóa port 22 mặc định (sau khi verify port mới)
sudo firewall-cmd --permanent --remove-service=ssh

# Reload firewall
sudo firewall-cmd --reload

# Kiểm tra
sudo firewall-cmd --list-all

Bước 4: Cài Đặt và Cấu Hình fail2ban

fail2ban monitor log file và tự động ban IP có nhiều failed login attempts. Đây là lớp bảo vệ thiết yếu ngay cả sau khi đã disable password auth.

# Cài đặt
sudo apt install fail2ban -y  # Ubuntu/Debian
# hoặc
sudo yum install fail2ban -y  # CentOS/RHEL

# Tạo file config local (không edit file gốc)
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
sudo nano /etc/fail2ban/jail.local

Cấu Hình jail.local

[DEFAULT]
# Ban IP trong 24 giờ
bantime  = 86400

# Thời gian tính retroactively (10 phút)
findtime = 600

# Số lần thất bại trước khi ban
maxretry = 3

# Không ban IP này (thêm IP nhà/office của bạn)
ignoreip = 127.0.0.1/8 ::1 YOUR_HOME_IP YOUR_OFFICE_IP

[sshd]
enabled  = true
port     = 2222
filter   = sshd
logpath  = %(sshd_log)s
maxretry = 3
bantime  = 86400
# Restart và enable fail2ban
sudo systemctl restart fail2ban
sudo systemctl enable fail2ban

# Kiểm tra status
sudo fail2ban-client status
sudo fail2ban-client status sshd

# Xem danh sách IP đang bị ban
sudo fail2ban-client status sshd | grep "Banned IP"

# Unban một IP cụ thể nếu cần
sudo fail2ban-client set sshd unbanip IP_ADDRESS

Bước 5: Thiết Lập Two-Factor Authentication (2FA)

2FA thêm một lớp bảo vệ nữa: ngay cả khi SSH key bị compromise, attacker vẫn cần mã OTP từ điện thoại của bạn.

# Cài đặt Google Authenticator PAM module
sudo apt install libpam-google-authenticator -y

# Cấu hình cho user của bạn (chạy với user thường, KHÔNG root)
google-authenticator

# Trả lời các câu hỏi:
# - Time-based tokens? -> y
# - Update .google_authenticator? -> y
# - Disallow multiple uses? -> y
# - Increase window? -> n (giữ 30 giây window)
# - Rate limiting? -> y

# Scan QR code bằng Google Authenticator hoặc Authy app
# LƯU emergency scratch codes ở nơi an toàn!

Cấu Hình PAM cho SSH

# Edit PAM config cho SSH
sudo nano /etc/pam.d/sshd
# Thêm dòng này VÀO ĐẦU file /etc/pam.d/sshd
auth required pam_google_authenticator.so

# Giữ nguyên @include common-auth bên dưới
# Cập nhật sshd_config để enable ChallengeResponse
sudo nano /etc/ssh/sshd_config
# Thêm/cập nhật các dòng này trong sshd_config
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

# Với OpenSSH 8.7+
# AuthenticationMethods publickey,keyboard-interactive:pam
# Restart SSH
sudo systemctl restart sshd

# Test từ terminal mới: sẽ hỏi SSH key + OTP code

Bước 6: SSH Jump Host và Bastion Server Pattern

Với hệ thống có nhiều server, best practice là không expose SSH của tất cả server ra internet. Chỉ một Bastion host (Jump server) có SSH public, các server khác chỉ accept SSH từ Bastion.

Cách Dùng SSH Jump (-J flag)

# SSH vào private server thông qua bastion
ssh -J bastion-user@bastion-ip:2222 [email protected]

# Hoặc config trong ~/.ssh/config (cleaner)
# ~/.ssh/config
Host bastion
    HostName 203.0.113.10
    User deploy
    Port 2222
    IdentityFile ~/.ssh/id_ed25519

Host private-server-1
    HostName 192.168.1.10
    User ubuntu
    IdentityFile ~/.ssh/id_ed25519
    ProxyJump bastion

Host private-server-2
    HostName 192.168.1.20
    User ubuntu
    IdentityFile ~/.ssh/id_ed25519
    ProxyJump bastion
# Bây giờ có thể SSH trực tiếp vào private server
# SSH client sẽ tự động jump qua bastion
ssh private-server-1

Bước 7: SSH Tunneling và Port Forwarding

SSH tunneling cho phép bạn access service nội bộ của server (database, monitoring dashboard) một cách bảo mật mà không cần mở thêm port trên firewall.

Local Port Forwarding (Phổ Biến Nhất)

# Forward port 5432 (PostgreSQL) từ server về local
# Sau đó connect localhost:15432 để access PostgreSQL
ssh -L 15432:localhost:5432 deploy@myserver -N -f

# Forward Grafana dashboard (port 3000)
ssh -L 13000:localhost:3000 deploy@myserver -N -f

# -N: không execute command (chỉ tunnel)
# -f: chạy background

# Để stop tunnel
# Tìm process ID
ps aux | grep ssh
kill 

SOCKS5 Proxy (Route toàn bộ traffic qua server)

# Tạo SOCKS5 proxy qua SSH
ssh -D 1080 deploy@myserver -N -f

# Sau đó set browser proxy: localhost:1080 SOCKS5
# Toàn bộ traffic browser sẽ route qua server

Bước 8: Monitoring và Audit SSH Access

# Xem tất cả login thành công
sudo grep "Accepted" /var/log/auth.log

# Xem failed attempts gần đây
sudo grep "Failed password" /var/log/auth.log | tail -20

# Xem ai đang SSH vào server ngay lúc này
who
w

# Xem lịch sử login
last -a | head -20

# Xem các session đang active
sudo ss -tnp | grep ssh

# Script monitor: alert khi có login mới
# Thêm vào /etc/ssh/sshrc (chạy khi user SSH vào)

Script Alert Email Khi Có SSH Login

# Tạo file /etc/ssh/sshrc
sudo nano /etc/ssh/sshrc
#!/bin/bash
# /etc/ssh/sshrc - Chạy mỗi khi có SSH login thành công

IP=$(echo $SSH_CONNECTION | awk '{print $1}')
HOSTNAME=$(hostname)
USER=$(whoami)
DATE=$(date '+%Y-%m-%d %H:%M:%S')

# Gửi notification (thay bằng webhook URL của bạn)
curl -s -X POST "https://hooks.slack.com/YOUR_WEBHOOK" \
  -H 'Content-type: application/json' \
  --data "{\"text\":\"SSH Login: $USER@$HOSTNAME from $IP at $DATE\"}"

# Hoặc gửi email
# echo "SSH Login: $USER from $IP at $DATE" | \
#   mail -s "SSH Alert: $HOSTNAME" [email protected]
# Set permission
sudo chmod 644 /etc/ssh/sshrc

Checklist Kiểm Tra Sau Khi Cấu Hình

Chạy lệnh này để check nhanh toàn bộ config SSH hiện tại:

#!/bin/bash
# SSH Security Check Script

echo "=== SSH Security Audit ==="
echo ""

# Check port
PORT=$(grep "^Port" /etc/ssh/sshd_config | awk '{print $2}')
echo "SSH Port: ${PORT:-22}"
[ "${PORT:-22}" == "22" ] && echo "  ⚠ WARNING: Using default port 22" || echo "  ✓ Custom port configured"

# Check root login
ROOT=$(grep "^PermitRootLogin" /etc/ssh/sshd_config | awk '{print $2}')
[ "$ROOT" == "no" ] && echo "  ✓ Root login disabled" || echo "  ⚠ WARNING: Root login is ${ROOT:-not explicitly disabled}"

# Check password auth
PASS=$(grep "^PasswordAuthentication" /etc/ssh/sshd_config | awk '{print $2}')
[ "$PASS" == "no" ] && echo "  ✓ Password auth disabled" || echo "  ⚠ WARNING: Password authentication is ${PASS:-enabled}"

# Check fail2ban
systemctl is-active --quiet fail2ban && echo "  ✓ fail2ban running" || echo "  ⚠ WARNING: fail2ban not running"

# Check UFW
sudo ufw status | grep -q "Status: active" && echo "  ✓ UFW firewall active" || echo "  ⚠ WARNING: UFW not active"

echo ""
echo "=== Current SSH Connections ==="
who

Những Lỗi Phổ Biến Khi Cấu Hình SSH

Disable password auth trước khi verify SSH key hoạt động: Đây là lỗi phổ biến nhất và hậu quả là bị lock out hoàn toàn. Luôn test SSH key login trong một terminal mới TRƯỚC khi disable PasswordAuthentication.

Không backup sshd_config trước khi edit: Một lỗi syntax nhỏ trong sshd_config sẽ khiến SSH daemon không start được sau khi restart. Luôn chạy sudo sshd -t để validate config trước khi restart.

Quên allow port mới trong firewall trước khi đổi port: Nếu bạn đổi SSH sang port 2222 trong sshd_config nhưng quên add rule UFW cho port 2222, sau khi restart SSH bạn sẽ bị lock out.

Không add IP của mình vào ignoreip của fail2ban: Nếu bạn gõ sai password nhiều lần khi test, fail2ban có thể ban chính IP của bạn. Luôn add IP nhà và office vào ignoreip.

Để private key không có passphrase: Private key không có passphrase là một điểm thất bại duy nhất. Nếu máy tính của bạn bị stolen hoặc compromised, attacker có ngay access vào tất cả server.

Câu Hỏi Thường Gặp Về Cấu Hình SSH

Nên chọn port SSH nào thay vì port 22?

Chọn port trong range 1024-65535, tránh các port phổ biến như 2222 (cũng được scan nhiều), 8022, 9022. Một số người chọn port ngẫu nhiên như 47291 hoặc 58432. Tránh port dưới 1024 vì cần quyền root để bind. Điều quan trọng hơn là đổi port bất kỳ giá trị nào cũng giảm đáng kể automated scan noise, nhưng security chính vẫn phải đến từ SSH key và fail2ban.

Ed25519 hay RSA 4096 an toàn hơn cho SSH key?

Ed25519 được khuyến nghị hơn RSA 4096 trong hầu hết trường hợp năm 2026. Ed25519 dùng elliptic curve cryptography, key ngắn hơn (256-bit) nhưng bảo mật tương đương hoặc tốt hơn RSA 4096, nhanh hơn trong authentication, và ít dễ bị tấn công side-channel hơn. Chỉ dùng RSA 4096 nếu cần tương thích với hệ thống cũ không hỗ trợ Ed25519.

Làm thế nào nếu bị lock out khỏi server vì sai cấu hình SSH?

Hầu hết VPS provider (DigitalOcean, Vultr, Linode, AWS, GCP) có tính năng Console Access hoặc Recovery Console trong dashboard, cho phép bạn access server qua browser mà không cần SSH. Từ đây bạn có thể edit sshd_config để sửa lỗi, restart SSH service, hoặc khôi phục từ backup. Với server bare-metal, bạn cần access vật lý hoặc IPMI/iDRAC remote console.

Có cần dùng fail2ban nếu đã disable password authentication?

Vẫn nên dùng fail2ban dù đã disable password auth. Lý do: (1) fail2ban block các scan attempt ngay cả với key-based auth, giảm noise trong log, (2) bảo vệ các service khác ngoài SSH như Apache, Nginx, (3) nếu sau này bạn hoặc ai đó vô tình enable password auth lại, fail2ban vẫn bảo vệ, (4) overhead của fail2ban rất nhỏ so với lợi ích bảo mật.

Nên quản lý SSH key như thế nào khi có nhiều server và nhiều developer?

Với team nhỏ (dưới 10 người): mỗi developer có key riêng, add public key của họ vào authorized_keys của từng server theo cách thủ công hoặc qua Ansible. Với team lớn hơn: dùng công cụ như HashiCorp Vault SSH Secrets Engine, Teleport, hoặc AWS Systems Manager Session Manager để quản lý access tập trung, có audit log, và revoke access ngay lập tức khi cần. Không bao giờ share private key giữa các developer.

Kết Luận

Cấu hình SSH đúng cách không tốn nhiều thời gian, thường chỉ 30-60 phút cho một server mới, nhưng hệ quả của việc bỏ qua có thể là mất toàn bộ data, server bị dùng để tấn công người khác, hoặc bị tính tiền compute khổng lồ vì botnet crypto-mining. Không có trade-off nào ở đây.

Thứ tự ưu tiên nếu bạn chỉ có 15 phút: (1) Tạo SSH key và disable password auth, (2) Disable root login, (3) Cài fail2ban với config mặc định. Ba bước này đã giải quyết 95% attack vector phổ biến nhất. Còn lại như đổi port, 2FA, bastion host là hardening thêm cho môi trường production critical.

Server của bạn đang bị scan ngay lúc này. Câu hỏi không phải là liệu ai đó có đang cố gắng vào hay không, mà là khi họ thành công thì hậu quả sẽ là gì. Với cấu hình SSH đúng, câu trả lời là không có gì cả.

Author
Lê Minh Trung

Kỹ sư phần mềm

Kỹ sư phần mềm cao cấp & người đam mê công nghệ. Chia sẻ những kinh nghiệm thực tiễn từ hơn 5 năm xây dựng các sản phẩm kỹ thuật số.

Hỗ trợ Zalo Zalo Hỗ trợ Telegram Telegram Gọi cho tôi Phone Gửi Email Email
Bot
Assistant
Online
Hello! I'm the portfolio chatbot. Feel free to ask me anything 😊