پراکسی و Reverse Proxy چیست؟ راهنمای جامع Nginx از مفاهیم تا پیکربندی Production
مهیار طلوعی اصل ·
·
۲۶ دقیقه مطالعه
این راهنما در مهر ۱۴۰۵ (اکتبر ۲۰۲۶) نوشته شده و نسخهها و رفتارهای پیشفرض Nginx در آن با مستندات رسمی nginx.org تطبیق داده شده است.
هر بار که آدرس یک وبسایت را در مرورگر وارد میکنید، به احتمال زیاد درخواست شما پیش از رسیدن به سرور اصلی از یک یا چند پراکسی عبور میکند: پراکسی شبکهی شرکت، یک CDN، یک Load Balancer یا وبسروری مثل Nginx که جلوی اپلیکیشن نشسته است. پراکسیها ستون پنهان وب امروزند؛ امنیت، سرعت، پایداری و مقیاسپذیری بسیاری از سرویسها به همین لایهی میانی وابسته است.
در این مقاله ابتدا مفاهیم پراکسی و انواع آن را مرور میکنیم و سپس سراغ Nginx میرویم: معماری، نصب، ساختار پیکربندی و مجموعهای از پیکربندیهای آماده برای Reverse Proxy، SSL، WebSocket، کش، محدودیت نرخ و هدرهای امنیتی.
بخش ۱ از ۱۵
۱. پراکسی چیست؟
پراکسی (Proxy) یا «سرور واسط» برنامه یا سروری است که میان یک کلاینت و یک سرور قرار میگیرد و درخواستها و پاسخها را به نمایندگی از یکی از طرفین جابهجا میکند. کلاینت بهجای اتصال مستقیم به مقصد، به پراکسی وصل میشود؛ پراکسی درخواست را بررسی، در صورت نیاز تغییر یا رد، و سپس به مقصد ارسال میکند و پاسخ را به کلاینت برمیگرداند.
کاربردهای پراکسی گسترده است: کنترل دسترسی، پنهانکردن نشانی کلاینت یا سرور، کش، توزیع بار، خاتمهی TLS و فیلتر کردن حملات.
۱.۱. پراکسی در یک نگاه
Direct: [Client] ----------------------------------> [Server]
Forward proxy: [Client] --> [Forward Proxy] --> Internet --> [Server]
(client knows about and is configured to use the proxy)
Reverse proxy: [Client] --> Internet --> [Reverse Proxy] --> [App 1]
\--> [App 2]
(client thinks the proxy IS the server)
بخش ۲ از ۱۵
۲. پراکسی فوروارد، معکوس و شفاف
مهمترین تقسیمبندی پراکسیها بر اساس جایگاه آنها در مسیر ارتباط و طرفی است که نمایندگیاش را بر عهده دارند.
۲.۱. پراکسی فوروارد (Forward Proxy)
پراکسی فوروارد در سمت کلاینت قرار میگیرد و از طرف کاربران یا دستگاههای یک شبکه با اینترنت ارتباط برقرار میکند. مرورگر یا سیستمعامل صراحتاً طوری تنظیم میشود که درخواستها را به پراکسی بفرستد (مثلاً با متغیرهای HTTP_PROXY و HTTPS_PROXY یا فایل PAC). سرور مقصد نشانی پراکسی را میبیند، نه نشانی کاربر را. کاربرد اصلی آن کنترل و ثبت دسترسی، کش مشترک و خروج کنترلشدهی سرورهای داخلی است. نمونهی کلاسیک این دسته Squid است.
۲.۲. پراکسی معکوس (Reverse Proxy)
پراکسی معکوس در سمت سرور قرار میگیرد و از طرف یک یا چند سرور پشتی (Backend) به درخواستهای اینترنت پاسخ میدهد. کلاینت معمولاً هیچ خبری از وجود آن ندارد؛ از دید او پراکسی همان وبسایت است. Nginx، HAProxy، Envoy و CDNها در این نقش به کار میروند.
۲.۳. پراکسی شفاف (Transparent Proxy)
پراکسی شفاف ترافیک را بدون نیاز به تنظیم در سمت کلاینت رهگیری میکند؛ معمولاً روتر یا فایروال ترافیک پورت ۸۰ را با قوانینی مثل iptables REDIRECT/TPROXY به سمت پراکسی هدایت میکند. شبکههای Wi-Fi عمومی (Captive Portal) و فیلترهای محتوای سازمانی از این روش استفاده میکنند. «شفاف» یعنی کاربر کاری انجام نمیدهد، نه اینکه پراکسی هویت او را پنهان میکند؛ این نوع معمولاً نشانی واقعی کاربر را هم در هدرها حفظ میکند. برای ترافیک HTTPS، پراکسی شفاف بدون نصب گواهی ریشهی سازمانی روی دستگاه کاربر نمیتواند محتوا را ببیند و حداکثر نام دامنه را از SNI تشخیص میدهد.
۲.۴. مقایسهی سه نوع
ویژگی
Forward Proxy
Reverse Proxy
Transparent Proxy
نمایندهی چه کسی است؟
کلاینتها
سرورها
معمولاً کلاینتها (در سطح شبکه)
محل قرارگیری
لبهی شبکهی کاربران
جلوی سرورهای اپلیکیشن
روی مسیر شبکه (روتر، فایروال)
تنظیم در کلاینت
لازم است
لازم نیست
لازم نیست
چه کسی از وجودش خبر دارد؟
کلاینت
مدیر سرور
مدیر شبکه
کاربردهای رایج
کنترل دسترسی، کش، ناشناسی
توزیع بار، TLS، کش، WAF
فیلتر محتوا، Captive Portal
نمونهها
Squid، Tinyproxy
Nginx، HAProxy، Envoy، CDN
Squid در حالت intercept
بخش ۳ از ۱۵
۳. انواع پراکسی از نظر پروتکل و ناشناسی
۳.۱. پراکسی HTTP و تونل HTTPS با CONNECT
پراکسی HTTP درخواستهای HTTP را کامل میخواند و میتواند هدرها را تغییر دهد، محتوا را کش کند یا آدرسهایی را مسدود کند. برای HTTPS وضعیت فرق دارد: کلاینت با متد CONNECT از پراکسی میخواهد یک تونل TCP به host:443 باز کند و سپس رمزنگاری TLS را مستقیماً با سرور مقصد انجام میدهد. پراکسی در این حالت فقط بایتهای رمزشده را جابهجا میکند و محتوای درخواست را نمیبیند؛ مگر اینکه سازمان «بازرسی TLS» (TLS Inspection) را با نصب گواهی ریشهی خودش روی دستگاهها فعال کرده باشد.
# Use an HTTP proxy for one request
curl -x http://proxy.example.com:3128 https://example.org/
# Or for the whole shell session
export HTTP_PROXY=http://proxy.example.com:3128
export HTTPS_PROXY=http://proxy.example.com:3128
export NO_PROXY=localhost,127.0.0.1,.internal.example.com
۳.۲. پراکسی SOCKS4 و SOCKS5
SOCKS پروتکلی سطح پایینتر از HTTP است و هر نوع اتصال TCP را جابهجا میکند، بیآنکه محتوای آن را تفسیر کند. SOCKS4 فقط TCP و نشانی IPv4 را پشتیبانی میکند (نسخهی SOCKS4a امکان ارسال نام دامنه را اضافه کرد). SOCKS5 که در RFC 1928 تعریف شده، احراز هویت (مثلاً نام کاربری و رمز طبق RFC 1929)، IPv6، نام دامنه و UDP را هم پشتیبانی میکند. سادهترین راه ساختن یک پراکسی SOCKS5 شخصی، قابلیت Dynamic Forwarding در SSH است:
# Open a local SOCKS5 proxy on port 1080 through an SSH server
ssh -D 1080 -N user@jump.example.com
# Use it; --socks5-hostname also resolves DNS through the proxy
curl --socks5-hostname 127.0.0.1:1080 https://example.org/
۳.۳. سطح ناشناسی: شفاف، ناشناس و Elite
برای پراکسیهای فوروارد معمولاً سه سطح ناشناسی (غیررسمی اما رایج) تعریف میشود:
شفاف (Transparent): نشانی واقعی کاربر را در هدرهایی مثل X-Forwarded-For به سرور مقصد میفرستد. فقط برای کش یا کنترل به کار میرود، نه حفظ حریم خصوصی.
ناشناس (Anonymous): نشانی کاربر را پنهان میکند، اما با هدرهایی مثل Via نشان میدهد که درخواست از پراکسی آمده است.
Elite یا High Anonymity: هیچ هدری اضافه نمیکند و از دید سرور مثل یک کاربر عادی است.
۳.۴. پراکسی کش (Caching Proxy)
پراکسی کش پاسخهای قابلذخیره را نگه میدارد تا درخواستهای تکراری بدون مراجعه به سرور اصلی پاسخ داده شوند. این کار هم در سمت کاربران (Squid) و هم در سمت سرور (Varnish یا کش Nginx) کاربرد دارد. CDNها در واقع شبکهای جهانی از پراکسیهای معکوسِ کشکنندهاند.
بخش ۴ از ۱۵
۴. کاربردهای Reverse Proxy
Reverse Proxy امروزه تقریباً جزء ثابت هر معماری وب جدی است. مهمترین کارهایی که بر عهده میگیرد:
توزیع بار (Load Balancing): پخش درخواستها میان چند نمونه از اپلیکیشن تا هیچ سروری بیش از حد شلوغ نشود و از کار افتادن یک سرور سرویس را قطع نکند.
خاتمهی SSL/TLS (TLS Termination): رمزگشایی HTTPS در پراکسی انجام میشود و اپلیکیشنها درگیر مدیریت گواهی و رمزنگاری نمیشوند. اگر شبکهی داخلی قابلاعتماد نیست، پراکسی میتواند دوباره با TLS به Backend وصل شود (Re-encryption).
کش: نگهداشتن پاسخهای پرتکرار در حافظه یا دیسک و کاهش چشمگیر بار پایگاه داده و اپلیکیشن.
فشردهسازی: فشردهکردن پاسخهای متنی با gzip (یا Brotli با ماژول جانبی) پیش از ارسال به کاربر.
امنیت و WAF: محدودیت نرخ درخواست، مسدودسازی IP، فیلتر کردن متدها و مسیرها، اعمال هدرهای امنیتی و اتصال فایروال برنامهی وب (WAF) مثل ModSecurity یا Coraza.
پنهانکردن Backendها: سرورهای اصلی IP عمومی ندارند و فقط پراکسی در معرض اینترنت است؛ ساختار داخلی، پورتها و نسخهی نرمافزارها از دید مهاجم پنهان میماند.
مسیریابی و یک نقطهی ورود: بر اساس نام دامنه یا مسیر، درخواستها به سرویسهای مختلف فرستاده میشوند؛ مثلاً /api به سرویس Node.js و / به فرانتاند.
۴.۱. مفهوم API Gateway
API Gateway نوعی Reverse Proxy تخصصی برای APIهاست که علاوه بر مسیریابی و توزیع بار، کارهایی مثل احراز هویت با کلید API یا توکن JWT، سهمیهبندی هر مشتری، تبدیل درخواست و پاسخ، نسخهگذاری، ثبت متریک و پرتال توسعهدهندگان را هم انجام میدهد. محصولاتی مثل Kong (مبتنی بر Nginx و OpenResty)، WSO2 API Manager، Apigee و Envoy Gateway در این دستهاند. Nginx بهتنهایی فقط بخشی از این کارها را پوشش میدهد.
بخش ۵ از ۱۵
۵. توزیع بار و الگوریتمهای آن
در Nginx گروه سرورهای پشتی با بلوک upstream تعریف میشود و الگوریتم توزیع با یک دستور در همان بلوک تعیین میشود. اگر هیچ الگوریتمی مشخص نشود، Round Robin وزندار استفاده میشود.
الگوریتم
دستور در Nginx
نحوهی کار
مناسب برای
Round Robin
(پیشفرض)
درخواستها بهنوبت میان سرورها پخش میشوند
سرورهای همتوان و درخواستهای مشابه
وزندار
weight=3
سرور با وزن بیشتر سهم بیشتری میگیرد
سرورهای با توان متفاوت، Canary
کمترین اتصال
least_conn
سرور با کمترین اتصال فعال انتخاب میشود
درخواستهای با مدت متفاوت، WebSocket
هش IP
ip_hash
کلاینت با IP ثابت همیشه به یک سرور میرود
Session چسبندهی ساده
هش دلخواه
hash $request_uri consistent
بر اساس هر کلید، با هش سازگار (ketama)
سرورهای کش، شاردینگ
تصادفی
random two least_conn
دو سرور تصادفی، سپس انتخاب کمبارتر
خوشههای بزرگ و چند Load Balancer
کمترین زمان پاسخ
least_time header
میانگین زمان پاسخ و اتصالهای فعال
در نسخهی متنباز از mainline 1.31.0
upstream app_backend {
least_conn; # pick the least busy server
server 10.0.0.11:8080 weight=3; # gets ~3x more requests
server 10.0.0.12:8080 max_fails=3 fail_timeout=30s;
server 10.0.0.13:8080 backup; # used only if the others fail
server 10.0.0.14:8080 down; # temporarily removed
keepalive 32; # idle connections kept per worker
}
۵.۱. بررسی سلامت (Health Check)
نسخهی متنباز Nginx بررسی سلامت غیرفعال (Passive) دارد: اگر در بازهی fail_timeout (پیشفرض ۱۰ ثانیه) به تعداد max_fails (پیشفرض ۱) خطا رخ دهد، آن سرور برای همان مدت کنار گذاشته میشود. اینکه چه چیزی «خطا» حساب شود با proxy_next_upstream تعیین میشود. بررسی سلامت فعال با دستور health_check (ارسال دورهای درخواست به یک مسیر مثل /healthz) فقط در NGINX Plus تجاری وجود دارد؛ در نسخهی متنباز میتوان سلامت را از بیرون (مثلاً با Kubernetes Probe) پایش کرد.
۵.۲. چسبندگی نشست (Session Affinity)
اگر اپلیکیشن وضعیت کاربر را در حافظهی همان سرور نگه میدارد، همهی درخواستهای یک کاربر باید به یک سرور برود. ip_hash سادهترین راه است، اما پشت IPهای مشترک (مثل اینترنت همراه) بار را نامتوازن میکند. از نسخهی 1.29.6 دستور sticky cookie که پیشتر مخصوص NGINX Plus بود، در نسخهی متنباز هم در دسترس است و در شاخهی stable 1.30 وجود دارد. بهترین راه اما نگهداشتن Session در Redis یا پایگاه داده است.
بخش ۶ از ۱۵
۶. آشنایی با Nginx
۶.۱. تاریخچه و وضعیت فعلی
Nginx (تلفظ: «اِنجین ایکس») را ایگور سیسویف، برنامهنویس روس، برای حل «مسئلهی C10K» یعنی مدیریت دهها هزار اتصال همزمان نوشت. اولین نسخهی عمومی آن (0.1.0) در ۴ اکتبر ۲۰۰۴ منتشر شد. شرکت NGINX Inc. در سال ۲۰۱۱ برای ارائهی پشتیبانی و نسخهی تجاری NGINX Plus تأسیس شد و در سال ۲۰۱۹ به مالکیت F5 درآمد. Nginx با مجوز BSD دوبندی منتشر میشود و کد منبع آن اکنون روی GitHub نگهداری میشود.
Nginx دو شاخهی انتشار دارد: mainline با شمارهی فرعی فرد که ویژگیهای جدید در آن عرضه میشود، و stable با شمارهی فرعی زوج که فقط اصلاحات مهم و امنیتی را دریافت میکند. شاخهی stable 1.30 در ۱۴ آوریل ۲۰۲۶ ایجاد شد و در زمان نگارش این مقاله آخرین نسخهها nginx 1.30.6 (stable) و nginx 1.31.7 (mainline) هستند که هر دو در ۱۴ اکتبر ۲۰۲۶ با رفع چند آسیبپذیری امنیتی منتشر شدند. مخازن پیشفرض توزیعهای لینوکس معمولاً نسخهی قدیمیتری دارند.
چند تغییر مهم یکی دو سال اخیر که در پیکربندیها اثر مستقیم دارند:
ACME داخلی: از اوت ۲۰۲۵ ماژول رسمی ngx_http_acme_module (بستهی nginx-module-acme) امکان دریافت و تمدید خودکار گواهی Let's Encrypt را بدون Certbot فراهم میکند.
Keepalive پیشفرض به Backend: از نسخهی 1.29.7 مقدار پیشفرض proxy_http_version برابر 1.1 است و کش اتصالهای keepalive در بلوک upstream بهصورت پیشفرض فعال است. در نسخههای قدیمیتر باید اینها را دستی تنظیم کرد.
وراثت هدرها: دستور add_header_inherit (از 1.29.3) مشکل قدیمی گمشدن هدرهای سطح بالاتر را قابلکنترل کرده است.
در شاخهی mainline: ماژول ngx_http_tunnel_module برای درخواستهای CONNECT (از 1.31.0) و در 1.31.5 قابلیتهایی مثل Control API، Predicate Locations و ماژول JSON اضافه شدهاند.
۶.۲. معماری رویدادمحور: Master و Worker
راز کارایی Nginx در معماری رویدادمحور و غیرمسدودکننده (Event-driven, Non-blocking) آن است. برخلاف مدل سنتی «یک پردازه یا نخ برای هر اتصال»، Nginx تعداد کمی پردازهی Worker دارد و هر Worker با یک حلقهی رویداد و سازوکارهای سیستمعامل مثل epoll در لینوکس یا kqueue در BSD، هزاران اتصال را همزمان مدیریت میکند. نتیجه، مصرف حافظهی کم و قابلپیشبینی زیر بار سنگین است.
پردازهی Master: با دسترسی root اجرا میشود، پیکربندی را میخواند، پورتها را باز میکند و Workerها را میسازد و مدیریت میکند. با سیگنال reload، پیکربندی جدید را بدون قطع اتصالهای فعلی بارگذاری میکند.
پردازههای Worker: با کاربر کمدسترسی (مثل nginx یا www-data) اجرا میشوند و همهی کار واقعی پردازش درخواستها را انجام میدهند. معمولاً worker_processes auto یعنی یک Worker به ازای هر هستهی CPU.
Cache Loader و Cache Manager: اگر کش فعال باشد، این دو پردازه فهرست کش را بارگذاری و حجم آن را در حد مجاز نگه میدارند.
۶.۳. مقایسه با Apache، HAProxy، Traefik، Caddy و Envoy
ابزار
زبان و معماری
نقطهی قوت
پیکربندی
TLS خودکار
کاربرد رایج
Nginx
C، رویدادمحور
وبسرور سریع، Reverse Proxy و کش همهکاره
فایل متنی اعلانی
با ماژول ACME یا Certbot
جلوی اپلیکیشنها، فایل استاتیک
Apache httpd
C، مدل MPM (prefork/worker/event)
ماژولهای فراوان، .htaccess
فایل متنی، پیکربندی در هر پوشه
با mod_md
میزبانی اشتراکی، PHP سنتی
HAProxy
C، رویدادمحور
Load Balancer تخصصی L4/L7، Health Check فعال، آمار دقیق
فایل متنی
پشتیبانی داخلی در نسخههای جدید
توزیع بار با کارایی بالا
Traefik
Go
کشف خودکار سرویس در Docker و Kubernetes
Label، CRD، فایل
داخلی
میکروسرویس و کانتینر
Caddy
Go
HTTPS خودکار بهصورت پیشفرض، پیکربندی بسیار ساده
Caddyfile یا JSON API
داخلی و پیشفرض
سایتهای کوچک و متوسط
Envoy
C++
پیکربندی پویا با xDS، قابلیت مشاهدهی قوی، gRPC
YAML و API
از طریق Control Plane
Service Mesh و API Gateway
بخش ۷ از ۱۵
۷. نصب Nginx روی Ubuntu و Docker
۷.۱. نصب از مخزن Ubuntu
سادهترین راه نصب، بستهی خود Ubuntu است. این بسته پایدار و یکپارچه با سیستم است، اما نسخهی آن معمولاً از آخرین نسخهی stable عقبتر است:
sudo apt update
sudo apt install nginx
nginx -v # show the installed version
sudo systemctl enable --now nginx
sudo ufw allow 'Nginx Full' # open ports 80 and 443 if UFW is enabled
۷.۲. نصب آخرین نسخه از مخزن رسمی nginx.org
برای دریافت آخرین نسخهی stable یا mainline، از مخزن رسمی استفاده کنید. دستورهای زیر از صفحهی Linux packages در nginx.org برگرفته شدهاند (Ubuntu 22.04، 24.04 و 26.04 پشتیبانی میشوند):
sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring
curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
# Stable branch (use .../packages/mainline/ubuntu for mainline)
echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
https://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
# Prefer nginx.org packages over the distribution ones
echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
| sudo tee /etc/apt/preferences.d/99nginx
sudo apt update
sudo apt install nginx
توجه کنید که بستهی nginx.org ساختار پوشهی متفاوتی دارد: بهجای sites-available و sites-enabled، فایلهای سایت در /etc/nginx/conf.d/*.conf قرار میگیرند و کاربر پردازهها nginx است، نه www-data.
۷.۳. اجرا با Docker
ایمیج رسمی nginx در Docker Hub برای هر دو شاخه برچسب دارد؛ مثلاً nginx:1.30.6-alpine یا nginx:stable-alpine برای stable و nginx:1.31.7 یا nginx:mainline برای mainline. در Production همیشه نسخهی مشخص را سنجاق کنید.
# Quick test: serve the default page on port 8080
docker run -d --name web -p 8080:80 nginx:1.30.6-alpine
# Validate a config file before using it
docker run --rm -v "$PWD/default.conf:/etc/nginx/conf.d/default.conf:ro" \
nginx:1.30.6-alpine nginx -t
# compose.yaml: Nginx in front of an app container
services:
app:
image: ghcr.io/example/app:1.4.2
expose:
- "3000" # reachable only inside the compose network
nginx:
image: nginx:1.30.6-alpine
depends_on: [app]
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
- ./certs:/etc/nginx/certs:ro
restart: unless-stopped
بخش ۸ از ۱۵
۸. ساختار فایلهای پیکربندی Nginx
۸.۱. فایل nginx.conf و Contextها
فایل اصلی معمولاً /etc/nginx/nginx.conf است. پیکربندی از دستورها (Directives) تشکیل میشود که با ; تمام میشوند و بلوکها (Contexts) که با آکولاد مشخص میشوند. هر دستور فقط در Contextهای مشخصی مجاز است و تنظیمات از بلوک بیرونی به درونی به ارث میرسند.
user nginx;
worker_processes auto; # main context
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
events {
worker_connections 4096; # per worker process
}
http { # HTTP traffic
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
server_tokens off; # hide the version number
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" rt=$request_time urt=$upstream_response_time';
access_log /var/log/nginx/access.log main;
upstream app { server 127.0.0.1:3000; } # backend group
server { # one virtual host
listen 80;
server_name example.com;
location / { # rules for a group of URIs
proxy_pass http://app;
}
}
include /etc/nginx/conf.d/*.conf; # more server blocks
}
# stream { ... } # optional raw TCP/UDP proxying
۸.۲. sites-available، sites-enabled و include
در بستهی Debian و Ubuntu، هر سایت یک فایل در /etc/nginx/sites-available/ دارد و با یک لینک نمادین در sites-enabled فعال میشود. دستور include هم برای تکههای مشترک (مثل تنظیمات TLS یا هدرهای پراکسی) به کار میرود تا تکرار کم شود.
Nginx ابتدا بر اساس IP و پورت و سپس هدر Host (مقایسه با server_name) بلوک server را انتخاب میکند. در غیر این صورت سرور default_server (یا اولین server) پاسخ میدهد. سپس داخل server، بلوک location با این ترتیب پیدا میشود:
اگر یک location = /path دقیقاً تطبیق کند، جستوجو همانجا تمام میشود.
در میان locationهای پیشوندی، طولانیترین پیشوند منطبق انتخاب و به خاطر سپرده میشود.
اگر آن پیشوند علامت ^~ داشته باشد، عبارتهای منظم بررسی نمیشوند و همان استفاده میشود.
در غیر این صورت عبارتهای منظم (~ حساس به حروف و ~* غیرحساس) به ترتیب ظاهر شدن در فایل بررسی میشوند و اولین تطبیق برنده است.
اگر هیچ عبارت منظمی تطبیق نکند، همان پیشوند به خاطر سپردهشده در گام ۲ استفاده میشود.
در شاخهی mainline (از 1.31.5) نوع جدیدی به نام Predicate Location با پیشوند $ اضافه شده که بر اساس مقدار یک متغیر تطبیق میکند و پس از عبارتهای منظم بررسی میشود؛ این قابلیت در stable 1.30 وجود ندارد.
بخش ۹ از ۱۵
۹. پیکربندیهای کاربردی Reverse Proxy
نمونهها برای Nginx 1.30 نوشته شدهاند. پس از هر تغییر nginx -t و سپس systemctl reload nginx را اجرا کنید.
۹.۱. Reverse Proxy پایه با هدرهای درست
وقتی Nginx درخواست را به Backend میفرستد، بهطور پیشفرض هدر Host را به نام upstream تغییر میدهد و اپلیکیشن نشانی واقعی کاربر را نمیبیند. چهار هدر زیر تقریباً همیشه لازماند:
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host; # original host name
proxy_set_header X-Real-IP $remote_addr; # client IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # proxy chain
proxy_set_header X-Forwarded-Proto $scheme; # http or https
proxy_set_header X-Forwarded-Host $host;
}
}
یک نکتهی ظریف در proxy_pass: اگر نشانی آن مسیر داشته باشد (حتی فقط /)، بخش منطبق با location از ابتدای URI حذف و با آن مسیر جایگزین میشود. مثلاً با location /api/ { proxy_pass http://app/; } درخواست /api/users به صورت /users به Backend میرسد، اما بدون اسلش پایانی همان /api/users ارسال میشود. همچنین به یاد داشته باشید که اگر در یک بلوک حتی یک proxy_set_header بنویسید، هدرهای تعریفشده در سطح بالاتر به ارث نمیرسند؛ بهتر است همه را در یک فایل جدا بگذارید و با include فراخوانی کنید:
upstream api_servers {
least_conn;
server 10.0.0.21:8080 max_fails=3 fail_timeout=15s;
server 10.0.0.22:8080 max_fails=3 fail_timeout=15s;
keepalive 64; # reuse connections to the backends
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://api_servers;
proxy_http_version 1.1; # default since 1.29.7; needed on older versions
proxy_set_header Connection ""; # keep upstream connections open (older versions)
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_next_upstream error timeout http_502 http_503; # try another server
proxy_next_upstream_tries 2;
}
}
دقت کنید که proxy_next_upstream فقط برای درخواستهای idempotent (مثل GET) بهطور پیشفرض تکرار میشود؛ درخواست POST بعد از ارسال به سرور دیگری فرستاده نمیشود مگر اینکه non_idempotent را اضافه کنید، که معمولاً کار درستی نیست.
۹.۳. SSL با Let's Encrypt و Certbot
Certbot طبق مستندات رسمی خودش ترجیحاً با snap نصب میشود. پیشنیاز آن این است که دامنه به سرور اشاره کند و پورت ۸۰ از اینترنت در دسترس باشد:
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/local/bin/certbot
sudo certbot --nginx -d example.com -d www.example.com # get + install
# or only obtain the certificate and edit nginx yourself:
sudo certbot certonly --nginx -d example.com -d www.example.com
sudo certbot renew --dry-run # test automatic renewal
اگر میخواهید پیکربندی را خودتان بنویسید، نمونهی زیر بر پایهی پروفایل Intermediate نسخهی 6.0 راهنمای Mozilla (ssl-config.mozilla.org) است: TLS 1.2 و 1.3، رمزهای AEAD با ECDHE، بدون ترجیح ترتیب رمز در سمت سرور و HSTS دوساله:
# Redirect all HTTP traffic to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on; # the "http2" listen parameter is deprecated
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
# Mozilla "intermediate" profile (guidelines v6.0)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1:secp384r1; # drop X25519MLKEM768 if OpenSSL < 3.5
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_prefer_server_ciphers off;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
# HSTS: only after HTTPS works everywhere on this domain
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://127.0.0.1:3000;
include /etc/nginx/snippets/proxy-headers.conf;
}
}
دو نکتهی بهروز: اول، Let's Encrypt از ۷ مه ۲۰۲۵ نشانی OCSP را از گواهیها حذف کرد و از ۶ اوت ۲۰۲۵ سرویس OCSP خود را خاموش کرد؛ بنابراین ssl_stapling برای گواهیهای Let's Encrypt دیگر اثری ندارد و فقط هشدار تولید میکند. دوم، HSTS را با احتیاط فعال کنید؛ مرورگرها تا پایان max-age فقط با HTTPS به دامنه وصل میشوند و افزودن includeSubDomains همهی زیردامنهها را هم شامل میشود.
جایگزین Certbot، ماژول ACME داخلی Nginx است. پس از نصب بستهی nginx-module-acme از مخزن nginx.org:
load_module modules/ngx_http_acme_module.so; # in the main context
http {
resolver 127.0.0.53; # required by the ACME module
acme_issuer letsencrypt {
uri https://acme-v02.api.letsencrypt.org/directory;
state_path /var/cache/nginx/acme-letsencrypt;
accept_terms_of_service;
}
server {
listen 80; # required for ACME HTTP-01 challenges
location / { return 404; } # as in the official example
}
server {
listen 443 ssl;
server_name example.com;
acme_certificate letsencrypt;
ssl_certificate $acme_certificate;
ssl_certificate_key $acme_certificate_key;
ssl_certificate_cache max=2; # do not parse the cert on every request
}
}
۹.۴. پراکسی WebSocket
WebSocket با یک درخواست HTTP/1.1 و هدرهای Upgrade و Connection شروع میشود. این هدرهای hop-by-hop باید صریحاً منتقل شوند. همچنین چون اتصال طولانی است، proxy_read_timeout (پیشفرض ۶۰ ثانیه) را بالا ببرید یا در اپلیکیشن پیام ping دورهای بفرستید:
# http context: 10 MB of keys (~80k entries), up to 2 GB on disk
proxy_cache_path /var/cache/nginx/app levels=1:2 keys_zone=app_cache:10m
max_size=2g inactive=60m use_temp_path=off;
server {
# ...
location / {
proxy_pass http://app;
proxy_cache app_cache;
proxy_cache_valid 200 301 10m; # cache good answers for 10 minutes
proxy_cache_valid 404 1m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on; # refresh in the background
proxy_cache_lock on; # one request fills a missing entry
proxy_cache_bypass $cookie_session $http_authorization; # never for logged-in users
proxy_no_cache $cookie_session $http_authorization;
add_header X-Cache-Status $upstream_cache_status always; # HIT, MISS, STALE...
}
}
Nginx بهطور پیشفرض به هدرهای Cache-Control و Set-Cookie Backend احترام میگذارد و پاسخهای دارای کوکی را کش نمیکند. صفحههای شخصی و پنل مدیریت هرگز نباید در کش مشترک ذخیره شوند.
۹.۶. فشردهسازی gzip
gzip on;
gzip_comp_level 5; # good balance between CPU and size
gzip_min_length 1024; # tiny responses are not worth it
gzip_proxied any; # also compress proxied responses
gzip_vary on; # add "Vary: Accept-Encoding"
gzip_types text/plain text/css application/javascript application/json
application/xml image/svg+xml; # text/html is always included
فایلهای از پیش فشرده (JPEG، PNG، WebP، ویدئو، ZIP) را در gzip_types قرار ندهید؛ فقط CPU مصرف میشود.
۹.۷. محدودیت نرخ درخواست با limit_req
# http context: 10 requests/second per client IP, 10 MB of state
limit_req_zone $binary_remote_addr zone=per_ip:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_ip:10m;
limit_req_status 429; # default is 503
server {
location /api/ {
limit_req zone=per_ip burst=20 nodelay; # allow short bursts
limit_conn conn_ip 20; # max parallel connections per IP
proxy_pass http://api_servers;
}
location = /login {
limit_req zone=per_ip burst=5; # stricter for brute-force targets
proxy_pass http://app;
}
}
اگر Nginx پشت یک CDN یا Load Balancer دیگر است، $binary_remote_addr نشانی آن لایه را نشان میدهد و همهی کاربران یک محدودیت مشترک خواهند داشت. در این حالت ابتدا با ماژول realip نشانی واقعی را بازیابی کنید:
set_real_ip_from 10.0.0.0/8; # trust only your own load balancers / CDN ranges
real_ip_header X-Forwarded-For;
real_ip_recursive on;
۹.۸. زمانهای انتظار، بافرها و حجم آپلود
client_max_body_size 20m; # default is 1m -> "413 Request Entity Too Large"
client_body_timeout 15s;
client_header_timeout 15s;
keepalive_timeout 65s;
proxy_connect_timeout 5s; # backend should accept quickly (default 60s)
proxy_send_timeout 60s;
proxy_read_timeout 60s; # raise for slow reports or long polling
proxy_buffering on; # default; frees the backend quickly
proxy_buffer_size 16k; # first part of the response (headers)
proxy_buffers 8 16k;
برای Server-Sent Events یا پاسخهای جریانی (Streaming) بافر را خاموش کنید (proxy_buffering off) یا از Backend هدر X-Accel-Buffering: no را بفرستید.
تفاوت root و alias مهم است: با root مسیر location به انتهای پوشه افزوده میشود، اما alias آن بخش را جایگزین میکند. در alias اسلش پایانی دو طرف را یکسان نگه دارید.
دستور add_header یک دام قدیمی دارد: اگر در یک location حتی یک add_header بنویسید، همهی هدرهای سطح server به ارث نمیرسند. راه کلاسیک، فراخوانی همان فایل با include در هر جایی است که add_header دارد. از نسخهی 1.29.3 میتوانید با add_header_inherit merge; بگویید هدرهای سطح بالاتر هم اضافه شوند. CSP را ابتدا با Content-Security-Policy-Report-Only آزمایش کنید.
بخش ۱۰ از ۱۵
۱۰. Nginx بهعنوان Forward Proxy؟
Nginx برای نقش Reverse Proxy طراحی شده است. نسخهی stable آن (1.30) متد CONNECT را پشتیبانی نمیکند، پس نمیتواند پراکسی فوروارد کامل برای HTTPS باشد. میشود با proxy_pass http://$http_host$request_uri و یک resolver یک پراکسی فوروارد ساده فقط برای HTTP ساخت، اما این روش امکانات یک پراکسی واقعی را ندارد و اگر بیدقت باز بماند به «Open Proxy» قابلسوءاستفاده تبدیل میشود.
وضعیت در شاخهی mainline در حال تغییر است: از نسخهی 1.31.0 ماژول ngx_http_tunnel_module درخواستهای HTTP/1.1 CONNECT را میپذیرد و تونل برقرار میکند و احراز هویت پراکسی هم به auth_basic اضافه شده است. این ماژول هنوز در هیچ شاخهی stable نیست. برای پراکسی فوروارد سازمانی، ابزار استاندارد همچنان Squid است:
# /etc/squid/squid.conf (minimal forward proxy for an internal network)
http_port 3128
acl localnet src 10.0.0.0/8 192.168.0.0/16
acl SSL_ports port 443
acl Safe_ports port 80 443
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localnet
http_access deny all # never run an open proxy
cache_dir ufs /var/spool/squid 2000 16 256
اگر فقط باید ترافیک TLS را بدون رمزگشایی و بر اساس نام دامنه به سرورهای مختلف هدایت کنید، ماژول stream در Nginx با ssl_preread on میتواند از روی SNI تصمیم بگیرد؛ این همان کاری است که بسیاری از Load Balancerهای لایهی ۴ انجام میدهند.
بخش ۱۱ از ۱۵
۱۱. عیبیابی رایج
پیش از هر کاری، این ابزارها را بشناسید:
sudo nginx -t # syntax check of the whole configuration
sudo nginx -T | less # print the full merged configuration
sudo systemctl status nginx
sudo journalctl -u nginx --since "10 min ago"
sudo tail -f /var/log/nginx/error.log /var/log/nginx/access.log
ss -tlnp | grep -E ':80|:443|:3000' # who is listening on which port?
curl -I -H "Host: app.example.com" http://127.0.0.1/ # test a vhost locally
curl -v http://127.0.0.1:3000/health # talk to the backend directly
openssl s_client -connect example.com:443 -servername example.com </dev/null
خطا
معنی
علتهای رایج و راهحل
502 Bad Gateway
Backend پاسخ معتبری نداد
اپلیکیشن خاموش است یا روی پورت دیگری گوش میدهد؛ مسیر یا دسترسی سوکت یونیکس اشتباه است؛ در CentOS و RHEL، SELinux اتصال را بسته است (setsebool -P httpd_can_network_connect 1).
504 Gateway Timeout
Backend در زمان مقرر پاسخ نداد
کوئری یا پردازش کند؛ proxy_read_timeout را متناسب کنید، اما علت کندی را هم پیدا کنید.
413 Request Entity Too Large
بدنهی درخواست بزرگتر از حد مجاز
مقدار client_max_body_size را افزایش دهید.
499 (فقط در لاگ)
کلاینت پیش از پاسخ اتصال را بست
معمولاً Backend کند است یا کاربر صفحه را بسته است.
حلقهی ریدایرکت
ریدایرکت بیپایان HTTP و HTTPS
اپلیکیشن X-Forwarded-Proto را نمیخواند، یا CDN با HTTP به سرور وصل میشود.
IP همهی کاربران یکی است
IP پراکسی بهجای کاربر ثبت میشود
هدرهای X-Forwarded-For و X-Real-IP را بفرستید و ماژول realip را تنظیم کنید.
upstream sent too big header
هدر پاسخ از بافر بزرگتر است
proxy_buffer_size و proxy_buffers را بزرگتر کنید.
در error.log، پیامهایی مثل connect() failed (111: Connection refused) while connecting to upstream یعنی چیزی روی آن پورت گوش نمیدهد و upstream timed out (110) یعنی Backend کند است.
بخش ۱۲ از ۱۵
۱۲. بهترین روشهای کارایی و امنیت
۱۲.۱. کارایی
worker_processes auto و مقدار کافی برای worker_connections و worker_rlimit_nofile تنظیم کنید.
اتصالهای keepalive به Backend را فعال نگه دارید تا برای هر درخواست اتصال TCP و TLS جدیدی ساخته نشود.
HTTP/2 را برای کاربران فعال کنید؛ HTTP/3 هم در Nginx پشتیبانی میشود، اما به باز کردن UDP 443 و آزمایش دقیق نیاز دارد.
فایلهای استاتیک را مستقیماً از Nginx با sendfile و هدرهای کش طولانیمدت ارائه کنید.
کش را برای صفحههای عمومی و پرتکرار فعال کنید و با X-Cache-Status نرخ HIT را بسنجید.
۱۲.۲. امنیت
Nginx را از مخزن رسمی و بهروز نگه دارید؛ در همین سال ۲۰۲۶ چند آسیبپذیری مهم در ماژولهای مختلف رفع شده است.
server_tokens off را فعال کنید و فقط پورتهای ۸۰ و ۴۴۳ را باز بگذارید؛ Backendها فقط روی شبکهی داخلی یا 127.0.0.1 گوش دهند.
یک default_server بسازید که درخواستهای با نام ناشناخته را با return 444 ببندد تا اسکنرها به سایت اصلی نرسند.
برای مسیرهای حساس مثل ورود و API محدودیت نرخ بگذارید و پنلهای مدیریتی را با allow/deny یا احراز هویت جداگانه محافظت کنید.
فایلهای مخفی و پشتیبان (.git، .env، *.bak) را مسدود کنید و فهرست پوشهها (autoindex) را خاموش نگه دارید.
به هدرهای X-Forwarded-* فقط از پراکسیهای قابلاعتماد اعتماد کنید؛ وگرنه مهاجم میتواند IP جعلی بفرستد.
بخش ۱۳ از ۱۵
۱۳. واژهنامه
اصطلاح
توضیح
Proxy
سرور واسطی که درخواستها را از طرف کلاینت یا سرور جابهجا میکند.
Forward Proxy
پراکسی در سمت کاربران که از طرف آنها به اینترنت وصل میشود.
Reverse Proxy
پراکسی در سمت سرور که از طرف سرورهای پشتی پاسخ میدهد.
TLS Termination
رمزگشایی HTTPS در پراکسی بهجای اپلیکیشن.
SNI
بخشی از دستدهی TLS که نام دامنهی مقصد را پیش از رمزنگاری اعلام میکند.
HSTS
هدری که به مرورگر میگوید فقط با HTTPS به دامنه وصل شود.
ACME
پروتکل خودکار دریافت و تمدید گواهی که Let's Encrypt از آن استفاده میکند.
CONNECT
متد HTTP برای ساختن تونل TCP از طریق پراکسی، معمولاً برای HTTPS.
SOCKS5
پروتکل پراکسی عمومی برای TCP و UDP با پشتیبانی از احراز هویت.
Health Check
بررسی سلامت سرورهای پشتی برای کنار گذاشتن سرور معیوب.
WAF
فایروال برنامهی وب که حملاتی مثل SQL Injection و XSS را فیلتر میکند.
بخش ۱۴ از ۱۵
۱۴. جمعبندی
پراکسیها در سه نقش اصلی ظاهر میشوند: پراکسی فوروارد نمایندهی کاربران است، پراکسی معکوس نمایندهی سرورهاست و پراکسی شفاف بیآنکه کاربر متوجه شود در مسیر شبکه مینشیند. در معماری وب امروز، پراکسی معکوس کارهای مهمی را یکجا انجام میدهد: توزیع بار، خاتمهی TLS، کش و محافظت از سرورهای پشتی.
Nginx با معماری رویدادمحور، مصرف منابع کم و پیکربندی خوانا هنوز یکی از بهترین انتخابها برای این نقش است. برای شروع، Nginx را از مخزن رسمی نصب کنید، یک Reverse Proxy ساده با هدرهای درست بسازید، HTTPS را با Let's Encrypt فعال کنید و سپس کش، محدودیت نرخ و هدرهای امنیتی را یکییکی اضافه کنید.
راهنمای جامع و کاربردی مدیریت secret ها با HashiCorp Vault: تاریخچه، تغییر مجوز به BSL، OpenBao و خرید HashiCorp توسط IBM، مفاهیم Seal/Unseal و Raft، توکن و Policy، AppRole و Kubernetes، رازهای پویا، PKI و Transit، راهاندازی با Docker Compose و TLS، اتصال Spring Boot و چکلیست Production.
راهنمای کامل و کاربردی WSO2: آشنایی با شرکت و محصولاتش، معماری API Manager نسخهی 4.7، نصب با Docker و Docker Compose، پیکربندی deployment.toml، راهاندازی SSL با Let's Encrypt و Nginx، نکات استقرار Production و مقایسه با رقبا.
آموزش شبکه کردن CALL OF DUTY 4:MODERN WARFARE 1 برای شبکه کردن این بازی شما نیاز به یک سری پچ ها و تنظیمات دارید که باید مرحله به مرحله انجام بشه مرحله اول مثل همیشه نصب یک نسخه…
نظرها هنوز نظری ثبت نشده
برای ثبت نظر، صفحه را در مرورگر باز کنید.