VPS & Hosting cho người Việt

Phục Hồi VPS Sau Khi Bị Hack: Chuyện Thật Của Tôi & Quy Trình Cứu Server Từng Bước

🔴 Cảnh báo: Bài này kể chuyện thật. VPS production của tôi bị hack năm 2024 vì một lỗi ngu ngốc: mở port 22 ra internet với root password 8 ký tự. Hậu quả: mất 3 ngày dữ liệu, client báo cáo downtime, tổng thiệt hại ~5 triệu đồng. Nhưng quan trọng hơn — tôi đã cứu được server và không để mất toàn bộ dữ liệu. Đây là cách tôi làm.

2h Sáng, Tin Nhắn "Anh Ơi Web Chết Rồi"

Tháng 5/2024, 2h sáng. Tôi đang ngủ thì điện thoại rung liên hồi. Client nhắn: "Anh ơi web chết rồi, vào toàn thấy blank page." Tôi mở laptop, thử SSH — không vào được. Ping thì VPS vẫn sống. Mở browser gõ URL → redirect sang một trang web cờ bạc Trung Quốc.

Tim tôi đập thình thịch. Đây không phải lần đầu tôi thấy dấu hiệu VPS bị hack, nhưng là lần đầu nó xảy ra với production server có khách hàng thật.

Mất 5 phút để bình tĩnh. Rồi tôi làm theo đúng quy trình mình đã chuẩn bị sẵn (may là có chuẩn bị). Sau 4 tiếng, server hoạt động trở lại. Sau 48 tiếng, mọi thứ như cũ.

Đây là toàn bộ quy trình — 15 bước tôi đã làm, từ phát hiện đến khôi phục hoàn toàn.

Giai Đoạn 1: Phát Hiện & Đánh Giá Thiệt Hại (30 Phút Đầu)

Bước 1: Đừng Hoảng — Đây Là Lúc Cần Tỉnh Táo Nhất

Nghe sáo rỗng nhưng thật. Khi bị hack, não bạn sẽ chạy đua: "Xóa hết đi cài lại ngay!" — đừng làm thế. Xóa vội vàng là mất hết bằng chứng, không biết hacker vào bằng cách nào, và có thể lỗ hổng vẫn còn sau khi cài lại.

⚠️ Bẫy #1: "Xóa sạch cài lại ngay" — Đây là phản xạ tự nhiên nhưng cực kỳ nguy hiểm. Cài lại OS mà không biết hacker vào bằng cách nào = 90% sẽ bị hack lại trong 24h. Luôn điều tra nguyên nhân trước khi format.

Bước 2: Cô Lập Server — Cắt Kết Nối Mạng Nhưng ĐỪNG Tắt Nguồn

Việc đầu tiên: vào control panel của provider, block tất cả network ra/vào server. Đừng tắt nguồn — nếu tắt, bạn mất toàn bộ dữ liệu trong RAM (process list, network connections, bash history của hacker).

# Trên control panel provider (Netihot/Tino/TrumVPS):
# Networking → Firewall → Block ALL inbound + outbound
# HOẶC: tạm thời detach public IP

# Nếu vẫn SSH được (qua console VNC của provider), làm nhanh:
# 1. Chặn tất cả input/output
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

# 2. Chỉ cho phép loopback (process nội bộ)
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

Bước 3: Thu Thập Bằng Chứng Trước Khi Động Vào Gì

Đây là bước quan trọng nhất. Bạn cần biết hacker đã làm gì, vào bằng cách nào, và có để lại backdoor không.

# === FORENSICS CHECKLIST ===

# 1. Ai đang login?
w
last -20
lastb -20  # failed login attempts

# 2. Process nào đang chạy? Có gì lạ không?
ps auxf
# Tìm process ẩn: ps auxf | grep -v "\[" | grep -v grep

# 3. Network connections — hacker đang kết nối đến đâu?
ss -tunap
netstat -tunap 2>/dev/null

# 4. Lịch sử command — hacker đã chạy lệnh gì?
cat /root/.bash_history | tail -100
cat /home/*/.bash_history | tail -100
# Kiểm tra history đã bị xóa chưa:
ls -la /root/.bash_history  # size = 0 nếu bị xóa

# 5. File mới tạo trong 24h qua?
find / -type f -mtime -1 -ls 2>/dev/null | head -50
# Tập trung vào: /tmp, /var/tmp, /dev/shm, /root

# 6. Cron job lạ?
crontab -l
cat /etc/crontab
ls -la /etc/cron.*/
# Hacker hay giấu backdoor trong cron

# 7. SSH key lạ?
cat /root/.ssh/authorized_keys
cat /home/*/.ssh/authorized_keys 2>/dev/null

# 8. User mới được tạo?
cat /etc/passwd | grep -v nologin | grep -v false
lastlog

# 9. Web shell / file uploads suspicious?
find /var/www -name "*.php" -mtime -7 -ls 2>/dev/null
find /var/www -name "*.jsp" -o -name "*.war" -o -name "*.cgi" 2>/dev/null

Kết quả forensics trên server của tôi:

Giai Đoạn 2: Backup Dữ Liệu An Toàn (1-2 Tiếng)

Trước khi làm gì khác, backup mọi thứ ra ngoài server. Tuyệt đối không backup vào chính server đó — hacker có thể có script giám sát và xóa backup của bạn.

Bước 4: Backup Database

# MySQL/MariaDB
mysqldump --all-databases --single-transaction --quick \
  > /tmp/full-backup-$(date +%Y%m%d).sql

# PostgreSQL
pg_dumpall -U postgres > /tmp/full-backup-$(date +%Y%m%d).sql

# Copy ra máy local (mở tạm output cho IP của bạn)
# Trên control panel: allow outbound to your IP
scp root@vps:/tmp/full-backup-*.sql ~/backups/

Bước 5: Backup Source Code & Config

# Backup toàn bộ /etc (config files quan trọng)
tar czf /tmp/etc-backup-$(date +%Y%m%d).tar.gz /etc

# Backup web root
tar czf /tmp/www-backup-$(date +%Y%m%d).tar.gz /var/www

# Backup home directories
tar czf /tmp/home-backup-$(date +%Y%m%d).tar.gz /home

# Copy tất cả ra máy local
scp root@vps:/tmp/*-backup-*.{sql,tar.gz} ~/backups/
⚠️ Bẫy #2: Backup file đã nhiễm malware — Tuyệt đối không import thẳng backup database/source code vào server mới. Phải audit từng file trước. Trường hợp của tôi, hacker đã nhúng backdoor PHP vào 3 file trong theme WordPress — nếu copy nguyên xi sang server mới, tôi sẽ bị hack lại.

Giai Đoạn 3: Cài Lại OS & Hardening (2-3 Tiếng)

Bước 6: Format VPS — Cài OS Mới Từ ISO Gốc Của Provider

Đây không phải lúc để "dọn dẹp". Format hoàn toàn, cài OS mới. Hacker chuyên nghiệp có thể giấu rootkit trong kernel, kernel module, thậm chí BIOS/firmware. Cách duy nhất để chắc chắn sạch là cài lại từ đầu.

# Trên control panel provider:
# VPS → Reinstall → Chọn OS (Ubuntu 22.04/24.04 LTS)
# ⚠️ CHỌN "Clean Install" — KHÔNG giữ data

# Sau khi cài xong, login qua VNC console của provider
# ĐỪNG mở SSH ra internet vội!

Bước 7: Hardening Bảo Mật — KHÔNG Lặp Lại Lỗi Cũ

Đây là bước quan trọng nhất. Nếu bạn cài lại OS rồi mở port 22 như cũ, hacker sẽ brute-force lại trong vài giờ.

#!/bin/bash
# === VPS HARDENING SCRIPT ===
# Chạy NGAY SAU KHI cài OS mới

echo "=== BƯỚC 1: Update system ==="
apt update && apt upgrade -y
apt install -y ufw fail2ban unattended-upgrades

echo "=== BƯỚC 2: Tạo user thường, KHÓA root login ==="
useradd -m -s /bin/bash deploy
mkdir -p /home/deploy/.ssh
# Copy public key của bạn vào
echo "ssh-ed25519 AAAAC3..." > /home/deploy/.ssh/authorized_keys
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.ssh

echo "=== BƯỚC 3: Cấu hình SSH cứng ==="
cat > /etc/ssh/sshd_config.d/99-hardening.conf << 'SSHCONF'
# KHÔNG cho root login
PermitRootLogin no
# CHỈ cho phép SSH key (không password)
PasswordAuthentication no
PubkeyAuthentication yes
# Đổi port mặc định
Port 2222
# Giới hạn user được SSH
AllowUsers deploy
# Timeout idle
ClientAliveInterval 300
ClientAliveCountMax 0
# Không cho phép empty password
PermitEmptyPasswords no
# Giới hạn số lần thử auth
MaxAuthTries 3
MaxSessions 2
SSHCONF
systemctl restart sshd

echo "=== BƯỚC 4: Firewall — chỉ mở port cần thiết ==="
ufw default deny incoming
ufw default allow outgoing
ufw allow 2222/tcp    # SSH port mới
ufw allow 80/tcp      # HTTP
ufw allow 443/tcp     # HTTPS
# KHÔNG mở port database ra ngoài!
ufw --force enable

echo "=== BƯỚC 5: Fail2ban chống brute-force ==="
cat > /etc/fail2ban/jail.local << 'F2BCONF'
[sshd]
enabled = true
port = 2222
maxretry = 3
bantime = 3600
findtime = 600
F2BCONF
systemctl enable --now fail2ban

echo "=== BƯỚC 6: Auto security updates ==="
cat > /etc/apt/apt.conf.d/20auto-upgrades << 'APTUP'
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutocleanInterval "7";
APTUP

echo "=== BƯỚC 7: Audit cuối cùng ==="
# Kiểm tra port đang mở
ss -tlnp
# Kiểm tra SSH config
sshd -t
# Kiểm tra fail2ban
fail2ban-client status sshd

echo "=== ✅ HARDENING HOÀN TẤT ==="
💡 Mẹo: Sau khi hardening, test thử xem SSH password còn hoạt động không. Nếu có — bạn cấu hình sai. Nếu bị lock out, dùng VNC console của provider để vào sửa.

Bước 8: Audit Source Code Trước Khi Deploy Lại

Đây là bước tôi suýt bỏ qua, và nếu bỏ qua thì đã bị hack lại. Hacker đã nhúng backdoor PHP vào 3 file trong theme WordPress. Tôi phải audit từng file một.

# Tìm backdoor PHP phổ biến
# Trong thư mục source code đã backup:

# 1. Tìm eval/base64/gzinflate (obfuscation phổ biến)
grep -r "eval(" . --include="*.php" | grep -v vendor
grep -r "base64_decode" . --include="*.php" | grep -v vendor
grep -r "gzinflate" . --include="*.php" | grep -v vendor

# 2. Tìm hàm system execution
grep -rE "(exec|shell_exec|system|passthru)\s*\(" . --include="*.php" | grep -v vendor

# 3. Tìm file mới/chỉnh sửa gần đây (từ ngày bị hack)
find . -name "*.php" -newer ./wp-config.php -ls

# 4. Tìm file ẩn (bắt đầu bằng dấu chấm)
find . -name ".*" -type f -ls

# 5. So sánh với bản sạch (nếu dùng WordPress)
# Download WordPress cùng version, diff từng file
diff -rq ./wp-admin /tmp/wordpress-clean/wp-admin

Giai Đoạn 4: Khôi Phục Dịch Vụ (1-2 Tiếng)

Bước 9: Deploy Lại Từng Service Một — Test Từng Cái

Đừng vội vàng deploy hết một lần. Làm từng service, test từng cái:

  1. Database trước — restore DB, check integrity, đổi toàn bộ password
  2. Web server — cài nginx/apache, test static page trước
  3. Application — deploy code đã audit, test từng endpoint
  4. Cron jobs — chỉ restore cron bạn nhận ra, bỏ hết cron lạ
  5. SSL — cài cert mới (đừng copy cert cũ từ server bị hack)
# Kiểm tra database integrity trước khi import
mysqlcheck -u root -p --all-databases --check --auto-repair

# Sau khi restore, ĐỔI TOÀN BỘ PASSWORD
# Database users
ALTER USER 'wp_user'@'localhost' IDENTIFIED BY 'new-strong-password-here';
# Application secrets
# Regenerate: wp-config.php salts, .env keys, JWT secrets, API keys
# FLUSH PRIVILEGES;

Bước 10: Setup Monitoring — Phát Hiện Sớm Lần Sau

# Cài đặt monitoring cơ bản (15 phút)
# 1. Uptime Kuma — theo dõi uptime + SSL expiry
docker run -d --name uptime-kuma \
  -p 3001:3001 \
  -v uptime-kuma:/app/data \
  --restart unless-stopped \
  louislam/uptime-kuma

# 2. Netdata — real-time system monitoring
bash <(curl -Ss https://my-netdata.io/kickstart.sh) \
  --disable-telemetry

# 3. Logwatch — daily security report qua email
apt install logwatch -y
# Sẽ gửi email hàng ngày tóm tắt: failed logins, sudo usage, disk, etc.

# 4. Teleport alert cho suspicious activity
# File: /root/security-alert.sh
#!/bin/bash
# Gửi Telegram alert nếu có login SSH thành công
tail -f /var/log/auth.log | grep --line-buffered "Accepted publickey" | while read line; do
  curl -s "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
    -d "chat_id=${CHAT_ID}" \
    -d "text=🔑 SSH Login: $line"
done

Giai Đoạn 5: Hậu Kiểm & Bài Học (Sau 48h)

Bước 11: Đổi Toàn Bộ Mật Khẩu & Key Liên Quan

Không chỉ password trên VPS đó — đổi hết:

Bước 12: Báo Cáo Sự Cố Cho Các Bên Liên Quan

Nếu bạn có khách hàng trên server đó:

Checklist 15 Bước Cứu VPS Bị Hack

In ra dán lên tường — khi bị hack bạn sẽ cần nó:

  1. ☐ Bình tĩnh — đừng xóa gì vội
  2. ☐ Cô lập server (block network, không tắt nguồn)
  3. ☐ Forensics: process list, network connections, auth logs, bash history, cron
  4. ☐ Xác định nguyên nhân + thời gian xâm nhập
  5. ☐ Backup database ra ngoài server
  6. ☐ Backup source code + config ra ngoài server
  7. ☐ Format VPS, cài OS mới từ ISO gốc
  8. ☐ Hardening: SSH key-only, non-root user, đổi port, fail2ban, ufw
  9. ☐ Audit source code: tìm backdoor, web shell
  10. ☐ Restore database + đổi toàn bộ password
  11. ☐ Deploy app từ code đã audit
  12. ☐ Setup monitoring (Uptime Kuma + Telegram alert)
  13. ☐ Đổi toàn bộ password/keys liên quan
  14. ☐ Báo cáo cho stakeholders
  15. ☐ Viết post-mortem: nguyên nhân, timeline, bài học, action items

Chi Phí Thực Tế Của Một Vụ Hack

Nhiều người nghĩ "VPS rẻ mà, cùng lắm cài lại". Nhưng chi phí thật không chỉ là tiền VPS:

Loại Thiệt HạiTrường Hợp Của TôiƯớc Tính
Downtime (4 tiếng)Khách hàng báo cáo, SEO bị ảnh hưởng~1.5 triệu (thiệt hại gián tiếp)
Mất dữ liệu3 ngày dữ liệu (backup daily nên mất ít)~500K (thời gian nhập lại)
Thời gian phục hồi12 tiếng làm việc (2 ngày)~2 triệu (nếu tính công 200K/h)
Uy tín1 khách hủy hợp đồng~1 triệu/tháng mất đi
Tổng thiệt hại ước tính~5 triệu

So với chi phí hardening ban đầu (2-3 tiếng làm + dùng VPS có backup snapshot tự động như Tino Group ~200K/tháng), bài học quá rõ ràng.

Phòng Chống: Những Gì Tôi Làm Khác Sau Vụ Hack

1. Không Bao Giờ Dùng Password Cho SSH Nữa

SSH key-only. Ed25519, không RSA. Passphrase cho private key. Không có ngoại lệ.

2. Port 22 Không Bao Giờ Mở Ra Internet

Hoặc đổi port (2222, 22222), hoặc dùng Cloudflare Tunnel, hoặc whitelist IP tĩnh của bạn. Tôi chọn giải pháp: Cloudflare Tunnel — không cần mở port nào ra internet, SSH qua tunnel.

# Cloudflare Tunnel cho SSH
# Cài cloudflared
curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared
chmod +x /usr/local/bin/cloudflared

# Tạo tunnel
cloudflared tunnel login
cloudflared tunnel create my-vps

# Config file: ~/.cloudflared/config.yml
# tunnel: <tunnel-id>
# credentials-file: /root/.cloudflared/<tunnel-id>.json
# ingress:
#   - hostname: ssh.mydomain.com
#     service: ssh://localhost:22
#   - service: http_status:404

cloudflared tunnel run my-vps
# Giờ SSH qua: ssh user@ssh.mydomain.com (qua Cloudflare)

3. Backup Tự Động Hàng Ngày — Không Khoan Nhượng

Tôi setup cron backup database + source code ra Cloudflare R2 (10GB free) mỗi đêm. Mất 30 phút setup, cứu tôi khỏi mất dữ liệu hoàn toàn.

Xem thêm: Backup VPS tự động với Restic + Backblaze B2Cài Cloudflare Tunnel cho VPS.

4. Dùng VPS Có Snapshot Tự Động

Nếu provider bạn hỗ trợ snapshot (như Tino Group), bật auto-snapshot hàng ngày. Khi bị hack, bạn rollback về snapshot sạch trong 5 phút thay vì cài lại toàn bộ.

5. Security Audit Định Kỳ

Mỗi tháng 1 lần, tôi chạy script audit toàn bộ VPS:

#!/bin/bash
# security-audit.sh — chạy monthly
echo "=== OPEN PORTS ===" && ss -tlnp
echo "=== FAILED LOGINS (30d) ===" && lastb -s -30days | wc -l
echo "=== USERS WITH SHELL ===" && grep -v nologin /etc/passwd | grep -v false
echo "=== CRON JOBS ===" && for u in $(cut -f1 -d: /etc/passwd); do crontab -u $u -l 2>/dev/null; done
echo "=== LISTENING SERVICES ===" && systemctl list-units --type=service --state=running
echo "=== DISK USAGE ===" && df -h
echo "=== UPDATES AVAILABLE ===" && apt list --upgradable 2>/dev/null | wc -l
echo "=== FAIL2BAN STATUS ===" && fail2ban-client status

Tổng Kết

Bị hack không phải là "nếu" mà là "khi nào". Sớm hay muộn, VPS của bạn cũng sẽ bị quét. Điều khác biệt là bạn có chuẩn bị trước hay không.

Ba điều quan trọng nhất tôi rút ra sau vụ hack:

  1. Backup là thứ duy nhất cứu bạn. Không backup = mất trắng. Backup daily ra ngoài server.
  2. SSH key-only, không password, không root. 90% VPS bị hack là qua SSH brute-force. Tắt password auth đi.
  3. Monitoring để biết sớm. Nếu tôi có Telegram alert khi có SSH login lạ, tôi đã phát hiện vụ hack trong 5 phút đầu thay vì 3 tiếng sau khi client báo.

VPS rẻ nhất hiện nay có giá từ 47K/tháng với NAT VPS (Netihot), 150K/tháng cho VPS IP riêng có snapshot (Tino Group). So với thiệt hại 5 triệu cho một vụ hack, vài trăm nghìn mỗi tháng cho backup + monitoring là khoản đầu tư rẻ nhất bạn từng bỏ ra.

Đọc thêm: Bảo mật VPS cho người mới, Cài Fail2ban chống brute-force, Bảo mật VPS toàn tập.

🛡️ VPS Bảo Mật, Backup Tự Động

VPS có snapshot tự động, backup daily, hỗ trợ 24/7. Từ 47K/tháng cho NAT VPS, 150K/tháng cho VPS IP riêng.

Netihot — VPS Giá Rẻ Nhất Tino Group — Snapshot Auto

Bài viết dựa trên sự cố thực tế tháng 5/2024. Một số chi tiết đã được thay đổi để bảo vệ thông tin khách hàng. Các script và cấu hình đã được test trên Ubuntu 22.04/24.04 LTS.