TLS و HTTPS

چرا HTTPS؟

HTTP خام، داده را به‌صورت متن ساده روی شبکه می‌فرستد؛ یعنی هرکسی در مسیر — یک Proxy میانی، یا حتی ISP — می‌تواند آن را بخواند یا دست‌کاری کند، بدون این‌که شما اصلاً متوجه شوید. HTTPS همان HTTP است، فقط این بار روی یک کانال رمزگذاری‌شده به اسم TLS، و سه چیز مهم را تضمین می‌کند:

  • محرمانگی — محتوا فقط برای دو طرف واقعی مکالمه خوانا است
  • صحت و یکپارچگی — داده در مسیر دست‌کاری نمی‌شود، حتی اگر کسی سعی کند
  • احراز هویت سرور — مطمئن می‌شوید واقعاً به سرور example.com وصل شده‌اید، نه به یک سرور جعلی که خودش را جای آن جا زده

در کار روزمره‌ی DevOps این مفاهیم همه‌جا حاضرند: وب‌سرورها و سرویس‌های API امروزه تقریباً همیشه فقط روی HTTPS کار می‌کنند، و همین منطق در جاهای دیگری مثل اتصال رمزگذاری‌شده به پورت 443 یا حتی برخی سرویس‌های دیتابیس مانند PostgreSQL هم تکرار می‌شود.

گواهی(Certificate) چیست؟

سرور یک گواهی (Certificate) به کلاینت نشان می‌دهد که در آن نام دامنه، نام صاحب گواهی و مدت اعتبار (Validity Period) نوشته شده. این گواهی توسط یک Certificate Authority (CA) امضا شده؛ مرورگرها و سیستم‌عامل‌ها از قبل فهرستی از CAهای معتبر دارند و زنجیره‌ی امضا را با همین فهرست چک می‌کنند. اگر گواهی منقضی شده باشد، صادرکننده‌اش معتبر نباشد، زنجیره‌ی امضا ناقص باشد یا نام دامنه با گواهی جور نباشد، مرورگر یا curl بی‌درنگ خطا می‌دهند — این‌ها خطاهای TLS هستند و باید آن‌ها را از خطاهای HTTP معمولی جدا کرد، چون ریشه‌شان کاملاً فرق دارد.

در محیط‌های آزمایشی (Development Environment) معمولاً یک گواهی Self-Signed می‌سازند که توسط هیچ CA معتبری امضا نشده، به همین دلیل مرورگر آن را رد می‌کند و هشدار می‌دهد؛ در Production اما یک CA واقعی و معتبر (مثل Let’s Encrypt) گواهی صادر می‌کند تا کاربر نهایی هیچ هشداری نبیند.

Handshake

TLS Handshake پیش از رسیدن اولین درخواست واقعی اتفاق می‌افتد، و با این‌که اسمش پیچیده به‌نظر می‌رسد، ماجرا نسبتاً کوتاه است: کلاینت نسخه‌ی TLS و Cipher Suiteهایی که می‌فهمد را پیشنهاد می‌دهد، سرور گواهی خودش را نشان می‌دهد، کلاینت زنجیره‌ی گواهی را در برابر CAهای شناخته‌شده چک می‌کند، بعد کلیدهایی برای رمزگذاری همان Session به‌اشتراک گذاشته می‌شوند و از همان لحظه کانال رمزگذاری‌شده فعال می‌شود. یک نکته‌ی مهم را همیشه یادتان باشد: در تمام این مراحل، کلید خصوصی سرور هیچ‌وقت جابه‌جا نمی‌شود — امنیت TLS متکی به رمز نیست، متکی به یک مبادله‌ی کلید هوشمند است.

بررسی عملی

با openssl s_client می‌توانید کل این Handshake و گواهی را مستقیم و بدون واسطه ببینید:

1openssl s_client -connect example.com:443 -brief </dev/null

اگر خروجی Verification: OK را همراه با نام پروتکل و Cipher دیدید، یعنی Handshake با موفقیت انجام شده. برای دیدن جزئیات بیشتر گواهی — مثلاً صادرکننده و تاریخ انقضا — نسخه‌ی کامل را اجرا کنید و به بخش Certificate نگاه کنید:

1openssl s_client -connect example.com:443 </dev/null

یک دستور کوتاه‌تر و کاربردی‌تر برای اسکریپت‌نویسی، دیدن سریع تاریخ انقضا است:

1openssl s_client -connect example.com:443 </dev/null 2>/dev/null | openssl x509 -noout -dates

همان مسیر را با curl -v هم می‌توانید ببینید:

1curl -v https://example.com/

خط‌هایی که با * شروع می‌شوند مراحل TLS را نشان می‌دهند — SSL connection using ...، بعد Server certificate، و در نهایت همان تبادل HTTP که در درس قبل دیدید، این بار فقط روی یک کانال رمزگذاری‌شده. برای مقایسه، یک درخواست ساده به http:// بزنید و ببینید چطور با کد 301 به https:// هدایت می‌شود.

تمرین

تاریخ انقضای گواهی چند سایت مختلف را با دستور کوتاه بالا مقایسه کنید:

1for host in example.com github.com wikipedia.org; do
2  echo "== $host =="
3  openssl s_client -connect "$host:443" -servername "$host" </dev/null 2>/dev/null | openssl x509 -noout -dates
4done

نتیجه معمولاً چند ماه تا اعتبار باقی مانده را نشان می‌دهد. حالا این را در ذهن نگه دارید: اگر گواهی یک سرویس Production منقضی شود، همه‌ی کلاینت‌ها — مرورگر، curl، حتی سرویس‌های دیگری که با API آن حرف می‌زنند — همزمان و بدون هشدار قبلی خطا می‌دهند. به همین دلیل بسیاری از تیم‌ها مانیتورینگ جداگانه‌ای فقط برای «چند روز تا انقضای گواهی» دارند؛ همین دستور openssl x509 -noout -dates پایه‌ی بسیاری از همان اسکریپت‌های ساده‌ی مانیتورینگ است.

منابع یادگیری

مستندات و مقالات

ویدیو