عنوان:

‫NGINX برای توسعه‌دهندگان ASP.NET Core - قسمت سوم - پیکربندی‌های ضروری


نویسنده: وحید نصیری
تاریخ: ۱۴۰۴/۰۳/۲۹ ۰۸:۱۰
آدرس: www.dntips.ir
این بخش بر روی تبدیل راه‌اندازی اولیه به یک ساختار حرفه‌ای، امن و استاندارد برای محیط Production تمرکز دارد.

بخش ۳: پیکربندی‌های ضروری برای محیط Production
تا اینجا شما با موفقیت یک اپلیکیشن ASP.NET Core را پشت NGINX راه‌اندازی کردید. حالا وقت آن است که این راه‌اندازی را برای دنیای واقعی آماده کنیم. در این بخش، سه قابلیت کلیدی را پیاده‌سازی می‌کنیم: فعال‌سازی HTTPS، بهینه‌سازی تحویل فایل‌های استاتیک و میزبانی چند اپلیکیشن روی یک سرور.

۱. فعال‌سازی HTTPS با SSL/TLS (و استفاده از Let's Encrypt)
در وب امروز، HTTPS دیگر یک گزینه نیست، بلکه یک ضرورت است. HTTPS با رمزنگاری ترافیک بین کاربر و سرور، امنیت و حریم خصوصی را تضمین می‌کند و حتی روی رتبه سایت شما در گوگل نیز تأثیر مثبت دارد.
خوشبختانه، به لطف پروژه‌ای به نام Let's Encrypt، دریافت و نصب گواهینامه SSL/TLS کاملاً رایگان و خودکار شده است. ما از ابزاری به نام certbot برای این کار استفاده می‌کنیم.

پیش‌نیاز: برای این مرحله، شما باید یک نام دامنه (Domain) داشته باشید که به IP سرور شما اشاره می‌کند. Let's Encrypt برای سرورهایی که فقط IP دارند، گواهینامه صادر نمی‌کند.

مراحل نصب و راه‌اندازی:
۱. نصب Certbot و پلاگین NGINX:
certbot ابزاری است که فرآیند دریافت و نصب گواهینامه را به صورت خودکار انجام می‌دهد.
sudo apt update
sudo apt install certbot python3-certbot-nginx

۲. دریافت و نصب گواهینامه:
در ادامه این دستور مهم را اجرا کنید. فراموش نکنید که your-domain.com را با نام دامنه واقعی خود جایگزین کنید.
sudo certbot --nginx -d your-domain.com
certbot از شما چند سؤال می‌پرسد:
  • آدرس ایمیل شما: برای دریافت اطلاعیه‌های مهم (مثلاً در مورد انقضای گواهینامه).
  • پذیرش قوانین: با تایپ A موافقت خود را اعلام کنید.
  • ریدایرکت HTTP به HTTPS: از شما پرسیده می‌شود که آیا می‌خواهید تمام ترافیک HTTP به صورت خودکار به HTTPS منتقل شود. گزینه 2 (Redirect) را انتخاب کنید. این کار شدیداً توصیه می‌شود.

certbot به صورت خودکار فایل کانفیگ NGINX شما (my-aspnet-app.conf) را پیدا کرده، گواهینامه را دریافت می‌کند و تنظیمات لازم برای فعال‌سازی HTTPS را به آن اضافه می‌کند.

۳. بررسی تنظیمات جدید:
اگر فایل /etc/nginx/sites-available/my-aspnet-app.conf را باز کنید، می‌بینید که certbot تغییراتی در آن ایجاد کرده است:
  • یک بلوک server برای گوش دادن روی پورت 443 ssl.
  • مسیر فایل‌های گواهینامه (ssl_certificate و ssl_certificate_key).
  • یک بلوک server جدید که تمام ترافیک پورت 80 را به آدرس https:// ریدایرکت می‌کند.

۴. تأیید تمدید خودکار:
گواهینامه‌های Let's Encrypt به مدت ۹۰ روز اعتبار دارند. certbot به صورت خودکار یک سرویس زمان‌بندی (timer) ایجاد می‌کند که دو بار در روز برای تمدید گواهینامه‌های نزدیک به انقضا تلاش می‌کند. برای تست کردن فرآیند تمدید (بدون تمدید واقعی) می‌توانید از دستور زیر استفاده کنید:
sudo certbot renew --dry-run
اگر خطایی مشاهده نکردید، یعنی همه چیز برای تمدید خودکار آماده است.

۲. سرویس‌دهی بهینه‌ی فایل‌های استاتیک (Static Files)
اپلیکیشن ASP.NET Core شما از فایل‌های استاتیک مانند CSS, JavaScript و تصاویر استفاده می‌کند که معمولاً در پوشه wwwroot قرار دارند. تحویل دادن این فایل‌ها توسط NGINX بسیار بهینه‌تر و سریع‌تر از ارسال درخواست آن‌ها به Kestrel است. با این کار، بار کاری از روی دوش اپلیکیشن شما برداشته می‌شود.

روش پیاده‌سازی:
ما فایل کانفیگ NGINX را طوری تغییر می‌دهیم که ابتدا وجود یک فایل استاتیک را بررسی کند. اگر فایل وجود داشت، آن را مستقیماً تحویل دهد و در غیر این صورت، درخواست را به اپلیکیشن ASP.NET Core ارسال کند.
فایل کانفیگ سایت خود را ویرایش کنید:
sudo nano /etc/nginx/sites-available/my-aspnet-app.conf
بلوک server خود را به شکل زیر تغییر دهید:
server {
    listen 443 ssl; # یا 80 اگر هنوز HTTPS را فعال نکرده‌اید
    server_name your-domain.com;
    
    # ... تنظیمات ssl که توسط certbot اضافه شده ...

    # مسیر اصلی فایل‌های استاتیک شما
    root /var/www/my-aspnet-app/wwwroot;

    location / {
        # ابتدا تلاش کن فایل استاتیک را پیدا کنی. اگر نبود، درخواست را به پراکسی بفرست
        try_files $uri @proxy;
    }

    location @proxy {
        proxy_pass         http://localhost:5000;
        # تمام خطوط proxy_set_header را به اینجا منتقل کنید
        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;
    }
}
توضیح منطق جدید:
  • root /var/www/my-aspnet-app/wwwroot;: مسیر پیش‌فرض برای پیدا کردن فایل‌ها را مشخص می‌کند.
  • try_files $uri @proxy;: این دستور کلیدی به NGINX می‌گوید:
  • ابتدا سعی کن فایلی با نام دقیق درخواست ($uri) را در مسیر root پیدا کنی.
  • اگر پیدا کردی، آن را به کاربر برگردان و کار را تمام کن.
  • اگر پیدا نکردی (یعنی این یک درخواست داینامیک است، مثل /api/products)، درخواست را به location نام‌گذاری شده @proxy ارسال کن.
  • location @proxy { ... }: این یک بلوک ویژه است که فقط توسط try_files فراخوانی می‌شود و تمام تنظیمات Reverse Proxy ما اکنون در آن قرار دارد.

فراموش نکنید که بعد از ذخیره فایل، کانفیگ را تست و NGINX را reload کنید:
sudo nginx -t && sudo systemctl reload nginx

۳. میزبانی چند اپلیکیشن روی یک سرور (Server Blocks)
یکی از بزرگ‌ترین مزایای NGINX، قابلیت میزبانی چندین سایت یا سرویس روی یک سرور و یک IP است. این کار با استفاده از بلوک‌های server مجزا (که به آن‌ها Virtual Host هم گفته می‌شود) انجام می‌شود. NGINX با خواندن هدر Host درخواست، تشخیص می‌دهد که آن را به کدام بلوک server ارسال کند.
مراحل کار:
فرض کنید می‌خواهیم یک اپلیکیشن دوم به نام my-second-app را روی همین سرور میزبانی کنیم.
اپلیکیشن دوم را مستقر کنید:
  • آن را در مسیری مجزا مانند /var/www/my-second-app قرار دهید.
  • برای آن یک سرویس systemd جدید بسازید (مثلاً kestrel-my-second-app.service) که روی یک پورت متفاوت اجرا شود (مثلاً http://localhost:5001).
  • یک فایل کانفیگ NGINX جدید بسازید: sudo nano /etc/nginx/sites-available/my-second-app.conf
پیکربندی سایت دوم:
  • محتوای فایل کانفیگ تقریباً مشابه سایت اول است، اما با دو تفاوت کلیدی: server_name و پورت proxy_pass.
server {
    listen 80;
    server_name my-second-app.com; # دامنه دوم

    location / {
        proxy_pass http://localhost:5001; # اشاره به پورت اپلیکیشن دوم

        # سایر تنظیمات proxy_set_header ...
        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;
    }
}

فعال‌سازی سایت دوم:
sudo ln -s /etc/nginx/sites-available/my-second-app.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

فعال‌سازی HTTPS برای سایت دوم (اختیاری):
می‌توانید دقیقاً مانند سایت اول، دستور sudo certbot --nginx -d my-second-app.com را برای دامنه دوم نیز اجرا کنید تا امن شود.
اکنون، NGINX به صورت هوشمند درخواست‌های your-domain.com را به اپلیکیشن اول (روی پورت 5000) و درخواست‌های my-second-app.com را به اپلیکیشن دوم (روی پورت 5001) هدایت می‌کند.

با تکمیل این بخش، شما مهارت‌های لازم برای راه‌اندازی یک یا چند وب‌سایت به شکلی کاملاً استاندارد، امن و بهینه را کسب کرده‌اید. در بخش‌های بعدی، به سراغ بهینه‌سازی عملکرد و مباحث امنیتی پیشرفته‌تر خواهیم رفت.

نظرات

  • وحید نصیری در ۱۴۰۴/۰۳/۳۱ ۰۷:۵۰
    یک نکته‌ی تکمیلی: روش دیباگ معتبر بودن تنظیمات SSL/TLS

    گاهی ... ممکن است که گواهی‌نامه‌های SSL شما منقضی شده باشند. گواهی‌نامه‌های Let's Encrypt دارای اعتبار ۹۰ روزه هستند و باید به صورت دوره‌ای تمدید شوند. ابزار Certbot که در این مطلب به آن اشاره شد، طراحی شده تا این فرآیند تمدید را به صورت خودکار انجام دهد. اما گاهی ممکن است این فرآیند خودکار به دلایلی (مانند تغییرات در تنظیمات سرور، مشکلات شبکه یا فایروال) با شکست مواجه شود.
    در سرور اوبونتو، شما چندین راه برای بررسی تاریخ انقضای گواهی‌نامه SSL دارید.

    راه ۱: استفاده از خود Certbot (روش پیشنهادی)
    این بهترین و ساده‌ترین روش است، زیرا مستقیماً از ابزاری استفاده می‌کند که گواهی‌نامه‌ها را مدیریت می‌کند.
    دستور زیر را در ترمینال سرور خود وارد کنید:
    sudo certbot certificates
    این دستور لیستی از تمام گواهی‌نامه‌هایی که توسط Certbot مدیریت می‌شوند را به همراه اطلاعات کلیدی نمایش می‌دهد. خروجی چیزی شبیه به این خواهد بود:
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Found the following certs:
      Certificate Name: dntips.ir
        Serial Number: 4a1b2c3d...
        Key Type: ECDSA
        Domains: dntips.ir www.dntips.ir
        Expiry Date: 2025-09-10 08:30:15+00:00 (VALID: 89 days)
        Certificate Path: /etc/letsencrypt/live/dntips.ir/fullchain.pem
        Private Key Path: /etc/letsencrypt/live/dntips.ir/privkey.pem
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    در این خروجی، به بخش Expiry Date توجه کنید. این بخش تاریخ دقیق انقضا و تعداد روزهای باقی‌مانده از اعتبار گواهی را به شما نشان می‌دهد.

    راه ۲: استفاده از OpenSSL (روش فنی و دقیق)
    شما می‌توانید مستقیماً فایل گواهی‌نامه را با استفاده از ابزار openssl بررسی کنید. این روش تاریخ شروع و پایان اعتبار را به شما نشان می‌دهد.
    دستور زیر را برای بررسی فایل fullchain.pem اجرا کنید:
    sudo openssl x509 -in /etc/letsencrypt/live/dntips.ir/fullchain.pem -noout -dates
    تفکیک دستور:
    • sudo: برای دسترسی به فایل‌هایی که در پوشه محافظت شده letsencrypt قرار دارند.
    • openssl x509: ابزاری برای کار با گواهی‌نامه‌های استاندارد X.509.
    • -in ...: مسیر فایل گواهی‌نامه شما.
    • -noout: از چاپ محتوای کدگذاری شده گواهی جلوگیری می‌کند.
    • -dates: فقط تاریخ شروع (notBefore) و تاریخ انقضا (notAfter) را نمایش می‌دهد.
    خروجی این دستور به شکل زیر خواهد بود:
    notBefore=Jun 12 08:30:16 2025 GMT
    notAfter=Sep 10 08:30:15 2025 GMT
    notAfter همان تاریخ انقضای گواهی شماست.

    راه ۳: استفاده از یک ابزار آنلاین (روش سریع و خارجی)
    شما می‌توانید بدون نیاز به دسترسی به سرور، از یک وب‌سایت بررسی‌کننده SSL استفاده کنید. این روش همچنین تأیید می‌کند که Nginx در حال ارائه صحیح گواهی‌نامه به کاربران است.
    • به یک وب‌سایت مانند SSL Labs Server Test (https://www.ssllabs.com/ssltest/) بروید.
    • نام دامنه خود (dntips.ir) را وارد کرده و روی "Submit" کلیک کنید.
    پس از چند دقیقه تحلیل، این سایت یک گزارش کامل از وضعیت SSL/TLS سرور شما، شامل تاریخ انقضا، زنجیره گواهی (Certificate Chain) و مشکلات احتمالی دیگر ارائه می‌دهد.

    چگونه فرآیند تمدید خودکار را بررسی کنیم؟
    Certbot معمولاً یک تایمر systemd یا یک cron job برای اجرای خودکار فرآیند تمدید ایجاد می‌کند.

    ۱. بررسی تایمر Systemd (در اوبونتو ۱۶.۰۴ و جدیدتر):
    sudo systemctl list-timers | grep certbot
    خروجی باید تایمر فعال certbot.timer را نشان دهد.

    ۲. تست فرآیند تمدید:
    شما می‌توانید فرآیند تمدید را بدون ایجاد تغییر واقعی شبیه‌سازی کنید تا از صحت عملکرد آن مطمئن شوید:
    sudo certbot renew --dry-run
    اگر این دستور با موفقیت به پایان رسید، یعنی فرآیند تمدید خودکار شما به درستی کار می‌کند. اگر با خطا مواجه شدید، خروجی به شما در پیدا کردن علت مشکل کمک خواهد کرد.

    اگر گواهی منقضی شده بود چه کار کنیم؟
    کافیست دستور تمدید را به صورت دستی اجرا کنید:
    sudo certbot renew
    پس از تمدید موفقیت‌آمیز، Nginx باید مجدداً بارگذاری شود تا از گواهی جدید استفاده کند. Certbot معمولاً این کار را به صورت خودکار انجام می‌دهد، اما برای اطمینان می‌توانید این دستور را نیز اجرا کنید:
    sudo systemctl reload nginx
  • وحید نصیری در ۱۴۰۴/۰۴/۰۱ ۲۱:۱۹
    یک نکته‌ی تکمیلی: چرا در این روزهای خاص، سایت‌هایی که مجوز SSL دارند، بالا نمیان!

    همانطور که در متن هم عنوان شد، پس از راه‌اندازی certbot و دریافت مجوزهای TLS/SSL از let's encrypt، تغییراتی به صورت خودکار در فایل conf وب سرور ایجاد شده:
    listen [::]:443 ssl ipv6only=on http2; # managed by Certbot
    listen 443 ssl http2; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/dntips.ir/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/dntips.ir/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    در اینجا به دو مورد http2 و همچنین فایل options-ssl-nginx.conf دقت کنید. اگر فایل /etc/letsencrypt/options-ssl-nginx.conf را باز کنیم که در آن تنظیمات اختصاصی پروتکل TLS درج شده‌اند، قسمتی از آن به صورت زیر تنظیم شده:
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers off;
    که مشخص می‌کند فقط پروتکل‌‌های 1.2 و 1.3 معتبر و امن هستند و مابقی را حذف کرده. همچنین سطر بعدی آن تعیین می‌کند که از این لیست، این مرورگر شماست که انتخاب کننده‌ی این پروتکل‌هاست. اگر آن‌را on کنید، حق انتخاب را از کلاینت می‌گیرید که توصیه نمی‌شود.

    اما ... این روزها، به علت از کار انداختن فیلترشکن‌هایی که از پروتکل TLS استفاده می‌کنند، پروتکل‌های TSLv1.3 و همچنین http2 مسدود شده‌اند. بنابراین اگر قصد دارید سایت خودتان را مجددا قابل دسترسی کنید، در تنظیمات فوق باید TSLv1.3 و http2 را حذف کنید (در دو فایل conf سایت و options-ssl-nginx.conf). سپس یکبار دستور nginx -t را صادر کنید تا از صحت تغییرات مطمئن شوید و دست آخر با اجرای دستور sudo systemctl reload nginx، وب سرور را وادار به خواندن این تنظیمات جدید کنید. البته ... علاوه بر این محدودیت‌ها، سرعت پورت 443 یا همان پورت استاندارد TLS/SSL هم به‌شدت پایین آورده شده و عملا هرچند سایت باز خواهد شد، اما به‌قدری کند است که بهتر است تا رفع محدودیت‌ها صبر کنید.