محدود کردن درخواست (Rate Limit) و بلاک کردن IP در nginx

ربات‌ها و حمله‌کننده‌ها می‌توانند با فرستادن هزاران درخواست سرور را کند کنند یا رمز صفحهٔ ورود را حدس بزنند. nginx می‌تواند تعداد درخواست هر IP را محدود کند و IP های مشکل‌دار را مسدود کند.

وب‌سرور و SSLمتوسط8 دقیقه

۱تعریف zone های محدودیت (در بلوک http)

zone یک حافظهٔ مشترک است که تعداد درخواست هر IP را نگه می‌دارد. ۱۰ مگابایت حافظه برای حدود ۱۶۰ هزار IP کافی است.

nginx
sudo nano /etc/nginx/conf.d/limits.conf

# محدودیت عمومی: ۱۰ درخواست در ثانیه برای هر IP
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;

# محدودیت سخت‌گیرانه برای صفحهٔ ورود: ۵ درخواست در دقیقه
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;

# محدودیت تعداد اتصال هم‌زمان
limit_conn_zone $binary_remote_addr zone=perip:10m;

# کد پاسخ هنگام رد شدن (به‌جای 503)
limit_req_status 429;
limit_conn_status 429;

۲اعمال محدودیت عمومی روی سایت

burst تعداد درخواست ناگهانی قابل قبول را مشخص می‌کند و nodelay آن‌ها را بدون تأخیر می‌پذیرد.

nginx
server {
    ...
    limit_req  zone=general burst=20 nodelay;
    limit_conn perip 30;
}

۳محدودیت شدیدتر برای صفحهٔ ورود

صفحات ورود و ثبت‌نام و API رمز عبور اصلی‌ترین هدف حملهٔ brute-force هستند.

nginx
    location = /login {
        limit_req zone=login burst=5 nodelay;
        proxy_pass http://127.0.0.1:3000;
    }

    location /wp-login.php {
        limit_req zone=login burst=3 nodelay;
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
    }

۴بلاک کردن IP یا بازهٔ IP

دستورهای deny و allow از بالا به پایین بررسی می‌شوند و اولین تطابق اجرا می‌شود.

nginx
    deny 203.0.113.10;
    deny 198.51.100.0/24;
    allow all;

۵بلاک کردن ربات‌ها با User-Agent

برای ربات‌های بدرفتار و اسکنرها که با نام مشخص شناخته می‌شوند. خارج از location و در بلوک server قرار دهید.

nginx
    if ($http_user_agent ~* (sqlmap|nikto|masscan|wpscan|semrushbot|ahrefsbot)) {
        return 403;
    }

if در nginx باید فقط برای return ساده استفاده شود. بلاک کردن ربات‌های مفید مثل Googlebot باعث افت سئو می‌شود.

۶دسترسی پنل مدیریت فقط از IP مشخص

امن‌ترین کار برای پنل‌هایی مثل phpMyAdmin یا /admin محدود کردن به IP دفتر یا VPN است.

nginx
    location /admin/ {
        allow 203.0.113.5;      # IP دفتر
        allow 10.8.0.0/24;      # شبکهٔ VPN
        deny all;
        proxy_pass http://127.0.0.1:3000;
    }

۷IP واقعی پشت Cloudflare یا پروکسی

اگر پشت CDN هستید همهٔ درخواست‌ها با IP همان CDN دیده می‌شوند و rate limit همهٔ کاربران را یکی می‌کند. باید IP واقعی را از هدر بخوانید.

nginx
# فقط برای IP های Cloudflare (فهرست کامل: cloudflare.com/ips)
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
real_ip_header CF-Connecting-IP;

لیست رسمی IP ها را حتماً از سایت Cloudflare بخوانید و به‌روز نگه دارید.

۸تست و مشاهدهٔ نتیجه

پس از reload، با چند درخواست پشت‌سرهم کد 429 را ببینید و در لاگ خطا رد شدن‌ها را بررسی کنید.

bash
sudo nginx -t && sudo systemctl reload nginx
for i in $(seq 1 30); do curl -s -o /dev/null -w "%{http_code} " https://example.com/login; done; echo
sudo grep -i 'limiting requests' /var/log/nginx/error.log | tail

پرسش‌های پرتکرار دربارهٔ محدود کردن درخواست (Rate Limit) و بلاک کردن IP در nginx

تفاوت limit_req و limit_conn چیست؟

limit_req نرخ درخواست در واحد زمان را محدود می‌کند (مثلاً ۱۰ در ثانیه) و limit_conn تعداد اتصال هم‌زمان باز را. برای حملهٔ اسکرپینگ و brute-force اولی و برای دانلود سنگین دومی مناسب است.

بهتر است از fail2ban استفاده کنم یا rate limit؟

هر دو مکمل هم‌اند: rate limit درخواست اضافی را همان لحظه رد می‌کند و fail2ban با خواندن لاگ IP را برای مدت طولانی در فایروال مسدود می‌کند.