امشب مسیر ورود یک درخواست را از اتصال شبکه تا برنامه بررسی می‌کنیم. هدف این است که پراکسی فقط اطلاعات مبدأ معتبر را بپذیرد و سیاست محدودیت درخواست واقعاً روی مسیریاب اعمال شود. مبنا Traefik Proxy v3.7 و آزمایشگاه Compose دوره است؛ نسخهٔ اصلاحی یا digest آزموده‌شده را ثبت کنید. حدود ۶۰ تا ۹۰ دقیقه برای اجرای تمرین و رفع خرابی در نظر بگیرید؛ این زمان جدا از مطالعهٔ متن است.

فهرست کامل دورهٔ ترافیک در ۳۰ شب

هدف‌های یادگیری#

  • کاهش سطح حملهٔ ارائه‌دهنده، محیط اجرا، شبکه، داشبورد و مسیریابی.
  • اعتماد به هدرهای forwarded فقط از پراکسی‌های بالادستی شناخته‌شده.
  • اعمال سیاست لایه‌ای درخواست و TLS با بررسی اثر آن بر برنامه‌ها.

تمرین عملی: خط پایهٔ راه‌اندازی و مسیریابی#

سرویس whoami و HTTPS سالم درس‌های Compose، گواهی آزمایشگاهی معتبر برای whoami.example.test و فایل CA در certs/lab-ca.crt پیش‌نیازند. پیش از تغییر، یک درخواست موفق بفرستید و تنظیمات سالم را نگه دارید. نمونهٔ زیر بخشی از تنظیمات راه‌اندازی است؛ آن را با پیکربندی موجود ادغام کنید، نه اینکه بخش‌های گواهی و شبکه را حذف کنید. تغییر این بخش به راه‌اندازی مجدد Traefik نیاز دارد.

در این توپولوژی، 192.0.2.10 فقط نشانی آموزشی پراکسی بالادستی مستقیم است. آن را با آدرسی که Traefik واقعاً به‌عنوان همتای اتصال می‌بیند جایگزین کنید. اگر کلاینت مستقیم وصل می‌شود، بخش‌های اعتماد به پراکسی را حذف کنید. اعتماد به یک زیرشبکهٔ بزرگ، همهٔ میزبان‌های آن را وارد مرز تصمیم امنیتی می‌کند.

entryPoints:
  websecure:
    address: ":443"
    forwardedHeaders:
      trustedIPs: ["192.0.2.10/32"]
    proxyProtocol:
      trustedIPs: ["192.0.2.10/32"]
    transport:
      respondingTimeouts:
        readTimeout: 30s
        writeTimeout: 30s
        idleTimeout: 90s
providers:
  file:
    directory: /etc/traefik/dynamic
    watch: true
  docker:
    exposedByDefault: false
    constraints: "Label(`edge.owner`,`platform`)"
api: {dashboard: true, insecure: false}

Proxy Protocol را فقط وقتی فعال کنید که بالادست مستقیم واقعاً آن را می‌فرستد. تنظیم نادرست ممکن است ترافیک را رد کند یا اطلاعات مبدأ جعلی را معتبر بداند.

هدرهای HTTP و Proxy Protocol دو روش مستقل انتقال اطلاعات اتصال‌اند. فعال‌بودن یکی، نیاز دیگری را اثبات نمی‌کند. پراکسی بالادستی هم باید ورودی جعل‌شدهٔ کلاینت را طبق سیاست مشخص پاک یا بازسازی کند. فهرست trustedIPs را با فهرست کاربران مجاز برنامه اشتباه نگیرید: این گزینه دربارهٔ اعتماد به گزارش پراکسی است.

فایل زیر را به‌عنوان dynamic/security.yml در پوشه‌ای بگذارید که داخل کانتینر در /etc/traefik/dynamic نصب شده است. تعریف میان‌افزار به‌تنهایی آن را فعال نمی‌کند؛ در مرحلهٔ بعد زنجیره را به مسیریاب وصل می‌کنیم.

http:
  middlewares:
    public-policy:
      chain: {middlewares: [request-cap, rate, headers]}
    request-cap:
      inFlightReq: {amount: 100}
    rate:
      rateLimit: {average: 50, burst: 100, period: 1s}
    headers:
      headers:
        contentTypeNosniff: true
        frameDeny: true
        referrerPolicy: strict-origin-when-cross-origin
        stsSeconds: 31536000
        stsIncludeSubdomains: true
tls:
  options:
    default:
      minVersion: VersionTLS12
      sniStrict: true

HSTS را فقط پس از اطمینان از کارکرد دائمی HTTPS روی تمام نام‌های میزبان تحت پوشش اعمال کنید؛ includeSubDomains می‌تواند زیردامنه‌های نامرتبط را مختل کند.

HSTS سیاستی است که مرورگر به خاطر می‌سپارد؛ حذف هدر از تنظیمات، وضعیت ذخیره‌شده در مرورگر را فوراً برنمی‌گرداند. این نمونه را روی نام آزمایشگاهی مستقل اجرا کنید. همچنین frameDeny نمایش صفحه در قاب را مسدود می‌کند و ممکن است با کاربرد مجاز برنامه تعارض داشته باشد. سیاست هدر را با ورود، دانلود و مسیرهای اصلی برنامه بسنجید.

در labelهای سرویس whoami، نام مسیریاب واقعی را بررسی و این موارد را ادغام کنید:

services:
  whoami:
    labels:
      edge.owner: platform
      traefik.enable: "true"
      traefik.http.routers.whoami.middlewares: public-policy@file

این قطعه، فایل کامل Compose نیست؛ rule، شبکه، TLS و پورت سرویس قبلی باید باقی بمانند. اگر مسیریاب میان‌افزار احراز هویت دارد، آن را در فهرست حفظ کنید و ترتیب اجرا را بازبینی کنید. پسوند @file یعنی زنجیره در ارائه‌دهندهٔ فایل تعریف شده، حتی اگر مسیریاب از labelهای Docker کشف شده باشد. نبود این پسوند می‌تواند باعث جست‌وجوی نام در ارائه‌دهندهٔ اشتباه و خطای مسیر شود.

بررسی رفتار، نه صرفاً وجود تنظیم#

ss -lntup
docker inspect TRAEFIK_CONTAINER --format '{{json .HostConfig.SecurityOpt}}'
curl -I --resolve whoami.example.test:443:127.0.0.1 \
  --cacert certs/lab-ca.crt https://whoami.example.test/
openssl s_client -connect 127.0.0.1:443 -servername whoami.example.test -tls1_1 </dev/null
rg -l '(password|token|secret|BEGIN .*PRIVATE KEY|api\.insecure)' .

در فرمان docker inspect نام واقعی کانتینر را جایگزین کنید. جست‌وجوی آخر فقط نام فایل‌های مشکوک را نشان می‌دهد تا رمز احتمالی در ترمینال چاپ نشود؛ این جست‌وجو ممیزی کامل رازها نیست و نام فایل هم ممکن است خصوصی باشد. نتیجه را عمومی نکنید.

درخواست مثبت باید پاسخ برنامه و هدر X-Content-Type-Options: nosniff را نشان دهد. سپس از مبدأ خارج فهرست پراکسی‌های مورداعتماد، همان درخواست را با هدر جعلی ارسال کنید:

curl --fail --show-error --silent \
  --resolve whoami.example.test:443:127.0.0.1 \
  --cacert certs/lab-ca.crt \
  -H 'X-Forwarded-For: 198.51.100.77' https://whoami.example.test/

این نمونهٔ loopback برای اجرای روی میزبان است؛ از کلاینت دیگر آدرس مقصد را عوض کنید. در پاسخ تشخیصی whoami، هویت مؤثر مبدأ نباید صرفاً عدد ساختگی باشد. آزمون را یک بار از مسیر پراکسی واقعی نیز انجام دهید و زنجیرهٔ هدر را با طرح مقایسه کنید. پاسخ موفق HTTP به‌تنهایی صحت هویت گزارش‌شده را ثابت نمی‌کند.

شکست دستور TLS قدیمی هم باید تفسیر شود: اگر OpenSSL محلی اصلاً TLS 1.1 یا رمزهای سازگار را فعال نکند، شکست پیش از مذاکرهٔ مفید رخ می‌دهد. ابتدا اتصال مثبت TLS 1.2 با همین نام و CA را تأیید کنید، سپس پیام خطای آزمون منفی را ثبت کنید. sniStrict نیز نام درخواست‌شده در مذاکرهٔ TLS را بررسی می‌کند؛ جای کنترل دسترسی کاربر یا حفاظت از داشبورد را نمی‌گیرد.

فهرست ایمن‌سازی#

  • Docker API فیلتر و احراز هویت دارد یا ریسک انتشار آن رسماً پذیرفته شده است؛ RBAC و ACL در Kubernetes و Nomad حداقل دسترسی را دارند.
  • هرجا پلتفرم و راهبرد پورت اجازه می‌دهد، Traefik با کاربر غیر root، بدون capability اضافه، با فایل‌سیستم فقط‌خواندنی و سیاست seccomp، AppArmor یا SELinux اجرا می‌شود.
  • شبکه‌ها و entrypointهای عمومی، خصوصی، پشت‌صحنه و مدیریت جدا هستند.
  • داشبورد، API و متریک‌ها احراز هویت یا مجوز شبکه می‌خواهند.
  • دامنهٔ ارائه‌دهنده به فعال‌سازی صریح و مالکیت محدود است.
  • ایمیج و digest، فهرست اجزای نرم‌افزار یا SBOM و هشدارها، افزونه‌ها و وصله‌های پلتفرم پایه بازبینی شده‌اند.
  • محدودیت نرخ، بدنه و هم‌زمانی با بارهای کاری مجاز آزموده شده است.

نکته‌های عیب‌یابی#

  • همهٔ کلاینت‌ها با IP متعادل‌کنندهٔ بار دیده می‌شوند: زنجیرهٔ اعتماد forwarded header ناقص است یا برنامه هدر دیگری می‌خواند.
  • IP کلاینت جعل می‌شود: forwarded header در حالت insecure است یا CIDRهای مورد اعتماد بیش از حد گسترده‌اند.
  • ورود یا callback پس از افزودن هدر خراب می‌شود: سیاست CSP، HSTS یا frame تعارض دارد؛ برای هر برنامه جداگانه اعمال و آزمایش کنید.
  • پاسخ 429 زیر بار عادی: مدل نرخ و هم‌زمانی، تجمع پشت NAT، جهش بار یا درخواست طولانی را لحاظ نمی‌کند.

خودآزمایی#

  1. چرا اعتماد به تمام forwarded headerها ناامن است؟ کلاینت می‌تواند دادهٔ مبدأ و پروتکل مورد استفادهٔ احراز هویت، تغییرمسیر و لاگ را جعل کند.
  2. چه چیزی باید داشبورد را محافظت کند؟ محدودیت شبکه همراه احراز هویت، مجوزدهی و TLS.
  3. چرا میان‌افزار را برای هر برنامه می‌آزماییم؟ سیاست امنیتی با رفتار مجاز مرورگر و API تعامل دارد.
  4. اثبات کنید: X-Forwarded-For جعلی از مبدأ نامطمئن نادیده گرفته می‌شود و TLS 1.1 شکست می‌خورد.

برای بازگشت، label و فایل پویای قبلی را با هم برگردانید تا ارجاع به میان‌افزار حذف‌شده باقی نماند. اگر تنظیم راه‌اندازی تغییر کرده، سرویس را با نسخهٔ سالم دوباره اجرا کنید و درخواست مثبت را تکرار کنید. نتیجهٔ تحویل شامل مبدأ آزمون، نام مسیریاب، هدر مشاهده‌شده و خطای دقیق آزمون منفی باشد؛ رمز و کوکی را ثبت نکنید.

منابع#