Chống DDoS & Rate Limiting Nginx Trên VPS - Bảo Vệ Website Khỏi Bot Xấu & Brute Force

📅 05/2026 · ⏱ 12 phút đọc · 🏷 Bảo Mật

Website WordPress của bạn bị bot Trung Quốc, Nga, Mỹ quét xmlrpc.php 5 lần/giây? Có ai đó đang brute force wp-login.php với 1000 request/phút? Server load lên 100% vì 1 con bot? Rate limiting trong Nginx chính là firewall layer 7 — chặn đứng kiểu tấn công này mà không cần CloudFlare, không tốn thêm 1 đồng nào. Chỉ cần vài dòng config trên VPS TrumVPS của bạn.

Tại Sao Cần Rate Limiting?

Hầu hết các cuộc tấn công vào website nhỏ/medium không phải DDoS 100Gbps từ botnet lớn. Đó là các "DDoS mini" — 1-2 script tự động spam request vào endpoint yếu:

💡 Rate limiting không thay thế CloudFlare — nhưng nó bảo vệ bạn ở layer 7 (HTTP), chính là nơi CloudFlare không giúp được nếu attacker biết IP thật của VPS. Đây là lớp phòng thủ cuối cùng trước khi request chạm vào ứng dụng.

Các Module Rate Limiting Trong Nginx

Nginx có 2 module chính để giới hạn request:

ModuleCông DụngKhi Nào Dùng
limit_req_zoneGiới hạn số request/giây từ 1 IPChống burst traffic, HTTP flood
limit_conn_zoneGiới hạn số kết nối đồng thời từ 1 IPChống connection flooding

Bước 1: Cấu Hình Rate Limiting Cơ Bản

Mở file cấu hình Nginx chính:

sudo nano /etc/nginx/nginx.conf

Thêm vào trong block http {}:

http {
    # Định nghĩa zone rate limiting
    # $binary_remote_addr = key theo IP client (4 bytes thay vì 7-15 bytes của $remote_addr)
    # zone=mylimit:10m = tên zone, 10MB bộ nhớ (đủ cho ~160K IP)
    # rate=10r/s = tối đa 10 request/giây/IP
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;

    # Zone riêng cho login (nghiêm ngặt hơn)
    limit_req_zone $binary_remote_addr zone=loginlimit:10m rate=3r/m;

    # Giới hạn kết nối đồng thời
    limit_conn_zone $binary_remote_addr zone=connlimit:10m;

    ... # các config còn lại
}
⚠️ Cẩn thận với rate quá thấp! Nếu đặt rate=1r/s cho toàn bộ site, 1 trang HTML tải 5 file CSS/JS/ảnh cùng lúc sẽ bị chặn. Luôn kiểm tra thực tế trước khi áp dụng!

Bước 2: Áp Dụng Rate Limit Vào Website

Mở file config site của bạn:

sudo nano /etc/nginx/sites-available/yoursite.com

Giới hạn toàn bộ site:

server {
    listen 80;
    server_name yoursite.com;

    # Áp dụng rate limit cho tất cả request
    location / {
        limit_req zone=mylimit burst=20 nodelay;
        limit_conn connlimit 10;
        # ... proxy_pass hoặc root config
    }
}

Giải thích:

Giới hạn nghiêm ngặt cho WordPress login:

# Chặn brute force wp-login.php - chỉ 3 request/phút
location = /wp-login.php {
    limit_req zone=loginlimit burst=2 nodelay;
    limit_conn connlimit 2;
    include fastcgi_params;
    # ... fastcgi pass config
}

Chặn spam xmlrpc.php:

# Chặn hoàn toàn xmlrpc.php nếu không dùng
location = /xmlrpc.php {
    deny all;
    return 403;
}

# Hoặc rate limit nếu vẫn cần dùng
location = /xmlrpc.php {
    limit_req zone=loginlimit burst=1 nodelay;
    include fastcgi_params;
}
🔥 90% WordPress site không cần xmlrpc.php! Nếu bạn không dùng WordPress mobile app hay Jetpack, hãy chặn hoàn toàn endpoint này. Botnet thường xuyên quét xmlrpc.php để DDoS hoặc brute force.

Bước 3: Chặn Bot & User-Agent Xấu

Nhiều bot không dùng IP cố định — chúng thay IP liên tục. Rate limiting theo IP không đủ. Cần chặn theo User-Agent:

Thêm vào /etc/nginx/conf.d/block-bots.conf:

# Map user-agent xấu → block
map $http_user_agent $bad_bot {
    default 0;
    ~*scrapy          1;
    ~*curl            1;
    ~*wget            1;
    ~*python-requests 1;
    ~*go-http-client  1;
    ~*zgrab           1;
    ~*masscan         1;
    ~*nmap            1;
    ~*sqlmap          1;
    ~*nikto           1;
    ~*acunetix        1;
    ~*nessus          1;
    ~*openvas         1;
    ~*MJ12bot         1;
    ~*DotBot          1;   # AI scraper
    ~*GPTBot          1;   # OpenAI scraper
    ~*Claude           1;   # Anthropic scraper
    ~*Bytespider      1;   # ByteDance scraper
    ~*PetalBot        1;
}

Trong server block:

server {
    # Từ chối bot xấu trước khi xử lý bất kỳ request nào
    if ($bad_bot) {
        return 403;
    }
    # ... config
}

Bước 4: Giới Hạn Request Body Size

Chặn upload file quá lớn làm đầy ổ cứng:

server {
    # Giới hạn upload 10MB
    client_max_body_size 10M;
    # Giới hạn body timeout
    client_body_timeout 12;
    client_header_timeout 12;
    # ... config
}

Bước 5: Cấu Hình Fail2Ban — Tự Động Ban IP

Rate limiting trong Nginx chỉ từ chối request (trả 503). Fail2Ban đọc log Nginx, phát hiện IP vi phạm, và ban hoàn toàn IP đó bằng firewall trong X phút.

Cài Fail2Ban:

sudo apt update
sudo apt install -y fail2ban

Tạo filter cho Nginx rate limiting:

sudo nano /etc/fail2ban/filter.d/nginx-req-limit.conf
[Definition]
failregex = ^ .* limiting requests, excess:.*$
ignoreregex =

Tạo jail:

sudo nano /etc/fail2ban/jail.local
[nginx-req-limit]
enabled  = true
port     = http,https
filter   = nginx-req-limit
logpath  = /var/log/nginx/error.log
findtime = 60          # Khoảng thời gian 60 giây
maxretry = 10          # 10 lần vi phạm trong 60s → ban
bantime  = 3600        # Ban 1 giờ
action   = iptables-multiport[name=ReqLimit, port="http,https", protocol=tcp]

Thêm Fail2Ban cho WordPress:

[wp-login]
enabled  = true
port     = http,https
filter   = wp-login
logpath  = /var/log/nginx/access.log
findtime = 300
maxretry = 5           # 5 lần thử login thất bại trong 5 phút → ban
bantime  = 7200        # Ban 2 giờ

Khởi động lại:

sudo systemctl enable fail2ban --now
sudo fail2ban-client status nginx-req-limit

Bước 6: Chặn Truy Cập File Nhạy Cảm

Thêm các rule chặn truy cập file cấu hình, backup, git:

# Trong server block
location ~ /\.git {
    deny all;
    return 404;
}

location ~ \.(env|sql|log|backup|bak|old|swp|save)$ {
    deny all;
    return 404;
}

location ~ /\.well-known {
    # Cho phép Let's Encrypt
    allow all;
}

# Ẩn header Nginx version
server_tokens off;

# Chặn clickjacking
add_header X-Frame-Options "SAMEORIGIN" always;

# Chặn MIME sniffing
add_header X-Content-Type-Options "nosniff" always;

# Enable HSTS (nếu đã có SSL)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

Bước 7: Giám Sát & Kiểm Tra

Xem IP nào đang bị rate limit:

sudo tail -f /var/log/nginx/error.log | grep "limiting requests"

Xem IP nào đang bị Fail2Ban ban:

sudo fail2ban-client status nginx-req-limit
sudo iptables -L -n | grep ReqLimit

Unban 1 IP (nếu lỡ ban nhầm):

sudo fail2ban-client set nginx-req-limit unbanip 1.2.3.4

Kiểm tra rate limit có hoạt động không:

# Gửi 20 request trong 1 giây để test
for i in {1..20}; do curl -s -o /dev/null -w "%{http_code}\n" https://yoursite.com & done; wait

Nếu thấy xen kẽ 200 và 503 → rate limiting đang hoạt động!

⚠️ Đừng lock chính mình! Thêm IP của bạn vào whitelist Fail2Ban nếu bạn hay test hoặc có cron job gọi API nội bộ: sudo nano /etc/fail2ban/jail.local → thêm dòng ignoreip = 127.0.0.1/8 ::1 YOUR-IP

Tổng Hợp Cấu Hình Chuẩn Cho WordPress Trên VPS

Đây là template hoàn chỉnh cho 1 WordPress site đã được bảo vệ:

# /etc/nginx/sites-available/yoursite.com

server {
    listen 443 ssl http2;
    server_name yoursite.com www.yoursite.com;

    # === SECURITY HEADERS ===
    server_tokens off;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Strict-Transport-Security "max-age=31536000" always;

    # === RATE LIMITING ===
    # Toàn trang: 10 req/s, burst 20
    location / {
        limit_req zone=mylimit burst=20 nodelay;
        limit_conn connlimit 10;
        try_files $uri $uri/ /index.php?$args;
    }

    # Login: 3 req/phút
    location = /wp-login.php {
        limit_req zone=loginlimit burst=2 nodelay;
        limit_conn connlimit 2;
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    }

    # Chặn xmlrpc hoàn toàn
    location = /xmlrpc.php {
        deny all;
        return 403;
    }

    # Chặn file nhạy cảm
    location ~ /\.git { deny all; }
    location ~ \.(env|sql|backup|bak|save)$ { deny all; }

    # Giới hạn upload
    client_max_body_size 10M;
    client_body_timeout 12;

    # === FASTCGI ===
    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
    }

    # === SSL ===
    ssl_certificate /etc/letsencrypt/live/yoursite.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yoursite.com/privkey.pem;
}

# Redirect HTTP → HTTPS
server {
    listen 80;
    server_name yoursite.com www.yoursite.com;
    return 301 https://$server_name$request_uri;
}

Nginx Rate Limiting vs CloudFlare: Khi Nào Dùng Cái Nào?

Lớp bảo vệCông CụPhù Hợp Khi
Lớp 1 (Edge)CloudFlare FreeGiấu IP thật, chống DDoS volumetric, CDN cache
Lớp 2 (Server)Nginx Rate LimitBiết IP thật (bot bypass CloudFlare), bảo vệ endpoint cụ thể
Lớp 3 (Server)Fail2BanKhi cần ban cả IP bằng firewall, không chỉ chặn HTTP
Lớp 4 (App)WordPress pluginBảo vệ logic ứng dụng, captcha, 2FA
🔥 Chiến lược tối ưu: CloudFlare (miễn phí) che IP + Nginx rate limiting (miễn phí) bảo vệ endpoint + Fail2Ban (miễn phí) tự động ban. Tổng chi phí: 0 đồng. Bảo vệ: 3 lớp. Ai bảo bảo mật phải tốn tiền?

Kết Luận

Rate limiting trong Nginx là 1 kỹ năng bảo mật cơ bản mà mọi chủ VPS nên biết. Chỉ cần copy-paste vài dòng config trong bài này, website WordPress của bạn đã được bảo vệ khỏi 80% các cuộc tấn công layer 7 phổ biến nhất.

Với VPS TrumVPS từ 40K/tháng, bạn hoàn toàn có thể cấu hình Nginx + Fail2Ban + CloudFlare tạo thành "pháo đài" bảo mật website mà không tốn thêm bất kỳ chi phí nào cho dịch vụ bảo mật bên ngoài.

Cần VPS để thực hành bảo mật ngay?

VPS TrumVPS từ 40K/tháng - NVMe SSD - IP sạch - Thoải mái test rate limiting

Mã giảm giá: 42089QPI03TI (-9%)

🚀 THUÊ VPS NGAY