Nginx menggunakan modul ngx_http_limit_req_module untuk mengimplementasikan rate limiting. Ada dua direktif utama yang akan kita gunakan:
-
limit_req_zone: Direktif ini mendefinisikan "zona" atau area memori bersama tempat Nginx akan menyimpan status permintaan untuk setiap klien (misalnya, berdasarkan IP address). Ini harus diletakkan di dalam blokhttp.Sintaksnya:
limit_req_zone $variable zone=name:size rate=rate [sync];
$variable: Variabel yang digunakan untuk mengidentifikasi klien. Umumnya kita menggunakan$binary_remote_addrkarena ini adalah representasi biner dari alamat IP klien yang lebih hemat memori daripada$remote_addr.zone=name:size: Nama zona (misalnya,mylimit) dan ukuran memori yang dialokasikan (misalnya,10muntuk 10 megabyte). Ukuran 10m bisa menyimpan sekitar 160.000 entri IP.rate=rate: Tingkat permintaan maksimum yang diizinkan (misalnya,1r/suntuk 1 permintaan per detik, atau30r/muntuk 30 permintaan per menit).[sync]: (Opsional) Jika Anda memiliki beberapa instance Nginx dan ingin mensinkronkan status rate limit di antara mereka. Umumnya tidak diperlukan untuk setup sederhana.
-
limit_req: Direktif ini menerapkan rate limit yang didefinisikan olehlimit_req_zoneke lokasi (endpoint) tertentu. Ini diletakkan di dalam blokhttp,server, ataulocation.Sintaksnya:
limit_req zone=name [burst=number] [nodelay | delay=number];
zone=name: Merujuk ke nama zona yang telah didefinisikan sebelumnya dilimit_req_zone.[burst=number]: (Opsional) Menentukan berapa banyak permintaan diizinkan untuk "meledak" atau tiba secara instan setelah batas tercapai, tanpa langsung diblokir. Permintaan burst ini akan diantrekan dan diproses jika ada kapasitas.[nodelay | delay=number]: (Opsional) Mengontrol bagaimana permintaan dalam burst ditangani.nodelay: Permintaan burst akan diproses secepat mungkin tanpa penundaan, tetapi hanya sampai batas rate reguler. Jika ada banyak permintaan burst, yang melebihi kapasitas rate reguler dan burst, maka permintaan akan langsung ditolak.delay=number: Permintaan dalam burst akan ditunda untuk diproses secara merata. Ini memastikan bahwa server tidak kewalahan oleh burst besar.
Misalkan Anda memiliki sebuah API atau situs web, dan Anda ingin membatasi upaya login untuk mencegah brute force attacks. Kita akan menerapkan rate limit hanya pada endpoint /api/login.
Buka file konfigurasi Nginx Anda (biasanya /etc/nginx/nginx.conf atau file konfigurasi virtual host di /etc/nginx/conf.d/ atau /etc/nginx/sites-available/).
Tambahkan direktif limit_req_zone di dalam blok http { ... }:
# /etc/nginx/nginx.conf atau file konfigurasi utama
http {
# ... konfigurasi http lainnya ...
# Mendefinisikan zona rate limit untuk login
# mylimitlogin: nama zona
# 10m: ukuran memori 10MB
# 5r/s: 5 permintaan per detik per IP
limit_req_zone $binary_remote_addr zone=mylimitlogin:10m rate=5r/s;
server {
# ... konfigurasi server lainnya ...
location /api/login {
# Menerapkan rate limit yang telah didefinisikan
# zone=mylimitlogin: Menggunakan zona mylimitlogin
# burst=10: Memungkinkan 10 permintaan burst (diantrekan)
# nodelay: Permintaan burst diproses secepat mungkin tanpa penundaan
limit_req zone=mylimitlogin burst=10 nodelay;
# Menambahkan header untuk informasi rate limit (opsional, tapi bagus untuk debugging)
add_header X-RateLimit-Limit 5;
add_header X-RateLimit-Remaining $limit_req_status; # Akan menunjukkan 'OK' atau 'REJECT'
add_header X-RateLimit-Reset $http_x_ratelimit_reset; # Anda perlu mengimplementasikan ini di aplikasi backend
proxy_pass http://backend_login_server; # Ganti dengan backend server Anda, misal mendeploy poject REST API berbasis NodeJs dengan pm2 di http://localhost:5000. maka arahkan ke http://localhost:5000
}
# ... endpoint lain tanpa rate limit atau dengan rate limit berbeda ...
}
}Penjelasan Konfigurasi:
-
limit_req_zone $binary_remote_addr zone=mylimitlogin:10m rate=5r/s;:- Kita membuat zona bernama
mylimitlogindengan ukuran 10MB. - Nginx akan melacak permintaan berdasarkan alamat IP klien (
$binary_remote_addr). - Setiap IP hanya diizinkan membuat 5 permintaan per detik.
- Kita membuat zona bernama
-
location /api/login { ... }:- Blok ini menargetkan endpoint
/api/login.
- Blok ini menargetkan endpoint
-
limit_req zone=mylimitlogin burst=10 nodelay;:- Kita menerapkan rate limit dari zona
mylimitloginke endpoint ini. burst=10berarti jika ada lonjakan permintaan (misalnya, lebih dari 5 per detik), Nginx akan mengizinkan hingga 10 permintaan tambahan untuk diantrekan sementara dan diproses secepatnya (sesuai rate 5r/s). Jika ada permintaan ke-11 atau lebih dalam burst tersebut, permintaan tersebut akan ditolak.nodelaymemastikan permintaan yang di-burst tidak sengaja ditunda lebih lama dari yang diperlukan oleh antrian Nginx (tetap mengikuti rate 5r/s).
- Kita menerapkan rate limit dari zona
-
add_header X-RateLimit-Limit 5;dll.:- Ini adalah header HTTP opsional yang berguna untuk memberi tahu klien tentang batas rate yang berlaku. Saat klien menerima kode
429 Too Many Requests, mereka dapat memeriksa header ini untuk memahami mengapa permintaan mereka ditolak dan kapan mereka bisa mencoba lagi.
- Ini adalah header HTTP opsional yang berguna untuk memberi tahu klien tentang batas rate yang berlaku. Saat klien menerima kode
Setelah memodifikasi file konfigurasi, sangat penting untuk menguji sintaks Nginx untuk memastikan tidak ada kesalahan:
sudo nginx -tJika outputnya seperti ini, berarti konfigurasi Anda baik-baik saja:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Jika pengujian berhasil, muat ulang Nginx agar perubahan konfigurasi diterapkan:
sudo systemctl reload nginxatau
sudo service nginx reloadSekarang, Anda bisa mencoba mengirimkan banyak permintaan ke /api/login dari satu IP address dalam waktu singkat. Anda bisa menggunakan curl atau alat lain.
Contoh dengan curl (jalankan ini berulang kali dengan cepat):
curl -v http://your_domain_or_ip/api/loginSetelah beberapa permintaan cepat, Anda akan mulai menerima respons dengan kode status HTTP 429 Too Many Requests. Anda juga akan melihat header X-RateLimit-Limit dan X-RateLimit-Remaining jika Anda menyertakannya dalam konfigurasi.
Secara default, Nginx akan mengembalikan error 429 Too Many Requests. Anda bisa mengkustomisasi halaman error ini:
http {
# ...
limit_req_zone $binary_remote_addr zone=mylimitlogin:10m rate=5r/s;
server {
# ...
error_page 429 /too_many_requests.html; # Mengarahkan ke halaman kustom
location = /too_many_requests.html {
internal; # Hanya bisa diakses secara internal oleh Nginx
return 429 "Ups, terlalu banyak permintaan. Coba lagi nanti!";
# Atau Anda bisa arahkan ke file HTML statis:
# root /var/www/html;
# index too_many_requests.html;
}
location /api/login {
limit_req zone=mylimitlogin burst=10 nodelay;
proxy_pass http://backend_login_server;
}
}
}Anda bisa mendefinisikan zona rate limit yang berbeda dan menerapkannya ke endpoint yang berbeda:
http {
limit_req_zone $binary_remote_addr zone=mylimitlogin:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=myapilimit:10m rate=20r/s; # Zona lain untuk API umum
server {
location /api/login {
limit_req zone=mylimitlogin burst=10 nodelay;
proxy_pass http://backend_login_server;
}
location /api/data { # Endpoint lain
limit_req zone=myapilimit burst=5 nodelay; # Menerapkan limit yang berbeda
proxy_pass http://backend_data_server;
}
location / { # Endpoint umum
limit_req zone=myapilimit; # Menerapkan limit yang sama atau berbeda tanpa burst
proxy_pass http://backend_main_server;
}
}
}Dengan mengikuti tutorial ini, Anda dapat secara efektif mengkonfigurasi rate limit Nginx untuk melindungi endpoint spesifik dari penyalahgunaan dan memastikan ketersediaan layanan Anda!