Ưu đãi của năm Mua 1 tháng, tặng 1 tháng Áp dụng cho mọi VPS và máy chủ riêng, với mọi thời hạn — trả 12 tháng, dùng 24 tháng. Nhân đôi thời hạn
Trang chủ / Hướng Dẫn Privacy Hosting / Chống DDoS cho VPS: nơi nhà cung cấp dừng lại, tầng 7 bắt đầu
Vận hành

Sống sót qua một cuộc tấn công DDoS trên VPS của bạn

Gói hosting nào cũng ghi "đã bao gồm chống DDoS", và tất cả đều chỉ mang cùng một nghĩa hẹp như nhau: mạng hấp thụ được các đợt lũ đo bằng gigabit. Còn các cuộc tấn công thực sự đánh sập những trang nhỏ lại đo bằng request mỗi giây, gần như không tốn kẻ tấn công đồng nào, và trông hoàn toàn hợp lệ khi ập đến. Hướng dẫn này vạch rõ ranh giới giữa hai loại đó, chỉ cách nhận biết trong chưa đầy một phút bạn đang gặp loại nào, và trình bày những gì thực sự trụ vững ở phía ranh giới thuộc về bạn.

Không KYC
Chỉ nhận Crypto
Không lưu nhật ký
Bỏ qua DMCA
Toàn quyền Root
NVMe SSD

Có hai thời điểm người ta thực sự hiểu cách chống DDoS hoạt động. Thời điểm đầu diễn ra bình thản, lúc mua hàng, khi đọc một danh sách tính năng ghi "đã bao gồm chống DDoS" rồi lặng lẽ mặc định rằng câu đó bao trùm tất cả. Thời điểm thứ hai là lúc ba giờ sáng, khi trang web đã sập, các biểu đồ trông sai một cách vô lý, và lớp bảo vệ "đã bao gồm" đó — đúng như thiết kế của nó — chẳng làm gì cả.

Cả hai thời điểm đều xoay quanh cùng một sản phẩm và cùng một sự thật: nhà cung cấp hosting lọc được các cuộc tấn công đến dưới dạng khối lượng thô, vì họ sở hữu đường truyền mà các gói tin đó đi qua, còn bạn thì không. Họ không thể lọc được các cuộc tấn công đến dưới dạng request trông bình thường, vì dưới góc nhìn của mạng, đó đúng là những request bình thường. Ranh giới đó — giữa đợt lũ mà host của bạn hấp thụ và đợt lũ mà chính bạn phải tự mình sống sót qua — là toàn bộ chủ đề của bài này. Mọi thứ bên dưới đây là để xác định bạn đang đứng ở phía nào của ranh giới đó, và phải làm gì ở mỗi phía.

Hai kiểu tấn công khác nhau chung một cái tên

"DDoS" là một từ dùng chung cho hai vấn đề gần như chẳng có điểm nào giống nhau ngoài hậu quả. Chúng bị chặn ở hai nơi khác nhau, bởi hai nhóm người khác nhau, bằng hai bộ công cụ khác nhau, và việc nhầm lẫn giữa chúng chính là lý do phần lớn công sức chống đỡ lại đổ nhầm vào tầng.

Khối lượng lớn — tầng 3 và 4Ứng dụng — tầng 7
Thứ ập đếnSYN flood, khuếch đại UDP qua các reflector DNS, NTP hay memcached để ngỏ, ACK flood, các gói tin rác thuần túyCác request HTTP trông bình thường: GET flood, POST flood, slow-loris, chuỗi query phá cache
Đo bằngGigabit và hàng triệu gói tin mỗi giâyRequest mỗi giây — thường chỉ vài nghìn
Băng thông cần để gây hại cho bạnCực lớn. Đây là một cuộc thi về năng lựcGần như không cần gì. Một chiếc laptop cũng đủ nếu endpoint đủ đắt đỏ
Nơi phải chặn nó lạiỞ thượng nguồn, bởi nhà cung cấp của bạn. Vì khi gói tin chạm tới cổng của bạn thì thiệt hại đã xảy ra rồiTrên server của bạn, bởi chính bạn, hoặc trên một proxy do bạn kiểm soát đặt trước nó
Trông ra sao trên máyInterface bão hòa, bộ đếm gói tin phi lý, CPU có thể vẫn rảnhBăng thông khiêm tốn, nhưng mọi worker đều bận, load tăng dần, hàng đợi database phình to
Ai xử lý nóScrubbing của host bạn, tự động, thường chỉ trong vài giâyCấu hình của bạn — giới hạn tốc độ, cache, giới hạn kết nối

Hãy đọc lại hai hàng cuối, vì chúng chứa đựng điểm mấu chốt thực tế. Nếu interface đã bão hòa, có gõ gì vào server cũng vô ích: gói tin đã chiếm hết cổng rồi, và bên duy nhất có thể loại bỏ chúng là bên sở hữu router ở thượng nguồn. Nếu interface vẫn im ắng mà trang web vẫn sập, điều ngược lại mới đúng — host của bạn chẳng thấy gì bất thường vì, ở tầng của họ, quả thực không có gì bất thường, và việc khắc phục hoàn toàn là việc của bạn.

Sống sót qua một cuộc tấn công DDoS trên VPS của bạn
Các đợt lũ khối lượng lớn bị lọc ở thượng nguồn, nơi có đủ năng lực để chặn chúng. Thứ sống sót qua bộ lọc đó là lưu lượng trông bình thường — và chặn nó là việc của bạn, không phải của nhà cung cấp.

"Đã bao gồm chống DDoS" thực sự mua được những gì

Bảo vệ ở tầng mạng là có thật, có giá trị, và hầu như luôn bị hiểu sai. Khi một nhà cung cấp quảng cáo lọc L3/L4, họ muốn nói rằng mạng của họ theo dõi lưu lượng hướng đến địa chỉ của bạn, và khi phát hiện một đợt lũ, lưu lượng đó được chuyển hướng qua phần cứng scrubbing để loại bỏ phần độc hại và chuyển tiếp phần trông hợp lệ. Việc này diễn ra mà không cần mở ticket hỗ trợ, và thường bạn cũng chẳng nhận ra gì ngoài một cú chớp nhoáng.

Một câu đó thôi đã gánh rất nhiều ý nghĩa, nên đáng để bóc tách xem nó bao gồm gì và không bao gồm gì:

  • Nó chặn được các cuộc tấn công mà một mình bạn không thể chống đỡ. Một đợt lũ khuếch đại 200 Gbps nhắm vào một server có cổng 1 Gbps không phải là vấn đề cấu hình. Đó là bài toán số học đơn thuần. Scrubbing ở thượng nguồn là câu trả lời duy nhất tồn tại.
  • Nó không biết gì về trạng thái ứng dụng của bạn. Bộ lọc không biết URL nào của bạn tốn kém, khách nào đã đăng nhập, hay một request tới endpoint tìm kiếm của bạn tốn gấp bốn trăm lần một request tới logo.
  • Nó phản ứng theo một ngưỡng, không theo mức độ bạn đang khổ sở. Việc phát hiện được kích hoạt dựa trên khối lượng lưu lượng. Một cuộc tấn công không bao giờ vượt ngưỡng đó sẽ không bao giờ kích hoạt nó, dù nó đã đánh sập trang của bạn triệt để đến đâu.
  • Trong trường hợp cực đoan, nó có thể null-route trong chốc lát. Mạng nào cũng có một giới hạn trên. Nếu một cuộc tấn công đe dọa hạ tầng dùng chung, địa chỉ của bạn có thể bị ngắt trong một khoảng thời gian — đây là thông lệ chuẩn, áp dụng ở khắp mọi nơi, và đáng để biết trước khi nó xảy ra hơn là biết trong lúc nó đang xảy ra.

Tóm gọn trong một dòng: host của bạn bảo vệ mạng của họ, và bạn hưởng lợi từ đó. Nó không bảo vệ ứng dụng của bạn, và cũng không có cách nào làm được điều đó. Tầng 7 không phải một gói nâng cấp bị giữ lại khỏi tay bạn — đó là một tầng mà nhà cung cấp của bạn không thể nhìn vào nếu không giải mã TLS của bạn, và với bất kỳ ai hosting offshore, đó là một sự đánh đổi có cái giá riêng rất nghiêm trọng.

Trước tiên, hãy xác định đây có thực sự là một cuộc tấn công không

Một tỷ lệ đáng kể các sự cố tưởng là DDoS thực ra là một thứ khác khoác lên chiếc áo đó, và cách khắc phục không thể dùng thay cho nhau. Trước khi giới hạn tốc độ bất cứ thứ gì, hãy dành hai phút loại trừ những kẻ mạo danh — chẩn đoán sai ở bước này tốn của bạn cả tiếng đồng hồ, và đôi khi là cả những người dùng thật của bạn.

  • Bạn nổi tiếng lên. Một liên kết trên một trang tổng hợp lớn tạo ra hình dạng lưu lượng giống hệt một đợt lũ tầng 7, chỉ khác là referrer đều có thật và các request là cho những trang một con người thực sự muốn xem. Đây là vấn đề về năng lực với một nguyên nhân đáng mừng; giới hạn tốc độ nó chẳng khác nào tự làm hại chính mình.
  • Một crawler đã mất lịch sự. Các scraper hung hãn và bot huấn luyện AI có thể dễ dàng vượt quá sức một server nhỏ. User-agent thường tự khai ra thủ phạm, và cách khắc phục là robots.txt cộng với một giới hạn nhắm đúng đối tượng, chứ không phải một giới hạn áp dụng chung.
  • Bạn đã làm hỏng thứ gì đó. Một lần deploy vô tình tắt cache, một cron job chạy mất kiểm soát, một database bị mất index — tất cả đều biểu hiện giống hệt "load tăng đột ngột, không rõ nguyên nhân". Nếu thời điểm trùng khớp với một thay đổi bạn vừa thực hiện, hãy tin vào thay đổi đó.
  • Chính hệ thống giám sát của bạn là đợt lũ. Hiếm gặp, đáng xấu hổ, và phổ biến hơn nhiều so với những gì người ta thừa nhận. Một vòng lặp health-check thử lại liên tục mà không có backoff có thể tạo ra một tốc độ request thực sự ấn tượng.

Câu hỏi để phân biệt rất đơn giản: lưu lượng này có đang muốn thứ gì đó không? Tải thật — kể cả tải thật trông có vẻ thù địch — luôn có một hình dạng nhất định. Nó chạm vào những trang thực sự tồn tại, đi theo các liên kết, tải các asset, và đến từ một dải mạng có vẻ hợp lý. Một cuộc tấn công thường chẳng buồn làm điều đó.

Đọc hiểu cuộc tấn công ngay trên server

Bạn không cần một dashboard để phân loại chuyện gì đang xảy ra. Bốn lệnh, chạy theo đúng thứ tự, sẽ cho bạn biết mình đang chống đỡ ở tầng nào trong chưa đầy một phút — và biết được điều đó quyết định mọi việc bạn làm tiếp theo.

Đường truyền có đầy không? Theo dõi bộ đếm của interface. Nếu throughput bị ghim gần sát giới hạn của cổng, bạn đang gặp một cuộc tấn công khối lượng lớn, và việc cần làm là mở ticket hỗ trợ, không phải sửa cấu hình:

  • vnstat -tr 10 — throughput trung bình trong mười giây, cách đọc nhanh và trung thực nhất về mức độ bão hòa.
  • cat /proc/net/dev chạy hai lần, cách nhau một giây — chênh lệch gói tin và byte theo từng interface, không cần công cụ nào thêm.

Có phải một đợt SYN flood không? Các kết nối nửa-mở chất đống ở trạng thái SYN-RECV. Một vài kết nối là bình thường; hàng nghìn thì không:

  • ss -s — dòng tóm tắt, số lượng kết nối theo từng trạng thái, nhìn một phát là biết.
  • ss -tn state syn-recv | wc -l — con số cụ thể thực sự quan trọng.

Có phải tầng 7 không? Nếu băng thông không có gì bất thường nhưng mọi thứ đều chậm, hãy đếm số request theo từng client trong access log của bạn. Một địa chỉ duy nhất với hàng chục nghìn lượt truy cập là một kẻ nghiệp dư; một trăm nghìn địa chỉ, mỗi địa chỉ chỉ ba lượt, mới là hàng thật:

  • tail -n 100000 access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -30
  • Đổi $1 thành $7 để xếp hạng theo đường dẫn được yêu cầu thay vì địa chỉ. Nếu một endpoint tốn kém chiếm áp đảo, bạn vừa tìm ra mục tiêu và có sẵn luôn một nửa cách khắc phục.

Thứ gì thực sự đã cạn kiệt? Load average tự nó nói lên rất ít. Hãy tìm giới hạn cụ thể mà bạn vừa chạm tới: các tiến trình con PHP-FPM đều đang bận, kết nối database đã chạm giới hạn, file descriptor cạn kiệt, hoặc worker bị kẹt ở trạng thái D chờ đĩa. Chính giới hạn đó — chứ không phải lưu lượng — mới là thứ đánh sập trang của bạn, và nâng nó lên thường nhanh hơn nhiều so với việc đi lọc bất cứ thứ gì.

Hãy ghi nhớ điều này trong lúc tìm hiểu: nếu bạn vận hành một dịch vụ chú trọng quyền riêng tư, một cuộc tấn công chính là lúc bạn dễ bị cám dỗ bật log lên mức chi tiết tối đa và giữ nguyên như vậy. Hãy bật lên nếu thực sự cần, rồi tắt lại và xoay vòng (rotate) các file log thật quyết liệt ngay sau đó. Một sự cố để lại cả tháng log truy cập chi tiết đầy đủ trên đĩa chỉ là đánh đổi một vấn đề lấy một vấn đề khác tệ hơn và tồn tại lâu hơn. Hướng dẫn OpSec máy chủ của chúng tôi trình bày kỷ luật này thuộc về đâu.

Mười phút đầu tiên

Dưới áp lực, người ta có xu hướng với lấy đòn bẩy lớn nhất có sẵn, và đòn bẩy lớn nhất thường lại sai. Đây là thứ tự giúp giới hạn thiệt hại, xếp gần đúng theo mức độ nhanh và an toàn giảm dần:

  1. Phân loại trước khi hành động. Interface bão hòa nghĩa là khối lượng lớn; interface im ắng mà worker lại bận nghĩa là tầng 7. Ba mươi giây bỏ ra ở đây giúp bạn khỏi mất cả tiếng đồng hồ sửa nhầm tầng.
  2. Nếu là tấn công khối lượng lớn, hãy mở ticket ngay lập tức, kèm theo địa chỉ đích, thời điểm bắt đầu, và các số liệu từ bộ đếm interface của bạn. Sau đó ngừng gõ bất cứ thứ gì vào server — bạn không thể khắc phục chuyện này từ bên trong nó.
  3. Nếu là tầng 7, hãy cache trước tiên. Bật cache toàn trang mạnh tay cho khách ẩn danh là cách nhanh nhất để biến một sự cố sập trang thành một cái nhún vai, và đây cũng là biện pháp duy nhất trong danh sách này giúp ích ngay cả với lưu lượng thật.
  4. Rồi mới giới hạn tốc độ — nhắm vào endpoint bị nhắm trước, mọi thứ còn lại sau. Hãy bắt đầu thận trọng. Một giới hạn đánh văng cả người dùng thật của chính bạn chỉ là một cách tự tiếp tay cho cuộc tấn công.
  5. Chỉ chặn những gì rõ ràng không thể nhầm lẫn. Một chục địa chỉ, mỗi địa chỉ gửi một trăm nghìn request, một user-agent giả mạo lộ liễu, một quốc gia bạn chẳng có người dùng nào. Hãy cưỡng lại ý muốn viết ra các luật phức tạp trong lúc đang bị tấn công; sang tháng sau bạn sẽ chẳng nhớ nổi chúng làm gì.
  6. Chủ động xả bớt tải nếu buộc phải làm vậy. Phục vụ một trang tĩnh "đang bảo trì" cho khách chưa xác thực giúp máy chủ sống sót, giữ API của bạn hoạt động, và mua thêm thời gian để suy nghĩ. Tự quyết định cái gì phải hy sinh vẫn tốt hơn là để nó bị quyết định thay bạn.
  7. Ghi lại những gì bạn đã làm. Mỗi luật tạm thời bạn thêm vào là một quả mìn cho chính bạn trong tương lai. Luật nào có tác dụng thì giữ lại vĩnh viễn; phần còn lại nên gỡ bỏ ngay ngày hôm sau.

Giới hạn tốc độ trụ vững, và sai lầm hầu như ai cũng mắc

Giới hạn tốc độ là công cụ chủ lực cho tầng 7, và nginx làm việc này tốt với hai directive giải quyết hai vấn đề thực sự khác nhau. limit_req giới hạn tốc độ request — tần suất một client được phép hỏi. limit_conn giới hạn số kết nối đồng thời — số kết nối mà một client được phép giữ mở cùng lúc. Các đợt lũ cần đến cái đầu tiên; các cuộc tấn công slow-loris, vốn giữ hàng nghìn kết nối gần như không hoạt động để rút cạn worker pool của bạn, cần đến cái thứ hai. Chỉ triển khai một trong hai thì bạn mới chỉ được bảo vệ trước một nửa vấn đề.

Ba chi tiết phân biệt một giới hạn thực sự có tác dụng với một giới hạn chỉ mang tính hình thức:

  • Hãy dùng burst, và dùng nodelay. Trình duyệt thật vốn hoạt động theo từng đợt (bursty) — một lượt xem trang bắn ra cả chục request tài nguyên gần như cùng lúc. Một giới hạn không có khoảng dư sẽ bóp nghẹt khách thật, trong khi một kẻ tấn công biết tiết chế ở ngay dưới ngưỡng lại ung dung lọt qua.
  • Giới hạn riêng các endpoint tốn kém. Trang tìm kiếm, form đăng nhập, đặt lại mật khẩu, và bất kỳ endpoint nào ghi vào database đều xứng đáng có một ngân sách chặt hơn nhiều so với các tài nguyên tĩnh. Kẻ tấn công tìm ra chúng mà chẳng cần cố gắng, vì đó chính là những chỗ gây đau nhất.
  • Trả về 429, không phải 503. Mã trạng thái này là tín hiệu cho các client biết điều và cho các công cụ tìm kiếm rằng đây là việc hãm tốc độ chứ không phải lỗi — và nó giúp một buổi chiều tồi tệ không biến thành một vấn đề về thứ hạng tìm kiếm.

Sai lầm âm thầm vô hiệu hóa tất cả những điều trên: nếu có bất cứ thứ gì đứng trước server của bạn — một CDN, một load balancer, hay reverse proxy của chính bạn — thì mọi request đều đến từ địa chỉ của , không phải của khách truy cập. Một giới hạn tốc độ theo từng client khi đó sẽ tính cả internet là một client duy nhất, và nó sẽ hoặc chẳng làm gì cả, hoặc cấm luôn toàn bộ khán giả của bạn cùng một lúc. Bạn phải cấu hình nguồn real-IP của mình (trong nginx là set_real_ip_from cho các dải địa chỉ của proxy, cộng với real_ip_header cho header mà nó gửi) trước khi mọi giới hạn có ý nghĩa gì. Cũng hãy giới hạn điều đó chỉ trong đúng các dải địa chỉ của proxy: tin tưởng một header do client tự cung cấp từ internet mở cho phép kẻ tấn công giả mạo một danh tính mới cho mỗi request và ung dung đi xuyên qua mọi giới hạn bạn dựng lên.

Cache là biện pháp chống đỡ rẻ nhất bạn từng triển khai

Một giới hạn tốc độ từ chối công việc. Một cache khiến công việc đó không cần tồn tại nữa. Với bất cứ thứ gì một khách ẩn danh nhìn thấy, cache toàn trang thay đổi hẳn bài toán kinh tế của toàn bộ cuộc tấn công: một request lẽ ra tốn một lượt round-trip tới database, một lượt dựng template và một PHP worker giờ chỉ còn là một lượt đọc file tính bằng micro giây. Chính chiếc server từng sập ở bốn trăm request động mỗi giây giờ có thể phục vụ hàng chục nghìn request đã cache mà chẳng hề hấn gì.

Những điều quan trọng khi bạn bật nó lên trong lúc nước sôi lửa bỏng:

  • Chỉ cache cho khách ẩn danh. Bỏ qua cache khi có session cookie. Phục vụ nhầm trang của một người dùng đã đăng nhập cho một người khác là một sự cố còn tệ hơn nhiều so với việc sập trang bạn đang cố khắc phục.
  • Chủ động phục vụ nội dung cũ (stale). proxy_cache_use_stale của nginx kết hợp với updating error timeout nghĩa là khi backend của bạn đang gặp khó khăn, khách truy cập sẽ nhận được một trang hơi cũ thay vì một lỗi. Trong lúc bị tấn công, đây chính là khác biệt giữa một trang trông vẫn ổn và một trang trông như đã chết.
  • Gộp các lượt cache-miss trùng nhau. proxy_cache_lock đảm bảo rằng một nghìn request đồng thời cho cùng một trang chưa được cache chỉ tạo ra một request tới backend, chứ không phải một nghìn. Thiếu nó, một cuộc tấn công phá cache sẽ xuyên thẳng qua cache và dội thẳng toàn lực vào database của bạn.
  • Vô hiệu hóa các query string phá cache. Thủ thuật tiêu chuẩn là thêm ? cùng một giá trị ngẫu nhiên để mỗi request trở thành một khóa duy nhất và luôn miss cache. Hãy chuẩn hóa cache key của bạn để bỏ qua các tham số query mà ứng dụng của bạn thực ra không hề dùng đến.

Có một sự bất đối xứng dễ chịu ở đây, đáng để khắc cốt ghi tâm: mỗi giờ bạn bỏ ra cho việc cache cũng đồng thời khiến trang web nhanh hơn vào ngày đẹp trời nhất của nó, rẻ hơn để vận hành, và giỏi sống sót hơn trước chính thành công của mình. Gần như không tuyến phòng thủ nào khác trả cổ tức cho bạn khi chẳng có gì bất ổn xảy ra cả.

Những giới hạn quyết định bạn có gục ngã hay không

Hầu hết server không chết vì hết CPU. Chúng chết vì chạm phải một giới hạn vô hình mà chẳng ai chủ đích đặt ra — một giá trị mặc định từ cả chục năm trước, từng hợp lý trên loại phần cứng giờ chẳng ai còn dùng. Khi bị tấn công, đây mới là những thứ thực sự gãy trước tiên:

  • Worker ứng dụng. pm.max_children của PHP-FPM, số worker Python, hay kích thước cluster Node của bạn. Đây chính là giới hạn kết nối đồng thời thực sự của trang web bạn. Khi tất cả đều bận, mỗi khách truy cập thêm vào sẽ phải xếp hàng, và trang web coi như sập bất kể CPU trông rảnh rỗi đến đâu. Chỉ nên nâng nó lên đến mức bộ nhớ còn cho phép — swap còn tệ hơn việc phải xếp hàng chờ.
  • Hàng đợi chấp nhận kết nối (accept queue). net.core.somaxconn và backlog lắng nghe của bạn quyết định có bao nhiêu kết nối được phép chờ để được chấp nhận. Một backlog nhỏ biến một đợt burst lẽ ra chịu được thành hàng loạt kết nối bị từ chối.
  • SYN cookie. net.ipv4.tcp_syncookies cho phép kernel trả lời một đợt SYN flood mà không cần cấp phát trạng thái cho các kết nối sẽ không bao giờ hoàn tất. Các kernel hiện đại bật sẵn tùy chọn này theo mặc định; hãy kiểm tra lại thay vì mặc định tin vào điều đó, vì việc kiểm tra chẳng tốn gì mà lại cứu bạn khỏi loại lũ phổ biến nhất tồn tại.
  • File descriptor. Mỗi kết nối là một descriptor. Giới hạn nofile mặc định thường thấp hơn số kết nối bạn đang cố phục vụ, và kiểu lỗi mà nó gây ra — accept thất bại trong khi mọi thứ trông vẫn khỏe mạnh — thực sự gây bối rối khi việc đó xảy ra lúc 3 giờ sáng.
  • Kết nối database. Nâng số worker mà không nâng connection pool chỉ đơn giản là dời hàng đợi sang một chỗ khó nhìn thấy hơn. Hai con số này phải được điều chỉnh cùng nhau.

Hãy tinh chỉnh những thứ này vào một ngày yên bình, không phải trong lúc sự cố đang diễn ra. Ý nghĩa của việc biết trước các con số này là khi trang web sập, bạn có thể gọi đúng tên giới hạn nào vừa bị chạm tới thay vì phải đoán mò — và một giới hạn đã được gọi tên là một giới hạn đã được ấn định.

Đặt một lớp đứng trước origin

Mọi thứ ở trên đều diễn ra ngay trên server. Bước tiếp theo là quyết định liệu server có nên là thứ trực tiếp nhận lưu lượng hay không. Có ba lựa chọn trung thực, và câu trả lời đúng phụ thuộc vào thứ bạn đang host nhiều hơn là vào số tiền bạn có thể bỏ ra.

Cách tiếp cậnBạn được gìBạn phải trả giá gì
Origin lộ trực tiếp, đã được gia cốĐơn giản, không bên thứ ba, không có việc kết thúc TLS nằm ngoài tầm kiểm soát của bạnĐịa chỉ của bạn công khai và vĩnh viễn. Tầng 7 hoàn toàn là việc của bạn
CDN thương mại hoặc dịch vụ scrubbingNăng lực hấp thụ cực lớn, một trang thử thách chỉ cách một cú nhấp, cache trên phạm vi toàn cầuMột bàn khiếu nại có ý kiến riêng về nội dung của bạn, và một công ty có thể nhìn thấy lưu lượng của bạn. Với các dự án offshore hay nhạy cảm với DMCA, đây có thể là mắt xích yếu nhất trong một cách bố trí vốn dĩ đã rất cẩn trọng
Node mặt tiền của riêng bạn — một VPS nhỏ chạy nginx, proxy về một origin đã được rào bằng firewallToàn quyền kiểm soát, không bên thứ ba nào nằm trên đường đi của request, một địa chỉ bạn có thể đốt bỏ và thay thế bất cứ lúc nào, và một địa chỉ thật luôn được giữ kínGiới hạn năng lực của riêng nó, và thêm một cỗ máy nữa phải vận hành. Hai hoặc ba mặt tiền đặt ở các mạng khác nhau khiến việc đánh sập trở nên khó khăn hơn hẳn

Node mặt tiền tự vận hành xứng đáng được chú ý nhiều hơn mức nó thường nhận được, đặc biệt với bất kỳ ai chọn hosting offshore vì những lý do mà một CDN lớn chưa chắc đã cảm thông. Mô hình này chẳng có gì hào nhoáng: các node proxy giá rẻ đặt phía trước, origin được rào bằng firewall để chỉ chấp nhận kết nối từ đúng các node đó, DNS trỏ vào các mặt tiền. Nếu một mặt tiền bị tấn công, bạn thay nó bằng một địa chỉ mới trong vài phút và origin chẳng hề hay biết. Phiên bản đầy đủ của kiến trúc này — bao gồm cả sáu cách một địa chỉ origin vẫn có thể rò rỉ dù đã làm mọi thứ — là chủ đề của hướng dẫn ẩn IP origin server của bạn.

Một origin được giấu kín đáng giá hơn mọi bộ lọc

Điều này đáng nói thẳng ra, vì nó đảo ngược thứ tự ưu tiên thông thường: biện pháp chống DDoS rẻ nhất mà bạn có được là một địa chỉ mà kẻ tấn công không hề có. Lọc lưu lượng là việc bạn làm khi điều đó đã thất bại rồi.

Điều này quan trọng hơn vẻ ngoài của nó, bởi địa chỉ origin rò rỉ liên tục và âm thầm. Các bản ghi DNS lịch sử từ trước khi bạn đặt một proxy ra phía trước vẫn tồn tại lâu hơn sự thay đổi đó hàng năm trời. Mail gửi trực tiếp từ ứng dụng mang theo địa chỉ trong header của nó. Một chứng chỉ TLS cấp cho địa chỉ thô được công bố vĩnh viễn trong các log certificate transparency. Một trang lỗi, một redirect, hay một subdomain hẻo lánh chưa từng được proxy — tất cả đều để lộ nó ra. Nếu bạn từng đặt một CDN trước một server vốn đã từng lộ diện, hãy mặc định rằng địa chỉ cũ đã bị biết cho đến khi bạn thực sự đổi nó.

Hệ quả tất yếu là một luật firewall, và đây là dòng giá trị nhất trong toàn bộ hướng dẫn này: một khi đã có gì đó đứng trước, origin nên từ chối mọi kết nối trên cổng 80 và 443 từ bất cứ đâu ngoại trừ các địa chỉ của lớp mặt tiền đó. Thiếu điều này, proxy chỉ còn là một gợi ý — bất kỳ ai biết được địa chỉ thật đơn giản là đi vòng qua nó và tấn công thẳng vào bạn, và mọi thứ bạn đã cấu hình ở lớp mặt tiền trở thành vô nghĩa, chỉ còn tác dụng trang trí.

Chọn phần cứng và địa điểm để các cuộc tấn công trở nên nhàm chán

Một phần của việc này được quyết định từ trước khi bất kỳ cuộc tấn công nào xảy ra, ngay tại thời điểm bạn chọn gói dịch vụ. Ba đặc tính sau quan trọng hơn nhiều so với những gì bảng thông số kỹ thuật gợi ý:

  • Băng thông không giới hạn. Trên một gói tính theo dung lượng, một cuộc tấn công không chỉ là sự cố sập trang — đó còn là một hóa đơn. Lưu lượng bạn chưa từng yêu cầu và không thể từ chối vẫn bị tính vào hạn mức của bạn. Băng thông không giới hạn biến một rủi ro tài chính thành một vấn đề thuần kỹ thuật, và đó là một loại vấn đề dễ chịu hơn nhiều.
  • Cổng mạng có thực sự thuộc về riêng bạn không. Trên một host ảo hóa dùng chung, một hàng xóm đang bị tấn công có thể kéo tụt hiệu năng của bạn, và giới hạn bảo vệ của chính bạn cũng là thứ dùng chung. Phần cứng chuyên dụng với cổng mạng riêng loại bỏ cả hai hiệu ứng này. Với một dự án dự kiến sẽ hứng chịu sự chú ý thù địch, đây là lý do rõ ràng nhất để nâng cấp từ một VPS — rõ ràng hơn cả lý do về số lõi CPU hay RAM.
  • Mạng đặt ở đâu. Một mạng châu Âu kết nối tốt với năng lực transit thực sự sẽ hấp thụ được một đợt lũ mà một mạng peering kém sẽ không chống nổi, và thẩm quyền pháp lý bạn chọn vì lý do pháp lý cũng có những đặc tính mạng riêng của nó. Cả hai điều này đều đáng để kiểm tra khi chọn trong số các địa điểm hiện có.

Ở đây còn có một lập luận về quy mô âm thầm nghiêng về phía sự đơn giản. Một trang tĩnh đặt sau một lớp cache trên một server khiêm tốn thì cực kỳ khó đánh sập; cũng nội dung đó nhưng chạy trên một CMS nặng nề với một endpoint tìm kiếm không được cache thì có thể bị đánh gục bởi một người quyết tâm với một đoạn script. Giảm bớt phần động của trang web là một biện pháp chống đỡ, và nó hoàn toàn miễn phí. Nếu dự án của bạn thực sự sống dưới tải liên tục, các ghi chú về hosting cho lưu lượng cao của chúng tôi sẽ đề cập tới khía cạnh chọn cấu hình phù hợp cho cùng câu hỏi này.

Năm điều không nên làm

Các kiểu thất bại ở đây đủ nhất quán để liệt kê ra, và mỗi kiểu đều từng khiến ai đó mất toi một cuối tuần:

  • Đừng tự null-route chính mình. Việc chặn đứng hoàn toàn (blackhole) địa chỉ của chính bạn chấm dứt cuộc tấn công theo đúng nghĩa đen triệt để nhất có thể — không ai chạm tới được bạn nữa, kể cả người dùng của bạn. Đây là công cụ chỉ dùng khi hết cách của nhà cung cấp, không phải hành động bạn tự nguyện thực hiện.
  • Đừng coi fail2ban là biện pháp chống DDoS. Đó là một công cụ tốt để chống các nỗ lực brute-force từ một vài địa chỉ. Trước một đợt lũ phân tán, nó phản ứng trong vài phút với thứ đến trong vài giây, và một luật cấm hàng nghìn địa chỉ có thể tốn nhiều tài nguyên xử lý firewall hơn cả chính cuộc tấn công.
  • Đừng trả tiền chuộc. Phần lớn áp đảo các email tống tiền đe dọa một cuộc tấn công tàn khốc đến từ những kẻ chẳng có năng lực gì, chỉ gửi hàng nghìn tin nhắn giống hệt nhau. Số ít thực sự có khả năng ra tay sẽ quay lại tìm bạn lần nữa, vì bạn đã chứng minh rằng mình chịu trả tiền.
  • Đừng trả đũa. Ngoài việc gần như ở đâu cũng phạm pháp, các nguồn tấn công đều là những bên thứ ba đã bị xâm nhập. Bạn sẽ đang tấn công chính các nạn nhân, và làm điều đó từ một địa chỉ rõ ràng thuộc về bạn.
  • Đừng di chuyển trong hoảng loạn. Chuyển host giữa lúc đang bị tấn công đồng nghĩa với việc địa chỉ mới công khai chỉ trong vài phút và bạn chưa có cấu hình nào hoạt động ổn định. Hãy ổn định tình hình trước, rồi di chuyển một cách có chủ đích sau — và nếu bạn thực sự di chuyển, hướng dẫn di chuyển không downtime của chúng tôi tồn tại chính là để cuộc di chuyển đó không trở thành một sự cố thứ hai.

Bản tóm tắt

Lược bỏ hết phần lý giải, mô hình thực chiến gói gọn trong tám dòng:

  1. Phân loại trước tiên. Interface bão hòa nghĩa là tấn công khối lượng lớn, thuộc về host của bạn. Interface im ắng mà worker cạn kiệt nghĩa là tầng 7, thuộc về bạn.
  2. Với tấn công khối lượng lớn, hãy mở ticket kèm địa chỉ, mốc thời gian và các số liệu bộ đếm của bạn — rồi ngừng động vào server.
  3. Cache mạnh tay cho khách ẩn danh, phục vụ nội dung cũ khi backend chịu áp lực, và gộp các lượt cache-miss trùng nhau. Đây là thay đổi mang lại đòn bẩy lớn nhất bạn có thể thực hiện.
  4. Giới hạn theo cả tốc độ request lẫn số kết nối đồng thời, chặt nhất ở các endpoint tốn kém nhất, và trả về 429.
  5. Sửa cấu hình real-IP trước khi làm bất cứ điều gì khác, nếu không mọi giới hạn theo từng client phía sau một proxy sẽ hoặc vô dụng, hoặc gây thảm họa.
  6. Nắm rõ các giới hạn của bạn — worker, backlog, descriptor, kết nối database — và chủ động nâng chúng lên vào một ngày yên bình.
  7. Giữ bí mật địa chỉ origin và chỉ mở firewall cho các node mặt tiền của bạn. Điều này đáng giá hơn tất cả các bộ lọc cộng lại.
  8. Mua băng thông không giới hạn để lưu lượng bạn không hề yêu cầu không bao giờ biến thành một hóa đơn.

Không điều nào trong số này khiến bạn miễn nhiễm, và bất kỳ ai rao bán sự miễn nhiễm đều đang bán một thứ gì đó khác. Điều những biện pháp này thực sự làm là đưa bạn ra khỏi nhóm những người bị đánh sập bởi một cậu nhóc rảnh rỗi, và đưa bạn vào nhóm đòi hỏi nguồn lực thật sự và chủ đích thật sự mới có thể quấy rối được — và với đại đa số dự án, điều đó chẳng khác gì an toàn tuyệt đối. Phần còn lại chỉ là những công việc chẳng có gì hào nhoáng, vốn khiến một server trở nên tốt ở mọi mặt khác: được gia cố ngay từ ngày đầu tiên, khôi phục được vào ngày tồi tệ nhất, và chạy ở một nơi coi lưu lượng của bạn là công việc kinh doanh của chính họ.

FAQ

DDoS trên một server nhỏ — các câu hỏi thường gặp

01 "Đã bao gồm chống DDoS" có nghĩa là tôi an toàn trước mọi thứ không?

Không, và khoảng trống đó rất rõ ràng chứ không hề mơ hồ. Lớp bảo vệ đi kèm là lọc ở tầng mạng: nó loại bỏ các đợt lũ khối lượng lớn — SYN flood, khuếch đại UDP, các cơn bão gói tin thô — ngay ở thượng nguồn, trước khi chúng chạm tới cổng của bạn. Đó chính là loại tấn công mà một mình bạn thực sự không thể xử lý, nên việc đưa nó vào gói mặc định là hợp lý. Nhưng nó không kiểm tra ứng dụng của bạn, nên một đợt lũ HTTP chỉ vài nghìn request mỗi giây nhắm vào một endpoint tốn kém vẫn xuyên qua nó nguyên vẹn và đánh sập trang của bạn, trong khi mọi biểu đồ mạng vẫn trông hoàn toàn bình thường. Tầng 7 là phần cấu hình thuộc về bạn: cache, giới hạn tốc độ và giới hạn kết nối.

02 Làm sao để phân biệt một cuộc tấn công DDoS với một đợt tăng vọt lưu lượng thông thường?

Hãy tự hỏi liệu lưu lượng đó có đang muốn thứ gì đó không. Khách truy cập thật, kể cả khi họ ập đến đột ngột từ một liên kết nổi tiếng, vẫn yêu cầu những trang thực sự tồn tại, tải các asset trên những trang đó, đến kèm referrer hợp lý và trải rộng trên nhiều mạng theo một hình dạng tự nhiên. Một cuộc tấn công thường chỉ dội vào một đường dẫn duy nhất, bỏ qua các asset, gửi user-agent vô lý hoặc trống rỗng, và cho thấy một phân bố trông như được tạo ra máy móc. Hãy kiểm tra access log để xem số request theo từng địa chỉ client và theo từng đường dẫn: nếu một endpoint chiếm áp đảo và không có gì khác được tải, đó là một cuộc tấn công. Nếu những trang mà một con người thực sự muốn xem đang được phục vụ và referrer của bạn là thật, thì đó chỉ là vấn đề về năng lực với một nguyên nhân đáng mừng.

03 Việc duy nhất hiệu quả nhất tôi có thể làm khi đang bị tấn công là gì?

Bật cache toàn trang cho khách ẩn danh, và cấu hình để nó phục vụ nội dung cũ khi backend đang gặp khó khăn. Một giới hạn tốc độ từ chối công việc; một cache khiến công việc đó không cần tồn tại. Một request từng tốn một truy vấn database, một lượt dựng template và một worker ứng dụng giờ chỉ còn là một lượt đọc file, và chính phần cứng từng sập ở vài trăm request động mỗi giây giờ có thể phục vụ hàng chục nghìn request đã cache. Đây cũng là biện pháp duy nhất trong danh sách có tác dụng y hệt với cả lưu lượng thật, nên khác với một giới hạn tốc độ, nó không thể phản tác dụng lên chính người dùng của bạn.

04 Vì sao giới hạn tốc độ nginx của tôi ngừng hoạt động sau khi tôi đặt một CDN ra phía trước?

Vì giờ đây mọi request đều đến từ địa chỉ của CDN chứ không phải của khách truy cập, nên một giới hạn theo từng client đang tính cả internet là một client duy nhất. Tùy vào ngưỡng đặt ra, nó sẽ hoặc không bao giờ kích hoạt, hoặc cấm toàn bộ lưu lượng của bạn cùng một lúc. Hãy cấu hình nguồn real-IP của bạn — trong nginx là các dải địa chỉ proxy đáng tin cậy cộng với header mà proxy đó gửi đi — để giới hạn lại tính theo đúng khách truy cập thật. Hãy giới hạn sự tin cậy đó chỉ trong đúng dải địa chỉ của proxy: nếu bạn chấp nhận một header do client tự khai từ internet mở, kẻ tấn công có thể giả mạo một danh tính mới cho mỗi request và ung dung đi xuyên qua mọi giới hạn bạn có.

05 fail2ban có đủ để chặn một cuộc tấn công DDoS không?

Không. fail2ban đọc log theo chu kỳ và cấm các địa chỉ vi phạm sau khi vượt một ngưỡng nhất định, phù hợp với các nỗ lực brute-force từ một số ít nguồn. Một cuộc tấn công phân tán lại ập đến trong vài giây từ hàng nghìn địa chỉ, mỗi địa chỉ chỉ gửi một nhúm request, nên ngưỡng đó chẳng bao giờ đạt tới, và thời gian phản ứng dù sao cũng quá chậm. Tệ hơn, một tập luật phình to tới hàng chục nghìn mục có thể tiêu tốn tài nguyên nhiều hơn cả chính cuộc tấn công. Hãy giữ fail2ban lại cho SSH và các endpoint đăng nhập, còn xử lý các đợt lũ bằng cache, giới hạn tốc độ và một bộ lọc ở thượng nguồn.

06 Tôi nên dùng một CDN, hay tự chạy reverse proxy của riêng mình ở phía trước?

Điều đó phụ thuộc vào thứ bạn đang host nhiều hơn là vào ngân sách của bạn. Một CDN thương mại mang lại năng lực hấp thụ mà bạn không thể sánh được cùng một trang thử thách chỉ cách một cú nhấp, nhưng bạn phải thừa hưởng bàn khiếu nại của họ, và họ có thể nhìn thấy lưu lượng của bạn — điều mà với các dự án offshore hay nhạy cảm với DMCA thường là mắt xích yếu nhất trong một cách bố trí vốn dĩ rất cẩn trọng. Các node mặt tiền của riêng bạn tốn nhiều công sức hơn và có giới hạn năng lực thực sự, nhưng không có bên thứ ba nào nằm trên đường đi của request, và một mặt tiền bị tấn công có thể được thay bằng một địa chỉ mới chỉ trong vài phút. Dù chọn cách nào, origin cũng phải được rào bằng firewall để chỉ nhận lưu lượng web từ lớp mặt tiền, nếu không toàn bộ cách bố trí đó chỉ còn tác dụng trang trí.

07 Một cuộc tấn công có khiến tôi mất tiền chứ không chỉ mất uptime không?

Trên một gói tính theo dung lượng thì có — lưu lượng bạn chưa từng yêu cầu và không thể từ chối vẫn bị tính vào hạn mức truyền tải của bạn, và một đợt lũ kéo dài có thể tạo ra một hóa đơn vượt hạn mức còn lớn hơn cả một năm hosting. Đây chính là lý do thực tế khiến băng thông không giới hạn quan trọng hơn nhiều so với những gì nó thể hiện trên bảng thông số: nó biến một rủi ro tài chính thành một vấn đề thuần kỹ thuật. Cũng đáng biết trước rằng nếu một cuộc tấn công đe dọa hạ tầng dùng chung, nhà cung cấp có thể tạm thời null-route địa chỉ đó; đó là thông lệ chuẩn ở khắp mọi nơi, không phải một thất bại riêng của nhà cung cấp bạn đang dùng.

08 Chuyển sang một nhà cung cấp offshore hoặc không-KYC có khiến tôi dễ bị tấn công hơn không?

Bản thân lựa chọn hosting là trung lập; thứ bạn vận hành mới là thứ thu hút sự chú ý. Server game, diễn đàn, streaming, sàn giao dịch và bất cứ thứ gì có đối thủ cạnh tranh hay có kẻ thù đều hứng chịu tấn công bất kể thẩm quyền pháp lý nào. Điều thực sự thay đổi khi ra offshore là hướng xử lý của bạn: bạn ít có khả năng bị cắt dịch vụ chỉ vì gây phiền phức hơn, và điều đó có hai mặt — sự bảo vệ giờ mang tính kỹ thuật chứ không còn mang tính hợp đồng. Hãy chọn một địa điểm có năng lực transit thực sự, lấy gói băng thông không giới hạn, giữ kín địa chỉ origin, và coi tầng 7 là trách nhiệm của chính bạn ngay từ ngày đầu tiên, chứ không phải chỉ từ sau sự cố đầu tiên.

Đặt máy chủ ở nơi biết lọc đợt lũ thay bạn

Máy chủ KVM offshore tại bảy thẩm quyền pháp lý, đi kèm lọc DDoS L3/L4, băng thông không giới hạn, toàn quyền root và lưu trữ NVMe. Không KYC, thanh toán bằng crypto, triển khai chỉ vài phút sau khi giao dịch được xác nhận.

Xem các gói VPS Máy chủ Dedicated Offshore Hosting