عنوان:

‫ NGINX برای توسعه‌دهندگان ASP.NET Core - قسمت پنجم - امنیت و مباحث پیشرفته


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

بخش ۵: امنیت و مباحث پیشرفته
اکنون که اپلیکیشن شما به صورت بهینه و پایدار در حال اجراست، زمان آن رسیده که آن را در برابر تهدیدات امنیتی رایج مقاوم کرده و برای الگوهای استقرار مدرن آماده کنیم.

۱. تنظیم هدرهای امنیتی (Security Headers)
هدرهای امنیتی، دستورالعمل‌هایی هستند که سرور شما به مرورگر کاربر ارسال می‌کند تا از حملات سمت کلاینت (Client-Side) مانند Cross-Site Scripting (XSS) و Clickjacking جلوگیری کند. افزودن این هدرها یک راه ساده و بسیار مؤثر برای افزایش امنیت اپلیکیشن شماست.
این هدرها را با دستور add_header داخل بلوک server در فایل کانفیگ سایت خود اضافه کنید.
# در فایل /etc/nginx/sites-available/my-aspnet-app.conf

server {
    # ... سایر تنظیمات

    # ------ شروع هدرهای امنیتی ------

    # مرورگر را مجبور می‌کند فقط از HTTPS استفاده کند (پس از اطمینان از عملکرد صحیح SSL فعال شود)
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # جلوگیری از قرار گرفتن سایت در یک <iframe> در دامنه‌های دیگر (مقابله با Clickjacking)
    add_header X-Frame-Options "SAMEORIGIN" always;

    # جلوگیری از حدس زدن نوع محتوا توسط مرورگر (مقابله با حملات XSS)
    add_header X-Content-Type-Options "nosniff" always;

    # کنترل می‌کند چه اطلاعاتی در هدر Referer ارسال شود
    add_header Referrer-Policy "no-referrer" always;

    # یک سیاست امنیتی محتوای قوی برای جلوگیری از تزریق کدهای مخرب
    # این هدر نیاز به سفارشی‌سازی دقیق بر اساس نیازهای پروژه شما دارد
    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; upgrade-insecure-requests;" always;
    
    # ------ پایان هدرهای امنیتی ------

    # ... سایر location ها
}
نکته مهم: هدر Content-Security-Policy (CSP) بسیار قدرتمند است اما ممکن است در ابتدا باعث شکسته شدن برخی بخش‌های سایت شما (مانند اسکریپت‌ها یا استایل‌های inline) شود. باید آن را با دقت و متناسب با منابعی که سایت شما استفاده می‌کند (مانند CDNها)، تنظیم کنید.

۲. محدودسازی نرخ درخواست‌ها (Rate Limiting)
Rate Limiting یک تکنیک دفاعی حیاتی برای جلوگیری از حملات خودکار مانند تلاش برای هک کردن پسوردها (Brute-force)، حملات Denial-of-Service (DoS) و سوءاستفاده از APIهای شماست. با این کار، تعداد درخواست‌هایی که یک کاربر (بر اساس IP) می‌تواند در یک بازه زمانی مشخص ارسال کند را محدود می‌کنیم.
مراحل پیاده‌سازی:

۱. تعریف یک ناحیه محدودیت:
در فایل nginx.conf و داخل بلوک http، یک ناحیه برای محدودیت تعریف می‌کنیم.
# در فایل /etc/nginx/nginx.conf داخل بلوک http

limit_req_zone $binary_remote_addr zone=login_limit:10m rate=5r/m;
  • $binary_remote_addr: کلید محدودسازی، یعنی IP کاربر.
  • zone=login_limit:10m: یک ناحیه حافظه ۱۰ مگابایتی برای نگهداری وضعیت IP ها.
  • rate=5r/m: نرخ مجاز را ۵ درخواست در دقیقه تعیین می‌کند.

۲. اعمال محدودیت روی یک location خاص:
حالا این محدودیت را روی یک مسیر حساس مانند صفحه لاگین اعمال می‌کنیم.
# در فایل /etc/nginx/sites-available/my-aspnet-app.conf

server {
    # ...
    location /api/account/login {
        limit_req zone=login_limit burst=10 nodelay;

        proxy_pass http://my_aspnet_app_backend;
        # ... سایر تنظیمات پراکسی
    }
}
  • limit_req zone=login_limit: ناحیه محدودیتی که تعریف کردیم را اعمال می‌کند.
  • burst=10: به کاربر اجازه می‌دهد تا ۱۰ درخواست اضافی را به صورت آنی ارسال کند (این درخواست‌ها در صف قرار می‌گیرند). این کار از تجربه کاربری بد جلوگیری می‌کند، اما نرخ کلی همچنان ثابت است. nodelay باعث می‌شود این درخواست‌های اضافی معطل نشوند. اگر کاربری از این حد فراتر رود، NGINX خطای 503 Service Unavailable را برمی‌گرداند.

۳. پیکربندی برای SignalR و WebSockets
اپلیکیشن‌های Real-time با SignalR از پروتکل WebSocket برای ارتباط دوطرفه و پایدار استفاده می‌کنند. یک کانفیگ عادی Reverse Proxy این ارتباط را قطع می‌کند، زیرا برای چرخه‌های کوتاه "درخواست-پاسخ" طراحی شده است. ما باید به NGINX بگوییم که چطور درخواست "ارتقا" به WebSocket را مدیریت کند.
# در فایل /etc/nginx/sites-available/my-aspnet-app.conf

location /myhub { # مسیر هاب SignalR شما
    proxy_pass http://my_aspnet_app_backend;

    # خطوط حیاتی برای پشتیبانی از WebSocket
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "Upgrade";
    
    proxy_set_header Host $host;
    
    # کش کردن برای ارتباطات WebSocket توصیه نمی‌شود
    proxy_cache off;

    # افزایش زمان انتظار برای ارتباطات طولانی مدت
    proxy_read_timeout 120s;
}
نکات کلیدی: دو هدر Upgrade و Connection به NGINX و سرور پشتیبان اجازه می‌دهند تا پروتکل ارتباطی را از HTTP به WebSocket تغییر دهند.

۴. استفاده از NGINX در محیط Docker (با Docker Compose)
استقرار با Docker و کانتینرها، الگوی مدرن و استاندارد توسعه نرم‌افزار است. در این مدل، NGINX و اپلیکیشن ASP.NET Core هر کدام در کانتینر مجزای خود اجرا می‌شوند. Docker Compose ابزاری است که به ما اجازه می‌دهد این محیط چندکانتینری را به سادگی تعریف و مدیریت کنیم.

مراحل اصلی:
۱. Dockerfile برای اپلیکیشن ASP.NET Core: یک فایل Dockerfile استاندارد برای پابلیش و اجرای اپلیکیشن خود بسازید.
۲. فایل کانفیگ NGINX: یک فایل کانفیگ NGINX (مثلاً nginx.conf) در کنار پروژه خود بسازید. تفاوت اصلی در خط proxy_pass است. به جای localhost، از نام سرویس اپلیکیشن که در docker-compose.yml تعریف می‌کنیم، استفاده می‌کنیم.
# در یک فایل محلی مانند ./nginx/default.conf
# ...
proxy_pass http://aspnet-app:8080; # 'aspnet-app' نام سرویس و 8080 پورت داخلی کانتینر است
# ...
۳. فایل docker-compose.yml: این فایل ارکستراسیون را انجام می‌دهد.
version: '3.8'

services:
  # سرویس اپلیکیشن ASP.NET Core
  aspnet-app:
    container_name: my-aspnet-app
    build:
      context: .
      dockerfile: YourApp/Dockerfile # مسیر Dockerfile شما
    environment:
      - ASPNETCORE_URLS=http://+:8080 # Kestrel داخل کانتینر روی این پورت گوش می‌دهد
    # expose:
    #   - "8080" # این پورت فقط در شبکه داخلی داکر قابل دسترس است

  # سرویس NGINX به عنوان Reverse Proxy
  nginx-proxy:
    container_name: my-nginx-proxy
    image: nginx:latest
    ports:
      - "80:80"     # پورت 80 ماشین میزبان را به پورت 80 کانتینر NGINX متصل کن
      - "443:443"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf # فایل کانفیگ ما را در کانتینر کپی کن
    depends_on:
      - aspnet-app # قبل از اجرای NGINX، منتظر باش تا اپلیکیشن اجرا شود

گردش کار:
با اجرای دستور docker-compose up --build، داکر هر دو کانتینر را می‌سازد و اجرا می‌کند. ترافیک از دنیای بیرون به پورت 80 ماشین شما می‌رسد، داکر آن را به کانتینر NGINX هدایت می‌کند. سپس NGINX از طریق شبکه داخلی داکر، درخواست را به کانتینر aspnet-app در پورت 8080 ارسال می‌کند.

با به پایان رساندن این بخش، شما نه تنها می‌توانید یک اپلیکیشن ASP.NET Core را به صورت امن و بهینه میزبانی کنید، بلکه با الگوهای استقرار مدرن و پیشرفته نیز آشنا شده‌اید.