پشت CDN، همهٔ درخواستها از آیپی سرورهای لبه به Nginx میرسند و آیپی واقعی کاربر در هدری مثل X-Forwarded-For یا X-Real-IP قرار دارد. با ماژول real_ip و دستورهای set_real_ip_from (محدودهٔ آیپیهای CDN) و real_ip_header، Nginx آیپی واقعی را جایگزین میکند تا لاگها، محدودیت نرخ، Fail2ban و برنامهها درست کار کنند. فقط به آیپیهای CDN اعتماد کنید، وگرنه هر کسی میتواند هدر را جعل کند.
مشکل: همهٔ کاربران یک آیپی دارند
وقتی سایت را پشت CDN قرار میدهید، کاربر دیگر مستقیم به سرور شما وصل نمیشود. مسیر اینطور است: کاربر به سرور لبهٔ CDN وصل میشود و سرور لبه یک اتصال جداگانه به سرور شما برقرار میکند. از دید Nginx، طرف مقابل اتصال همیشه یکی از سرورهای CDN است.
نتیجهاش در جاهای مختلف خودش را نشان میدهد:
- لاگ دسترسی Nginx فقط آیپیهای CDN را نشان میدهد و نمیدانید بازدیدکنندگان واقعی از کجا آمدهاند.
- محدودیت نرخ (
limit_req) بر اساس آیپی، بهجای یک کاربر مزاحم، کل ترافیک یک سرور لبه را محدود میکند. - Fail2ban ممکن است آیپی CDN را بن کند و بخش بزرگی از کاربران واقعی را قطع کند.
- برنامههایی مثل وردپرس آیپی کامنتگذاران یا لاگینها را اشتباه ثبت میکنند و ابزارهای ضداسپم کاراییشان را از دست میدهند.
- قوانین دسترسی بر اساس آیپی (مثلاً محدود کردن پنل مدیریت به آیپی دفتر) کار نمیکنند.
آیپی واقعی کجاست؟
CDN آیپی کاربر را در یک هدر HTTP به سرور شما میفرستد. هدرهای رایج:
| هدر | توضیح |
|---|---|
X-Forwarded-For |
استاندارد غیررسمی رایج؛ فهرستی از آیپیها که هر پروکسی به انتهایش اضافه میکند |
X-Real-IP |
فقط یک آیپی؛ برخی پروکسیها و CDNها استفاده میکنند |
CF-Connecting-IP |
مخصوص Cloudflare |
True-Client-IP |
در برخی CDNهای دیگر |
مستندات CDN خود را ببینید تا بدانید کدام هدر را میفرستد. برای اطمینان، میتوانید موقتاً هدرها را در لاگ ثبت کنید (بخش آخر مقاله).
پیکربندی ماژول real_ip
ماژول ngx_http_realip_module در بستههای رایج Nginx روی اوبونتو و دبیان وجود دارد. دو دستور اصلی لازم است: اینکه به کدام آیپیها اعتماد کنیم و آیپی واقعی را از کدام هدر بخوانیم. یک فایل جداگانه بسازید:
sudo nano /etc/nginx/conf.d/realip.conf
# محدودههای آیپی سرورهای CDN (از مستندات CDN خود بگیرید)
set_real_ip_from 192.0.2.0/24;
set_real_ip_from 198.51.100.0/24;
set_real_ip_from 2001:db8::/32;
# هدری که آیپی واقعی در آن است
real_ip_header X-Forwarded-For;
real_ip_recursive on;
آیپیهای بالا نمونهاند؛ فهرست واقعی را از صفحهٔ رسمی محدودههای آیپی CDN خود بگیرید. سپس:
sudo nginx -t && sudo systemctl reload nginx
از این لحظه متغیر $remote_addr در Nginx آیپی واقعی کاربر است و همهٔ ماژولها، از لاگ تا limit_req و allow/deny، با همان کار میکنند.
real_ip_recursive چه میکند؟
هدر X-Forwarded-For ممکن است چند آیپی داشته باشد؛ مثلاً اگر کاربر خودش پشت یک پروکسی باشد یا CDN چند لایه داشته باشد. با real_ip_recursive on، Nginx از انتهای فهرست شروع میکند، آیپیهایی را که در set_real_ip_from معتمد تعریف شدهاند کنار میگذارد و اولین آیپی غیرمعتمد را بهعنوان آیپی واقعی انتخاب میکند. بدون این گزینه، فقط آخرین آیپی فهرست استفاده میشود که ممکن است خودش یکی از پروکسیها باشد.
- لاگ پر از آیپی CDN
- limit_req کل یک لبه را محدود میکند
- Fail2ban ممکن است CDN را بن کند
- آمار بازدید بیمعنا
- آیپی واقعی در لاگ
- محدودیت نرخ برای هر کاربر
- تشخیص درست مزاحم
- allow و deny قابلاستفاده
چرا set_real_ip_from اینقدر مهم است؟
هدرهای HTTP را هر کسی میتواند بفرستد. اگر به همهٔ آیپیها اعتماد کنید (مثلاً set_real_ip_from 0.0.0.0/0)، مهاجمی که آیپی سرور شما را پیدا کند میتواند مستقیم و بدون CDN درخواست بفرستد و در هدر X-Forwarded-For هر آیپی دلخواهی بنویسد. نتیجه: دور زدن محدودیت نرخ، بن شدن آیپیهای بیگناه توسط Fail2ban، یا حتی دسترسی به بخشهایی که فقط برای آیپی خاصی باز است.
بنابراین:
- فقط محدودههای رسمی CDN را در
set_real_ip_fromبگذارید. - این فهرست را دورهای بهروز کنید؛ CDNها گاهی محدودههای جدید اضافه میکنند. اگر محدودهای جا بیفتد، کاربرانی که از آن سرورهای لبه میآیند با آیپی CDN ثبت میشوند.
- در صورت امکان، در فایروال سرور ورود به پورتهای ۸۰ و ۴۴۳ را فقط برای آیپیهای CDN باز کنید تا هیچکس نتواند CDN را دور بزند.
Nginx پشت Nginx: وقتی برنامه هم آیپی را لازم دارد
اگر Nginx خودش بهعنوان Reverse Proxy درخواستها را به برنامهای (Node.js، پایتون، PHP یا کانتینر داکر) میفرستد، باید آیپی واقعی را به آن برنامه هم منتقل کنید:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
سپس در برنامه، تنظیم «اعتماد به پروکسی» را فعال کنید؛ مثلاً app.set('trust proxy', ...) در Express یا ProxyFix در Flask یا TrustProxies در لاراول. این تنظیمات هم باید فقط به آیپی Nginx محلی (معمولاً 127.0.0.1) اعتماد کنند.
اثر روی Fail2ban و محدودیت نرخ
پس از پیکربندی real_ip، لاگهای Nginx آیپی واقعی را ثبت میکنند و Fail2ban میتواند کاربران مزاحم را درست تشخیص دهد. اما یک نکتهٔ مهم باقی میماند: بن کردن آیپی کاربر در فایروال سرور (iptables) اثری ندارد، چون اتصالها از آیپی CDN میآیند، نه از کاربر. برای سایتهای پشت CDN، مسدودسازی باید در خود Nginx (با deny یا limit_req) یا در پنل CDN انجام شود. پیکربندی پایهٔ Fail2ban را در آموزش Fail2ban ببینید.
بررسی صحت پیکربندی
برای اطمینان از اینکه همهچیز درست است، یک قالب لاگ موقت تعریف کنید که هم آیپی نهایی و هم هدر خام را ثبت کند:
log_format realip '$remote_addr | xff="$http_x_forwarded_for" | $request';
access_log /var/log/nginx/realip-test.log realip;
سایت را از گوشی یا کامپیوتر خود باز کنید و لاگ را ببینید. ستون اول باید آیپی عمومی شما باشد، نه آیپی CDN. پس از اطمینان، این لاگ موقت را حذف کنید.
$ tail -n 1 /var/log/nginx/realip-test.log198.51.100.25 | xff="198.51.100.25, 192.0.2.10" | GET / HTTP/2.0$ nginx -t && systemctl reload nginxnginx: configuration file /etc/nginx/nginx.conf test is successful$
اگر بهجای Nginx از Apache یا برنامهٔ مستقیم استفاده میکنید
همین مشکل در هر وبسروری وجود دارد و راهحل هم مشابه است. در Apache ماژول mod_remoteip همین کار را انجام میدهد: با دستور RemoteIPHeader نام هدر و با RemoteIPTrustedProxy محدودههای معتمد را تعیین میکنید. پس از فعالسازی، باید قالب لاگ را هم طوری تغییر دهید که از آیپی بازنویسیشده استفاده کند، وگرنه لاگ همچنان آیپی CDN را نشان میدهد.
اگر برنامهٔ شما بدون وبسرور میانی و مستقیم پشت CDN است، مثلاً یک برنامهٔ Node.js که خودش روی پورت ۴۴۳ گوش میدهد، مسئولیت خواندن هدر و اعتبارسنجی آیپیهای معتمد با خود برنامه است. در این حالت هم اصل یکسان است: فقط وقتی به هدر اعتماد کنید که اتصال از آیپیهای CDN آمده باشد.
حریم خصوصی و نگهداری آیپیها
وقتی آیپی واقعی کاربران در لاگها ثبت میشود، این لاگها دادهٔ حساسی هستند. لاگها را فقط به مدتی که برای عیبیابی و امنیت لازم است نگه دارید، با logrotate نسخههای قدیمی را حذف کنید و دسترسی به پوشهٔ لاگ را محدود نگه دارید. اگر لاگها را برای تحلیل به سرویس دیگری میفرستید، در نظر بگیرید که آیپی کامل لازم است یا بخشی از آن کافی است.
خطاهای رایج
- هنوز آیپی CDN در لاگ است: محدودهٔ آیپی سرور لبه در
set_real_ip_fromنیست یا نام هدر اشتباه است. - آیپیهای عجیب یا خصوصی در لاگ: احتمالاً
real_ip_recursiveخاموش است و آیپی میانی انتخاب شده، یا به محدودهای بیش از حد گسترده اعتماد کردهاید. - پیکربندی در یک server block است و در دیگری نه: فایل را در
conf.dقرار دهید تا در سطح http برای همهٔ سایتها اعمال شود.
برای آشنایی بیشتر با پیکربندی Nginx، آموزش کانفیگ Nginx را بخوانید. اگر بعد از فعالسازی CDN سایت خطا میدهد، خطاهای 5xx در CDN را ببینید. CDN اختصاصی کلودیفای با پرداخت بهازای مصرف و بدون بستهٔ ماهانه در دسترس است.
سؤالات متداول
چرا در لاگ Nginx فقط آیپی CDN را میبینم؟
چون اتصال به سرور شما از طرف سرور لبهٔ CDN برقرار میشود. آیپی واقعی کاربر در هدری مثل X-Forwarded-For است و برای استفاده از آن باید ماژول real_ip را پیکربندی کنید.
آیا اعتماد به X-Forwarded-For خطرناک است؟
اگر به همهٔ آیپیها اعتماد کنید بله، چون هر کسی میتواند این هدر را جعل کند. فقط محدودههای آیپی رسمی CDN را در set_real_ip_from قرار دهید و در صورت امکان دسترسی مستقیم به سرور را در فایروال ببندید.
Fail2ban پشت CDN کار میکند؟
تشخیص با real_ip درست انجام میشود، اما مسدود کردن آیپی کاربر در فایروال سرور بیاثر است، چون اتصالها از CDN میآیند. مسدودسازی را در Nginx یا پنل CDN انجام دهید.
real_ip_recursive را روشن کنم یا خاموش؟
اگر هدر X-Forwarded-For استفاده میکنید، روشن باشد تا Nginx از میان فهرست آیپیها، اولین آیپی غیرمعتمد یعنی کاربر واقعی را انتخاب کند.
از ۱٬۲۰۰ تومان در ساعت · پرداخت ریالی



