Hướng dẫn cấu hình Rate Limiting trong HAProxy để chống DDoS
Bài viết sẽ hướng dẫn chi tiết từng bước thiết lập rate limiting, giải thích lệnh, và giới thiệu cách sử dụng script Lua để bổ sung các headers thông báo cho client về trạng thái giới hạn của mình.
Giới thiệu
Mục tiêu
Cấu Hình HAProxy Rate Limiting
1. Cấu hình trong haproxy.cfg
haproxy.cfg # --------------------------------------------------- #
# ### HAProxy Rate Limiting ###
# https://www.haproxy.com/blog/four-examples-of-haproxy-rate-limiting
# Cấu hình giới hạn tốc độ yêu cầu (Rate Limiting) cho mỗi địa chỉ IP client
# `is_host_have_rate_limiting` ACL để kiểm tra khi có bật chế độ Rate Limiting
# Chỉ kích hoạt rate limiting cho các yêu cầu đến host "hdr(host) -i nqdev.local"
acl is_host_have_rate_limiting hdr(host) -i nqdev.local
# ### Stick-table cho giới hạn theo IP ###
# Tạo một stick-table với kích thước 1m, hết hạn sau 10 phút, và lưu số lượng yêu cầu HTTP trong 10 giây qua.
# Mỗi mục trong stick-table sẽ hết hạn (expire) sau 10 giây kể từ lần cuối cùng mục đó được truy cập hoặc cập nhật.
# type: binary | ip | string
stick-table type string size 1m expire 10s store http_req_rate(1s)
# Track IP của client bằng http-request (thay vì tcp-request)
# Kết hợp base32 + src (Host header + URL path + src IP) để tạo khóa theo dõi duy nhất cho từng IP và yêu cầu.
# http-request track-sc0 base32+src
# Lấy thời gian hiện tại và lưu vào biến
http-request lua.set_ratelimit_timestamp
# Lưu timestamp vào biến
# http-request set-var(req.timestamp) date
# Sử dụng track với khóa kết hợp IP và timestamp
http-request track-sc0 src,concat(_,req.ip_request_timestamp)
# Đọc giới hạn tốc độ từ file map cho từng IP
# File map (ipclient-rates.map) chứa giới hạn tốc độ cho từng IP cụ thể. -1: không giới hạn tốc độ.
http-request set-var(req.ip_rate_limit) src,map_beg(/usr/local/etc/haproxy/map/ipclient-rates.map,2)
# Kiểm tra nếu giới hạn tốc độ của IP là -1 (tức là không áp dụng giới hạn với IP này)
acl ignore_ip_limit var(req.ip_rate_limit) -m int eq -1
# Lấy tốc độ yêu cầu hiện tại của IP từ stick-table và lưu vào biến `req.ip_request_usage`
# Nếu sử dụng nhiều stick-table hoặc nhiều store khác nhau, các stick-counters được đánh số từ sc0, sc1, sc2,…
http-request set-var(req.ip_request_usage) sc0_http_req_rate()
# So sánh tốc độ yêu cầu của IP với giới hạn từ file map.
# Nếu tốc độ hiện tại vượt quá giới hạn, thì `rate_limit_above_limit` sẽ kích hoạt
acl rate_limit_above_limit var(req.ip_rate_limit),sub(req.ip_request_usage) lt 0
# Thêm tốc độ yêu cầu vào header của phản hồi HTTP để client có thể thấy giới hạn của mình
http-request add-header x-ratelimit-limit %[var(req.ip_rate_limit)]
http-request add-header x-ratelimit-usage %[var(req.ip_request_usage)]
# Lưu giá trị `req.ip_rate_limit` vào `txn.rate_limit` trong giai đoạn `http-request`
# Giúp chuyển giá trị này đến bước xử lý `http-response` sau
http-request lua.save_ratelimit_info
# Thêm header `x-ratelimit-*` vào phản hồi trong giai đoạn `http-response` để cung cấp thông tin về giới hạn
http-response lua.add_ratelimit_headers
# Sử dụng Lua service cho các yêu cầu với trạng thái 429 (Too Many Requests)
# Nếu IP vượt quá giới hạn tốc độ và IP không nằm trong danh sách được bỏ qua, thì trả về mã lỗi 429
# http-request use-service lua.deny_429_ratelimit_headers if rate_limit_above_limit !ignore_ip_limit
http-request use-service lua.deny_429_ratelimit_headers if rate_limit_above_limit !ignore_ip_limit is_host_have_rate_limiting
# Quy tắc xử lý giới hạn tốc độ
# Nếu vượt quá giới hạn theo đường dẫn và không bỏ qua giới hạn theo IP, thì trả về mã lỗi 429
# http-request deny deny_status 429 if rate_limit_above_limit !ignore_ip_limit
http-request deny deny_status 429 if rate_limit_above_limit !ignore_ip_limit is_host_have_rate_limiting
# ### HAProxy Rate Limiting ###
# --------------------------------------------------- #
Giải thích các dòng lệnh:
2. Tạo Lua script để quản lý Header và Response
Giải thích Lua script:
3. Cấu hình file ipclient-rates.map
ipclient-rates.mapGiải thích file ipclient-rates.map:
ipclient-rates.map:Kết Luận
Last updated