ایمنسازی حرفهای Nginx: مسدودسازی جغرافیایی و مقابله با حملات (راهنمای ویژه توسعهدهندگان .NET)
نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۱۲/۰۱ ۱۳:۰۰
آدرس: www.dntips.ir
| مطالب | ۳۶۹۴ |
| نویسندگان | ۲۷۶ |
| گروههای مطالب | ۱۰۲۴ |
| نقشههای راه | ۱۱۹ |
| دورهها | ۱۴ |
| اشتراکها | ۱۷۹۱۴ |
geoip منسوخ شده است. روش استاندارد و مدرن، استفاده از ماژول ngx_http_geoip2_module است.sudo apt update sudo apt install libnginx-mod-http-geoip2 -y
GeoLite2-Country نیاز داریم. این دیتابیس برای تشخیص کشورها دقت بالایی دارد (دقت شهر برای هدف ما نیاز نیست).sudo mkdir -p /etc/nginx/geoip cd /etc/nginx/geoip # دانلود دیتابیس (از میرور گیتهاب برای دسترسی سریع) wget https://github.com/P3TERX/GeoLite.mmdb/raw/download/GeoLite2-Country.mmdb
nginx.conf)444 استفاده میکنیم. این کد استاندارد HTTP نیست، بلکه مخصوص Nginx است و به سرور میگوید "بدون ارسال هیچ پاسخی، کانکشن را قطع کن". این کار دو مزیت دارد:/etc/nginx/nginx.conf را ویرایش کنید:http {
# ... سایر تنظیمات ...
# بارگذاری دیتابیس GeoIP2
geoip2 /etc/nginx/geoip/GeoLite2-Country.mmdb {
$geoip2_country_code country iso_code;
}
# نقشهبرداری کد کشورها به وضعیت بلاک
map $geoip2_country_code $block_country {
default 0; # به صورت پیشفرض همه مجاز هستند
CN 1; # چین
RU 1; # روسیه
VN 1; # ویتنام
# سایر کدهای ISO کشورها را میتوانید اضافه کنید
}
# تعریف Rate Limit عمومی (توضیحات در بخش دوم)
limit_req_zone $binary_remote_addr zone=global:10m rate=15r/s;
}/etc/nginx/sites-available/default یا فایل کانفیگ پروژه داتنت شما)، شرط بررسی را اضافه کنید:server {
listen 80;
server_name yourdomain.com;
# بلاک کردن کشورها قبل از هر پردازشی
if ($block_country) {
return 444;
}
location / {
# اعمال محدودیت نرخ درخواست
limit_req zone=global burst=30 nodelay;
# تنظیمات پروکسی به سمت Kestrel
proxy_pass http://localhost:5000;
# ... سایر تنظیمات پروکسی ...
}
}rate=15r/s: اجازه ۱۵ درخواست در ثانیه به ازای هر IP.burst=30: اجازه میدهد ترافیک ناگهانی تا ۳۰ درخواست در صف قرار گیرد.nodelay: درخواستهای موجود در burst را بدون وقفه پردازش میکند (تجربه کاربری بهتر برای کاربران واقعی)، اما اگر از حد بگذرد، خطا میدهد./usr/local/bin/update-geoip.sh را ایجاد کنید:#!/usr/bin/env bash
set -euo pipefail
# تنظیم متغیرها
GEOIP_DIR="/etc/nginx/geoip"
TMP_DIR="$(mktemp -d)"
DB_NAME="GeoLite2-Country.mmdb"
URL="https://github.com/P3TERX/GeoLite.mmdb/raw/download/${DB_NAME}"
LOG="/var/log/geoip-update.log"
echo "[$(date)] Starting GeoIP update" >> "$LOG"
# دانلود در پوشه موقت
cd "$TMP_DIR"
wget -q --timeout=30 "$URL"
# Sanity Check: بررسی اینکه فایل دانلود شده سالم و غیرخالی باشد
if [ ! -s "$DB_NAME" ]; then
echo "[$(date)] Download failed or empty file" >> "$LOG"
exit 1
fi
# جایگزینی اتمیک (Atomic Replace)
# این روش تضمین میکند که Nginx هرگز فایل ناقص یا خراب را نمیخواند
mv "$DB_NAME" "$GEOIP_DIR/${DB_NAME}.new"
mv "$GEOIP_DIR/${DB_NAME}.new" "$GEOIP_DIR/$DB_NAME"
# بارگذاری مجدد سرویس (Reload نه Restart)
nginx -t && systemctl reload nginx
echo "[$(date)] GeoIP update successful" >> "$LOG"
rm -rf "$TMP_DIR"sudo chmod +x /usr/local/bin/update-geoip.sh sudo crontab -e
0 3 * * 1 /usr/local/bin/update-geoip.sh
wp-login.php, .env, .git و... میگردند./etc/fail2ban/filter.d/ ایجاد کنید.[Definition] failregex = limiting requests, excess:.* by zone.*client: <HOST> ignoreregex =
[Definition] failregex = ^<HOST> - .* "(GET|POST).*?(wp-login\.php|xmlrpc\.php|\.env|\.git|phpmyadmin).*" (404|403|444) ignoreregex =
[Definition] failregex = ^<HOST> - .* "(GET|POST).*" 4(03|04|44) ignoreregex =
/etc/fail2ban/jail.d/nginx.conf را ایجاد کنید. در اینجا سیاستهای سختگیرانهای برای محیط Production اعمال میکنیم.[nginx-req-limit] enabled = true filter = nginx-req-limit port = http,https logpath = /var/log/nginx/error.log maxretry = 3 findtime = 60 bantime = 1d # بن شدن به مدت یک روز [nginx-custom-bot] enabled = true filter = nginx-custom-bot port = http,https logpath = /var/log/nginx/access.log maxretry = 2 # حساسیت بالا: با دومین تلاش بن میشود findtime = 10m bantime = 7d # بن طولانی مدت (یک هفته) [nginx-4xx] enabled = true filter = nginx-4xx port = http,https logpath = /var/log/nginx/access.log maxretry = 10 findtime = 1m bantime = 6h
systemctl restart fail2ban
fail2ban-client status nginx-custom-bot چک کنید تا ببینید چه تعداد حمله دفع شده است.bantime = -1 (بن دائم) قرار ندهید؛ زیرا به مرور زمان دیتابیس Fail2Ban بسیار حجیم و کند میشود. بنهای طولانی (مثلاً یک هفته) کافی و موثر هستند.nginx -t را اجرا کنید تا از صحت Syntax مطمئن شوید.