Bài viết này giải thích cách sử dụng nginx HttpLimitReqModule để giới hạn số lượng yêu cầu cho một phiên nhất định. Điều này hữu ích, ví dụ, nếu trang web của bạn bị bot tấn công bằng cách thực hiện nhiều yêu cầu mỗi giây và do đó làm tăng tải máy chủ của bạn. Với HttpLimitReqModule, bạn có thể xác định giới hạn tốc độ và nếu khách truy cập vượt quá tốc độ này, họ sẽ nhận được lỗi 503.
... và xác định một vùng lưu trữ trạng thái phiên - vùng này phải nằm bên trong vùng chứa http {}:
Khu vực này được gọi là one và được phân bổ 10MB dung lượng lưu trữ. Thay vì biến $remote_addr, chúng tôi sử dụng biến $binary_remote_addr giúp giảm kích thước của trạng thái xuống còn 64 byte. Có thể có khoảng 16.000 trạng thái trong một vùng 1MB, vì vậy 10MB cho phép khoảng 160.000 trạng thái, do đó, điều này sẽ đủ cho khách truy cập của bạn. Tốc độ được giới hạn ở một yêu cầu mỗi giây. Xin lưu ý rằng bạn phải sử dụng giá trị số nguyên ở đây, vì vậy nếu bạn muốn đặt giới hạn thành một nửa yêu cầu mỗi giây, bạn sẽ sử dụng 30r/m (30 yêu cầu mỗi phút).
Để áp dụng giới hạn này, chúng ta sử dụng lệnh limit_req. Bạn có thể sử dụng lệnh này trong các container http {}, server {} và location {}, nhưng theo tôi, lệnh này hữu ích nhất trong các container location {} chuyển tiếp yêu cầu đến máy chủ ứng dụng của bạn (PHP-FPM, mongrel, v.v.) vì nếu không, nếu bạn tải một trang duy nhất có nhiều hình ảnh, tệp CSS và JavaScript, bạn có thể sẽ vượt quá giới hạn tốc độ đã cho với một yêu cầu trang duy nhất.
Vì vậy, hãy đặt lệnh này vào container location ~ \.php$ {}:
limit_req zone=one burst=5; chỉ định rằng giới hạn tốc độ này thuộc về vùng lưu trữ phiên mà chúng ta đã xác định trước đó (vì zone=one) có nghĩa là giới hạn tốc độ là 1r/s. Bạn có thể hình dung ý nghĩa của tùy chọn burst như một loại hàng đợi. Điều này có nghĩa là nếu bạn vượt quá giới hạn tốc độ, các yêu cầu sau sẽ bị trì hoãn và chỉ khi có nhiều yêu cầu đang chờ trong hàng đợi hơn số lượng được chỉ định trong tham số burst, bạn mới nhận được lỗi 503 (ví dụ như sau:
data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22750%22%20height=%22505%22%3E%3C/svg%3E
).
Nếu bạn không muốn sử dụng hàng đợi này (tức là gửi ngay 503 nếu ai đó vượt quá giới hạn tốc độ), bạn phải sử dụng tùy chọn nodelay:
Đừng quên tải lại nginx để các thay đổi của bạn có hiệu lực:
1 Sử dụng HttpLimitReqModule
Mở nginx.conf...
Mã:
nano /etc/nginx/nginx.conf
Mã:
http { [...] limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; [...]}
Để áp dụng giới hạn này, chúng ta sử dụng lệnh limit_req. Bạn có thể sử dụng lệnh này trong các container http {}, server {} và location {}, nhưng theo tôi, lệnh này hữu ích nhất trong các container location {} chuyển tiếp yêu cầu đến máy chủ ứng dụng của bạn (PHP-FPM, mongrel, v.v.) vì nếu không, nếu bạn tải một trang duy nhất có nhiều hình ảnh, tệp CSS và JavaScript, bạn có thể sẽ vượt quá giới hạn tốc độ đã cho với một yêu cầu trang duy nhất.
Vì vậy, hãy đặt lệnh này vào container location ~ \.php$ {}:
Mã:
[...] location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; limit_req zone=one burst=5; }[...]
data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20width=%22750%22%20height=%22505%22%3E%3C/svg%3E
).
Nếu bạn không muốn sử dụng hàng đợi này (tức là gửi ngay 503 nếu ai đó vượt quá giới hạn tốc độ), bạn phải sử dụng tùy chọn nodelay:
Mã:
[...] location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; bao gồm fastcgi_params; limit_req vùng=một burst=5 nodelay; }[...]
Mã:
systemctl nginx reload