عنوان:

‫چالش‌های متداول توسعه‌دهندگان ASP.NET Core هنگام استفاده از Nginx - قسمت سوم - پیکربندی Nginx به عنوان Reverse Proxy


نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۴/۰۹ ۰۸:۱۰
آدرس: www.dntips.ir
در قسمت قبل، ما یک سرویس پایدار و خودکار برای برنامه ASP.NET Core خود ساختیم. اکنون برنامه ما در پس‌زمینه به خوبی اجرا می‌شود، اما هنوز یک قطعه مهم از پازل باقی مانده است: پل ارتباطی بین دنیای بیرون و برنامه ما. Nginx این پل است. در این ثسمت، از یک کانفیگ ساده فراتر رفته و یاد می‌گیریم چگونه Nginx را به عنوان یک Reverse Proxy هوشمند پیکربندی کنیم. هدف این است که Nginx نه تنها ترافیک را به برنامه ما منتقل کند، بلکه اطلاعات زمینه‌ای (Context) لازم را نیز به آن برساند تا برنامه ما دقیقاً بداند با چه کسی و چگونه صحبت می‌کند. این فصل پر از نکات کلیدی است که جلوی بسیاری از خطاهای پنهان در آینده را می‌گیرد.

بخش ۱: ساختار فایل پیکربندی Nginx
بهترین روش برای مدیریت سایت‌ها در Nginx، ایجاد یک فایل کانفیگ جداگانه برای هر سایت است. این کار باعث نظم و سهولت در مدیریت می‌شود.
محل فایل‌ها:
  • /etc/nginx/sites-available/: تمام کانفیگ‌های سایت شما در این پوشه قرار می‌گیرند (چه فعال باشند چه غیرفعال).
  • /etc/nginx/sites-enabled/: برای فعال کردن یک سایت، یک لینک نمادین (Symbolic Link) از فایل کانفیگ آن در sites-available به این پوشه ایجاد می‌کنیم.

ایجاد فایل کانفیگ برای سایت:
بیایید فایل کانفیگ را برای MyWebApp ایجاد کنیم:
sudo nano /etc/nginx/sites-available/kestrel-mywebapp

بخش ۲: قالب کامل پیکربندی و تحلیل آن
محتوای زیر را در فایلی که ایجاد کردید کپی کنید. این یک "قالب طلایی" است که اکثر نیازهای یک برنامه استاندارد ASP.NET Core را پوشش می‌دهد. سپس خط به خط آن را تشریح خواهیم کرد.
server {
    # به درخواست‌های HTTP روی پورت 80 گوش بده
    listen 80;
    listen [::]:80;

    # دامنه‌هایی که این کانفیگ برای آن‌ها اعمال می‌شود
    server_name your-domain.com www.your-domain.com;

    # بلاک اصلی برای Reverse Proxy
    location / {
        # آدرس سرویس ASP.NET Core ما
        proxy_pass         http://localhost:5000;
        
        # --- هدرهای ضروری برای حفظ اطلاعات کلاینت ---
        # ارسال هدر هاست اصلی به برنامه
        proxy_set_header   Host $host;
        # ارسال IP واقعی کلاینت به برنامه
        proxy_set_header   X-Real-IP $remote_addr;
        # ارسال لیست IP های پراکسی‌های مسیر (برای شناسایی IP اصلی)
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        # ارسال پروتکل اصلی (http یا https) به برنامه
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

بخش ۳: مشکل‌یابی و اهمیت هدرهای proxy_set_header
بخش proxy_set_header حیاتی‌ترین قسمت این کانفیگ است. بدون آن، برنامه شما اطلاعات اشتباهی دریافت می‌کند.

مشکل شماره ۱: برنامه من IP همه کاربران را 127.0.0.1 (یا ::1) نشان می‌دهد!
  • علامت: در لاگ‌های برنامه، تمام درخواست‌ها از طرف localhost ثبت می‌شوند. ویژگی‌هایی مانند محدود کردن درخواست بر اساس IP یا نمایش موقعیت جغرافیایی کاربر کار نمی‌کنند.
  • علت: از دید Kestrel، تمام درخواست‌ها مستقیماً از Nginx (که روی همان سرور است) می‌آیند.
  • راه‌حل: هدرهای X-Real-IP و X-Forwarded-Forproxy_set_header X-Real-IP $remote_addr;: این هدر، IP اصلی کاربر را در خود نگه می‌دارد.
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;: این هدر یک لیست از IPهایی است که درخواست از آن‌ها عبور کرده. فریم‌ورک ASP.NET Core به صورت خودکار از این هدر برای تشخیص IP واقعی کلاینت استفاده می‌کند.

مشکل شماره ۲: ریدایرکت HTTPS به درستی کار نمی‌کند یا لینک‌ها با http:// تولید می‌شوند.
  • علامت: در برنامه از app.UseHttpsRedirection() استفاده کرده‌اید، اما یا کاربر در یک حلقه ریدایرکت بی‌پایان گیر می‌کند، یا لینک‌های تولید شده در صفحه (مثلاً در تگ‌های ) با http شروع می‌شوند و باعث خطای Mixed-Content در مرورگر می‌شوند.
  • علت: ارتباط بین Nginx و Kestrel روی پروتکل HTTP (ناامن) انجام می‌شود. بنابراین، برنامه شما فکر می‌کند که درخواست اصلی نیز HTTP بوده است.
  • راه‌حل: هدر X-Forwarded-Protoproxy_set_header X-Forwarded-Proto $scheme;: این هدر به برنامه اطلاع می‌دهد که پروتکل اصلی که کاربر استفاده کرده چه بوده است (http یا https که توسط متغیر $scheme در Nginx مشخص می‌شود). میدل‌ور ASP.NET Core با دیدن https در این هدر، متوجه می‌شود که ارتباط امن است و رفتار درستی از خود نشان می‌دهد.

مشکل شماره ۳: آپلود فایل‌های حجیم با خطای 413 Request Entity Too Large مواجه می‌شود.
  • علامت: کاربر هنگام آپلود یک فایل نسبتاً بزرگ، با یک صفحه خطای سفید از طرف Nginx مواجه می‌شود.
  • علت: Nginx به صورت پیش‌فرض یک محدودیت بسیار پایین (معمولاً 1 مگابایت) برای حجم بدنه درخواست (Request Body) دارد.
  • راه‌حل: افزایش client_max_body_size این دستور را باید در بلاک server (خارج از location) اضافه کنید.
server {
    listen 80;
    server_name your-domain.com;

    # اجازه آپلود فایل تا حجم ۱۰۰ مگابایت
    client_max_body_size 100M;

    location / {
        # ... بقیه تنظیمات پراکسی
    }
}

بخش ۴: بهینه‌سازی: سرویس‌دهی فایل‌های استاتیک توسط Nginx
برنامه ASP.NET Core شما می‌تواند فایل‌های استاتیک (CSS, JS, تصاویر و...) را از پوشه wwwroot سرویس‌دهی کند، اما Nginx این کار را بسیار بهینه‌تر و سریع‌تر انجام می‌دهد. با این کار، بار از روی دوش Kestrel برداشته می‌شود.
برای این کار، یک بلاک location جدید به کانفیگ خود اضافه می‌کنیم:
server {
    # ... تنظیمات قبلی
    server_name your-domain.com;
    client_max_body_size 100M;

    # این بلاک برای فایل‌های استاتیک است
    location / {
        # ... تنظیمات پراکسی برای Kestrel
    }

    # این بلاک جدید، درخواست برای فایل‌های استاتیک را می‌گیرد
    location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg)$ {
        # مسیر پوشه wwwroot برنامه شما
        root /var/www/mywebapp/wwwroot;
        
        # تنظیم هدرهای کش در مرورگر کاربر (مثلا ۷ روز)
        expires 7d;
    }
}
نکته: ترتیب بلاک‌های location مهم نیست. Nginx به صورت هوشمند بر اساس تطابق با آدرس درخواست، بلاک مناسب را انتخاب می‌کند.

بخش ۵: فعال‌سازی نهایی کانفیگ
ایجاد لینک نمادین برای فعال‌سازی سایت:
sudo ln -s /etc/nginx/sites-available/kestrel-mywebapp /etc/nginx/sites-enabled/

تست پیکربندی Nginx: قبل از اعمال تغییرات، همیشه کانفیگ را تست کنید تا خطای تایپی نداشته باشید.
sudo nginx -t
  • اگر خروجی syntax is ok و test is successful را دیدید، همه چیز مرتب است.

اعمال تغییرات: از دستور reload استفاده کنید تا Nginx بدون هیچ‌گونه قطعی (Downtime)، کانفیگ جدید را بارگذاری کند.
sudo systemctl reload nginx

جمع‌بندی فصل ۳:
شما با موفقیت Nginx را به عنوان یک Reverse Proxy هوشمند و بهینه پیکربندی کردید. اکنون نه تنها ترافیک به درستی به برنامه شما هدایت می‌شود، بلکه برنامه شما اطلاعات کاملی از کلاینت دریافت می‌کند، فایل‌های حجیم قابل آپلود هستند و فایل‌های استاتیک با بالاترین سرعت ممکن سرو می‌شوند.
تنها یک مشکل باقی مانده است: ارتباط بین کاربر و سایت شما هنوز روی پروتکل ناامن HTTP است. در قسمت بعدی، این مشکل را با فعال‌سازی SSL/TLS حل کرده و سایت خود را با HTTPS امن خواهیم کرد.