4 phút đọc

App nhỏ có cần chống DDoS không

App nhỏ ít khi bị DDoS thật, nhưng một script gửi vài trăm request mỗi giây là đủ làm sập VPS 1 GB hay đẩy bill serverless lên. Bốn lớp chặn rẻ: Cloudflare phía trước, giới hạn ở reverse proxy, trang tĩnh khi API quá tải, và trần chi tiêu trên serverless.

Câu trả lời ngắn: app nhỏ hiếm khi là mục tiêu của một đợt DDoS hàng trăm Gbps. Nhưng bạn không cần bị tấn công cỡ đó mới sập. Một VPS 1 GB RAM chạy Node.js và Postgres có thể đứng hình chỉ vì vài trăm request mỗi giây vào trang tìm kiếm, từ một con bot cào dữ liệu, một đối thủ khó chịu, hay chính một vòng lặp lỗi trong app di động của bạn.

Với app chạy serverless thì chuyện ngược lại: app không sập, nó tự mở rộng và phục vụ hết, rồi gửi bill.

Nên câu hỏi đúng hơn là: lớp nào rẻ và đáng làm ngay. Có bốn lớp.

Linh vật robot cầm khiên tròn đứng cạnh hộp máy chủ nhỏ, bức tường mây chắn dòng hạt đỏ đang ào tới

1. Đặt Cloudflare (hoặc CDN) phía trước

Theo tài liệu của Cloudflare, chống DDoS được cung cấp không tính theo lưu lượng và không giới hạn cho mọi khách hàng ở mọi gói, cả tầng mạng (L3/L4) lẫn tầng HTTP (L7). Gói miễn phí cũng có. Đây là lớp rẻ nhất bạn có.

Hai chỗ hay làm sai:

  • IP gốc vẫn lộ. Nếu trước đây tên miền trỏ thẳng về VPS, IP đó nằm trong lịch sử DNS công khai, và hacker gọi thẳng vào IP là đi vòng qua Cloudflare. Sau khi đưa qua Cloudflare, cấu hình tường lửa của VPS chỉ nhận cổng 80, 443 từ dải IP của Cloudflare (danh sách ở cloudflare.com/ips). Một số bản ghi phụ như mail., ftp. trỏ thẳng về cùng IP cũng làm lộ.
  • Chỉ bật proxy cho tên miền chính. Subdomain api. để “DNS only” (đám mây xám) thì không được bảo vệ.

Cùng lúc, thêm vài rule miễn phí: rate limit cho /api/login và /api/search, bật chế độ thử thách khi đang bị dồn request.

2. Giới hạn ở reverse proxy

Cloudflare chặn được lũ lớn, nhưng một con bot gửi 50 request mỗi giây trông vẫn như người dùng bình thường. Lớp tiếp theo là Nginx (hoặc Caddy, Traefik) trước app:

# /etc/nginx/conf.d/limit.conf
limit_req_zone  $binary_remote_addr zone=api:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn:10m;

server {
  # khi đứng sau Cloudflare, lấy IP thật của người dùng thay vì IP của Cloudflare
  # set_real_ip_from <các dải IP của Cloudflare>; real_ip_header CF-Connecting-IP;

  client_max_body_size 5m;
  client_body_timeout 10s;

  location /api/ {
    limit_req  zone=api burst=20 nodelay;
    limit_conn conn 20;
    limit_req_status 429;
    proxy_pass http://127.0.0.1:3000;
  }
}

Mỗi IP được 10 request mỗi giây, dồn tối đa 20, quá thì nhận 429. Nhớ dòng set_real_ip_from khi đứng sau Cloudflare, nếu không mọi người dùng chung vài IP của Cloudflare và bị chặn lẫn nhau.

Ở tầng app, các route tốn kém (tìm kiếm, xuất file, gọi AI) cần giới hạn riêng chặt hơn, theo tài khoản chứ không chỉ theo IP.

3. Trang tĩnh khi API quá tải

Khi API đang ngộp, trang chủ, trang giá, trang giới thiệu vẫn nên mở được. Cách làm:

  • Trang marketing build tĩnh (Next.js output: 'export', Astro) và để CDN cache. Dù server app chết, khách vẫn thấy trang và số điện thoại liên hệ.
  • Đặt Cache-Control: public, s-maxage=60 cho các API công khai đọc nhiều (danh sách sản phẩm), để CDN gánh thay database.
  • Chuẩn bị sẵn một trang “đang bảo trì” tĩnh và cách bật nó trong một phút (Cloudflare có Custom Error Pages, Nginx thì error_page 502 503 504 /maintenance.html;).

4. Trần chi tiêu trên serverless

Vercel, Netlify, AWS Lambda, Cloudflare Workers đều tự mở rộng theo lưu lượng, kể cả lưu lượng rác. Lớp chặn cuối là tiền:

  • Vercel (Pro): Settings, Billing, Spend Management. Đặt mức chi, và quan trọng là bật Pause Production Deployments. Tài liệu của Vercel nói rõ đặt mức chi thôi thì không dừng được việc tiêu tiền, phải bật tạm dừng. Vercel kiểm mức chi vài phút một lần, nên tiền có thể vượt mức một chút trước khi dừng. Khi dừng, mọi project production trả lỗi 503 tới khi bạn bật lại bằng tay.
  • AWS Lambda: đặt reserved concurrency cho từng hàm để giới hạn số bản chạy cùng lúc, cộng với AWS Budgets để báo động.
  • Hàm gọi AI hay gửi email/SMS là chỗ đốt tiền nhanh nhất, cần trần riêng theo người dùng mỗi ngày ngay trong code.

Kiểm tra app của bạn trong vài phút

  1. dig +short app-cua-ban.com. Ra IP của Cloudflare (thường bắt đầu bằng 104. hoặc 172.6x.) là đã qua proxy; ra IP VPS của bạn là chưa.
  2. Từ máy ngoài, curl -I http://<IP VPS>. Trả về trang của app là IP gốc đang mở cho mọi người, cần chặn bằng tường lửa.
  3. Gửi thử 50 request liên tục vào API của chính bạn: for i in $(seq 50); do curl -s -o /dev/null -w "%{http_code}\n" https://app-cua-ban.com/api/search?q=a; done | sort | uniq -c. Không thấy 429 nào là chưa có giới hạn.
  4. Mở trang billing của nền tảng serverless, xem đã có mức chi kèm hành động dừng chưa, hay chỉ có email.

App của bạn đã từng bị một đợt request dồn dập chưa, và bạn phát hiện bằng cách nào? Vào cộng đồng Vibe Code & Bảo Mật kể cho mọi người nghe nhé.

Nguồn

Chia sẻ lên Facebook

Bình luận

Đang tải bình luận…