Thursday, September 19, 2024

Bảo vệ máy chủ Nginx khỏi quá tải với ngx_http_limit_req_module

-

1. Tổng quan.

ngx_http_limit_req_module là một module quan trọng trong Nginx, được thiết kế để giới hạn tốc độ xử lý các yêu cầu đến máy chủ. Module này đặc biệt hữu ích trong việc bảo vệ máy chủ khỏi các cuộc tấn công DDoS (Distributed Denial of Service) và các tình huống quá tải đột ngột.

Leaky Bucket Algorithm: Đây là thuật toán cơ bản mà module ngx_http_limit_req_module sử dụng. Hình dung như một cái xô có lỗ nhỏ ở đáy. Nước (tương đương với các yêu cầu) được đổ vào xô với tốc độ nhất định. Nếu xô đầy, nước sẽ tràn ra (tương đương với yêu cầu bị từ chối).

Key: Module này cho phép bạn định nghĩa một “key” để phân nhóm các yêu cầu. Ví dụ, key có thể là địa chỉ IP của client, một phần của URL, hoặc một header tùy chỉnh. Điều này cho phép bạn thiết lập giới hạn tốc độ khác nhau cho từng nhóm khách hàng.

Tình huống là một máy chủ Nginx nhận nhiều yêu cầu từ các client khác nhau. Các yêu cầu được phân nhóm dựa trên địa chỉ IP và được xử lý với tốc độ giới hạn. Nếu vượt quá giới hạn, yêu cầu sẽ bị từ chối.

2. Tác dụng của Module.

  • Bảo vệ API: Giới hạn số lượng request đến API để ngăn chặn việc khai thác hoặc lạm dụng.
  • Bảo vệ trang đăng nhập: Ngăn chặn các cuộc tấn công brute-force bằng cách giới hạn số lần đăng nhập thất bại từ một địa chỉ IP.
  • Bảo vệ trang web tĩnh: Ngăn chặn các bot tải xuống dữ liệu với tốc độ cao.

3. So sánh với các giải pháp khác.

Firewall: Firewall tập trung vào việc kiểm soát lưu lượng mạng, trong khi ngx_http_limit_req_module tập trung vào việc giới hạn tốc độ xử lý các yêu cầu HTTP.

WAF (Web Application Firewall): WAF bảo vệ ứng dụng web khỏi các cuộc tấn công web, trong khi ngx_http_limit_req_module cung cấp một lớp bảo vệ bổ sung bằng cách giới hạn tốc độ.

Lưu ý.

  • Cấu hình: Cần cấu hình module này một cách cẩn thận để tránh ảnh hưởng đến hiệu suất của máy chủ.
  • Key: Việc lựa chọn key phù hợp là rất quan trọng để đảm bảo rằng giới hạn tốc độ được áp dụng đúng cách.
  • Giám sát: Theo dõi hiệu suất của máy chủ và điều chỉnh các thông số cấu hình nếu cần.
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;

        error_log /var/log/nginx/error.log;
        access_log /var/log/nginx/access.log;

        server_name _;
        location / {
                try_files $uri $uri/ =404;
        }
}

4. Ví dụ minh họa.

Dưới đây là cách bạn có thể sử dụng module ngx_http_limit_req_module của Nginx để giới hạn số lượng request cho từng URL cụ thể. Cụ thể ở ví dụ này chúng ta cấu hình để giới hạn request cho URL http://10.237.7.72/hoanghd là 10 và các URL khác là 2500.

Cấu hình Nginx.

Mở file cấu hình Nginx (thường là /etc/nginx/nginx.conf hoặc /etc/nginx/conf.d/default.conf) và thêm các cấu hình sau:

limit_req_zone $binary_remote_addr zone=hoanghd_zone:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=default_zone:10m rate=2500r/s;

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;

    error_log /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;

    server_name _;

    location /hoanghd {
        limit_req zone=hoanghd_zone burst=10;
        try_files $uri $uri/ =404;
    }

    location / {
        limit_req zone=default_zone burst=50;
        try_files $uri $uri/ =404;
    }
}

Trong đó:

limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;: Tạo một vùng tên là one với kích thước 10MB và tốc độ giới hạn là 500 requests mỗi giây.

limit_req_zone $binary_remote_addr zone=two:10m rate=2500/s;: Tạo một vùng tên là two với kích thước 10MB và tốc độ giới hạn là 2500 requests mỗi giây.

limit_req zone=one burst=10 nodelay;: Áp dụng giới hạn request cho vùng one với burst là 10 và không có độ trễ.

limit_req zone=two burst=10 nodelay;: Áp dụng giới hạn request cho vùng two với burst là 10 và không có độ trễ.

Khởi động lại Nginx.

Sau khi chỉnh sửa file cấu hình, khởi động lại Nginx để áp dụng thay đổi:

shell> nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Với cấu hình này, URL http://10.237.7.72/hoanghd bị giới hạn ở mức 10 requests mỗi giây, trong khi các URL khác sẽ bị giới hạn ở mức 2500 requests mỗi giây.

Reload lại cấu hình Nginx.

nginx -s reload

Kiểm tra log Nginx.

Trong khi gửi request, bạn có thể kiểm tra log của Nginx để xem các request bị giới hạn:

tail -f /var/log/nginx/error.log

Kiểm tra trạng thái Nginx.

Bạn cũng có thể kiểm tra trạng thái của Nginx để xem các request bị giới hạn:

curl -s http://demo.com/nginx_status

Lưu ý rằng bạn cần cấu hình Nginx để bật tính năng xem status nếu chưa làm:

server {
    listen 80;
    server_name demo.com;

    location /nginx_status {
        stub_status on;
        allow 127.0.0.1;
        deny all;
    }
}

Sau khi thực hiện các bước trên, bạn sẽ có thể kiểm tra và xác nhận rằng cấu hình giới hạn request của bạn đang hoạt động như mong đợi.

5. Kiểm tra kết quả.

Sử dụng ngxtop: ngxtop là một công cụ dòng lệnh để phân tích file log của Nginx.

Cài đặt ngxtop bằng cách chạy lệnh dưới, nếu chưa cài pip thì bạn hãy cài đặt pip trước khi chạy lệnh này nhé.

pip install ngxtop

Sử dụng ngxtop để xem số lượng request:

ngxtop -n 10

Bạn có thể sử dụng xargs để chạy các lệnh song song. Dưới đây là cách bạn có thể thực hiện việc gửi 10000 request với 10 luồng đồng thời:

seq 1 10000 | xargs -n1 -P10 -I{} curl -s -o /dev/null -w "%{http_code}\n" http://10.237.7.72

Trong đó:

  • seq 1 10000: Tạo ra một dãy số từ 1 đến 10000.
  • xargs -n1 -P10: Chạy lệnh với 10 luồng song song, mỗi lần một lệnh.
  • -I{}: Thay thế {} bằng số hiện tại từ seq.

Lệnh này sẽ gửi 10000 request với 10 luồng đồng thời.

running for 2 seconds, 0 records processed: 0.00 req/sec

Summary:
|   count | avg_bytes_sent   |   2xx |   3xx |   4xx |   5xx |
|---------+------------------+-------+-------+-------+-------|
|       0 |                  |     0 |     0 |     0 |     0 |

Detailed:
| request_path   | count   | avg_bytes_sent   | 2xx   | 3xx   | 4xx   | 5xx   |
|----------------+---------+------------------+-------+-------+-------+-------|

Đây là kết quả khi truy cập url khác với /hoanghd. mọi thứ đều diễn ta bthuong.

running for 132 seconds, 10000 records processed: 75.70 req/sec

Summary:
|   count |   avg_bytes_sent |   2xx |   3xx |   4xx |   5xx |
|---------+------------------+-------+-------+-------+-------|
|   10000 |          612.000 | 10000 |     0 |     0 |     0 |

Detailed:
| request_path   |   count |   avg_bytes_sent |   2xx |   3xx |   4xx |   5xx |
|----------------+---------+------------------+-------+-------+-------+-------|
| /              |   10000 |          612.000 | 10000 |     0 |     0 |     0 |

Và nếu bạn truy cập vào domain có /hoanghd, kết quả đã bị chặn như bạn thấy.

running for 64 seconds, 10000 records processed: 156.01 req/sec

Summary:
|   count |   avg_bytes_sent |   2xx |   3xx |   4xx |   5xx |
|---------+------------------+-------+-------+-------+-------|
|   10000 |          205.076 |     0 |   330 |     0 |  9670 |

Detailed:
| request_path   |   count |   avg_bytes_sent |   2xx |   3xx |   4xx |   5xx |
|----------------+---------+------------------+-------+-------+-------+-------|
| /hoanghd       |   10000 |          205.076 |     0 |   330 |     0 |  9670 |

Kết quả trên /var/log/nginx/error.log cho bạn biết nếu truy cập /hoanghd thì sẽ bị giới hạn lại lượng truy cập 10 bản tin đồng thời.

shell> tail -f /var/log/nginx/error.log 
2024/07/26 10:28:06 [error] 7922#7922: *20889 limiting requests, excess: 10.400 by zone "hoanghd_zone", client: 10.237.7.250, server: _, request: "GET /hoanghd HTTP/1.1", host: "10.237.7.72"
2024/07/26 10:28:06 [error] 7922#7922: *20888 limiting requests, excess: 10.400 by zone "hoanghd_zone", client: 10.237.7.250, server: _, request: "GET /hoanghd HTTP/1.1", host: "10.237.7.72"
2024/07/26 10:28:06 [error] 7922#7922: *20890 limiting requests, excess: 10.320 by zone "hoanghd_zone", client: 10.237.7.250, server: _, request: "GET /hoanghd HTTP/1.1", host: "10.237.7.72"
2024/07/26 10:28:06 [error] 7922#7922: *20891 limiting requests, excess: 10.320 by zone "hoanghd_zone", client: 10.237.7.250, server: _, request: "GET /hoanghd HTTP/1.1", host: "10.237.7.72"
2024/07/26 10:28:06 [error] 7922#7922: *20892 limiting requests, excess: 10.320 by zone "hoanghd_zone", client: 10.237.7.250, server: _, request: "GET /hoanghd HTTP/1.1", host: "10.237.7.72"
2024/07/26 10:28:06 [error] 7923#7923: *20893 limiting requests, excess: 10.240 by zone "hoanghd_zone", client: 10.237.7.250, server: _, request: "GET /hoanghd HTTP/1.1", host: "10.237.7.72"
2024/07/26 10:28:06 [error] 7922#7922: *20894 limiting requests, excess: 10.240 by zone "hoanghd_zone", client: 10.237.7.250, server: _, request: "GET /hoanghd HTTP/1.1", host: "10.237.7.72"

6. Tổng kết.

ngx_http_limit_req_module là một công cụ hữu ích để bảo vệ máy chủ Nginx khỏi quá tải và các cuộc tấn công. Bằng cách hiểu rõ cách thức hoạt động của module này và áp dụng nó một cách hợp lý, bạn có thể tăng cường đáng kể độ ổn định và bảo mật cho hệ thống của mình.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories