تنظیم SSL به صورت Self–Signed برای NginX روی دبیان ۹ و اوبونتو ۱۸.۰۴ – راهنمای جامع


TLS یا «امنیت لایه انتقال» (transport layer security) و نسخه قبلی آن SSL یعنی «لایه سوکتهای امن» (secure sockets layer) هر دو پروتکلها وب هستند که ترافیک معمول را در یک پوشش رمزنگاری و محافظت شده میپیچند.
سرورها با استفاده از این فناوری میتوانند ترافیک امنی را بین خود و کلاینتهایشان برقرار کنند و احتمال این که پیامها از سوی طرفهای بیرونی تفسیر شوند، از بین میرود. سیستم گواهی نیز به کاربران کمک میکند که هویت سایتی که به آن وصل شدهاند را تأیید کنند.
در این راهنما روش ساخت یک SSL به صورت Self-Signed یا خود-امضا (یعنی آن SSL که مرجع تأیید دیگری ندارد و سرور خودش را تأیید میکند) را برای استفاده از وبسرور Nginx روی سرور دبیان 9 توضیح میدهیم. توجه داشته باشید که تمام مراحل برای سرور اوبونتو 18.04 و حتی اوبونتو 16.04 نیز کاملاً مشابه است.
گواهیهای خود-امضا، ارتباط بین سرور و کلاینتها را رمزنگاری میکنند. با این حال از آنجا که این ارتباط از سوی هیچ مرجع تأیید مورد اعتماد از سوی مرورگرهای وب تأیید نشده است، کاربران نمیتوانند از این گواهی برای اعتبارسنجی خودکار سرور شما استفاده کنند.
یک گواهی خود-امضا در صورتی که روی سرور خود، نام دامنه نداشته باشید، برای مثال زمانی که رابط وب رمزنگاری شده برای استفاده کاربر طراحی نشده است، مناسب خواهد بود. اما اگر نام دامنه دارید در اغلب موارد بهتر است که از یک گواهی امضا شده از سوی CA استفاده کنید. اگر میخواهید برای وبسایت خود SSL ایجاد کنید، میتوانید از این مطلب استفاده کنید.
پیشنیازها
پیش از آغاز باید روی سرور یک کاربر غیر root با دسترسی sudo داشته باشید. همچنین باید وبسرور Nginx را روی سرور نصب کرده باشید. شاید تصمیم داشته باشید که استک LEMP یعنی (Linux, Nginx, MySQL, PHP) را روی سرور خود نصب کنید. زمانی که موارد فوق آماده بودند، میتوانیم راهنمای خود را آغاز کنیم.
گام 1 – ایجاد گواهی SSL
TLS/SSL با استفاده از ترکیبی از گواهی عمومی و کلید خصوصی عمل میکند. کلید SSL روی سرور به صورت محرمانه حفظ میشود. از این کلید برای رمزنگاری محتوایی که به کاربران ارسال میشود، استفاده خواهد شد. گواهی SSL به صورت عمومی با هر کسی که محتوا را درخواست میکند، به اشتراک گذارده میشود. از کلید عمومی برای رمزگشایی محتوای امضا شده به وسیله کلید SSL مرتبط استفاده میشود.
ما میتوانیم یک جفت کلید خود-امضا و گواهی را با استفاده از OpenSSL در یک دستور تکخطی ایجاد کنیم:
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt
پس از اجرای دستور فوق از شما خواسته میشود به یک سری سؤالات پاسخ دهید. پیش از این که این سؤالات را بررسی کنیم، نگاهی به آنچه در دستور خود خواستهایم، خواهیم داشت.
- Openssl: این پایه دستور ما است و ابزاری برای ایجاد و مدیریت گواهیهای OpenSSL، کلیدها و فایلهای دیگر محسوب میشود.
- Req: این زیردستور تعیین میکند که میخواهیم از مدیریت درخواست امضای (CSR) گواهی X.509 استفاده کنیم. منظور از X.509 استاندارد زیرساخت کلید عمومی است که SSL و TLS برای مدیریت کلید و گواهیهای خود از آن بهره میگیرند. ما میخواهیم یک cert به صورت X.509 ایجاد کنیم و از این رو از این زیردستور استفاده میکنیم.
- x509-: این پارامتر به زیردستور قبلی مرتبط است و میگوید که میخواهیم به جای ایجاد یک درخواست امضای گواهی که روال معمول است، یک گواهی خود-امضا ایجاد کنیم.
- nodes-: این پارامتر تعیین میکند که OpenSSL باید از گزینه امن سازی گواهی با یک عبارت رمزی (passphrase) استفاده کند. ما باید کاری کنیم Nginx بتواند در زمان آغاز به کار، این فایل را بدون دخالت کاربر بخواند. یک عبارت رمزی این کار را ناممکن میکند، زیرا هر بار که سرور راهاندازی مجدد میشود باید این عبارت رمزی را مجدداً وارد کنیم.
- days 365-: این گزینه مدت زمانی که گواهی معتبر تلقی میشود را تعیین میکند. ما آن را برای یک سال تعیین میکنیم.
- newkeys rsa:2048-: این پارامتر تعیین میکند که میخواهیم همزمان یک گواهی جدید و یک کلید جدید ایجاد کنیم. ما کلیدی که برای امضا کردن گواهی لازم است را در گام قبلی ایجاد نکردیم و از این رو باید آن را همراه با گواهی ایجاد کنیم. بخش rsa:2048 به این معنی است که کلید RSA باید طولی به اندازه 2048 بیت داشته باشد.
- keyout-: این پارامتر به OpenSSL میگوید که کلید خصوص ایجاد شده را در فایلی که ایجاد میکنیم ذخیره کند.
- out-: این پارامتر تعیین میکند که OpenSSL باید فایل ما را کجا ذخیره کند.
همانطور که قبلاً اشاره کردیم این گزینهها همزمان یک کلید و یک گواهی ایجاد میکنند. از ما چند سؤال در مورد سرور پرسیده میشود تا اطلاعات صحیحی در گواهی گنجانده شوند. باید به سؤالات به طرز صحیح پاسخ داده شود. مهمترین سؤالی که پرسیده میشود به Common Name مربوط است. منظور از Common Name مقدار FQDN سرور یا نام شما است. شما باید نام دامنه مرتبط با سرور خود یا به طور معمولتر، آیپی عمومی سرور خود را ذکر کنید.
کل این اعلان ظاهری شبیه زیر دارد:
Country Name (2 letter code) [AU]:US State or Province Name (full name) [Some-State]:New York Locality Name (eg, city) []:New York City Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc. Organizational Unit Name (eg, section) []:Ministry of Water Slides Common Name (e.g. server FQDN or YOUR name) []:server_IP_address Email Address []:admin@your_domain.com
هر دو فایلی که ایجاد میشوند در زیرشاخههای مناسب دایرکتوری etc/ssl/ ذخیره خواهند شد.
مادامی که از OpenSSL استفاده میکنیم، باید یک گروه قوی Diffie-Hellman نیز ایجاد کنیم که هنگام ارتباط با کلاینتها به صورت (perfect forward secrecy (PFS مورد استفاده قرار میگیرد. این کار از طریق اجرای دستور زیر میسر است:
sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096
این کار اندک زمانی طول میکشد؛ اما وقتی که یک گروه قوی DH در مسیر etc/nginx/dhparam.pem/ ایجاد کنید، میتوانیم از آن در پیکربندیهای خود استفاده کنیم.
گام 2 – پیکربندی NginX برای استفاده از SSL
اینک ما فایلهای گواهی خود را در مسیر دایرکتوری /etc/ssl ایجاد کردهایم و کافی است پیکربندی انجینایکس را تغییر دهیم تا بتوانیم از آن بهرهبرداری کنیم.
بدین منظور باید چند تغییر کوچک در پیکربندی خود ایجاد کنیم.
- ما یک اسنیپست پیکربندی شامل مکانهای فایلهای کلید و گواهی SSL ایجاد میکنیم.
- یک اسنیپست شامل رشتههای SSL قوی ایجاد میکنیم که به وسیله گواهیهای آینده مورد استفاده قرار خواهند گرفت.
- بلوکهای سرور Nginx خود را طوری پیکربندی میکنیم که درخواستهای SSL را مدیریت کرده و از اسنیپستهای فوق استفاده کند.
این روش پیکربندی برای Nginx باعث میشود قادر باشیم بلوکهای سرور را به صورت مرتب حفظ کنیم و اسنیپستهای پیکربندی متداول را در ماژولهایی با قابلیت استفاده مجدد نگهداری کنیم.
ایجاد اسنیپست پیکربندی برای اشاره به کلید و گواهی SSL
ابتدا اجازه بدهید یک اسنیپست پیکربندی Nginx را در دایرکتوری etc/nginx/snippets/ ایجاد کنیم. برای این که هدف از ایجاد این فایل کاملاً مشخص باشد آن را self-signed.conf مینامیم:
sudo nano /etc/nginx/snippets/self-signed.conf
درون این فایل باید مسیر ssl_certificate را به سوی فایل گواهی و مسیر ssl_certificate_key را به سمت کلید مرتبط تعیین کنیم. در این مورد متغیرهای فوق چنین وضعیتی خواهند داشت:
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt; ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
زمانی که خطوط فوق را به فایل اضافه کردید آن را ذخیره کرده و ببندید.
ایجاد یک اسنیپست پیکربندی با تنظیمات رمزنگاری قوی
در این مرحله یک اسنیپست ایجاد میکنیم که در آن برخی تنظیمات SSL را تعیین مینماییم. این تنظیمات باعث میشوند که Nginx بتواند با یک رمز SSL قوی آغاز شود و برخی ویژگیهای پیشرفته که موجب امن ماندن سرور میشود را فراهم میسازد.
پارامترهایی که در این فایل تعریف میکنیم، میتوانند در پیکربندیهای بعدی Nginx نیز مورد استفاده قرار گیرند و از این رو نام فایل را به صورت کلی تعیین میکنیم:
sudo nano /etc/nginx/snippets/ssl-params.conf
ما برای راهاندازی امن SSL برای Nginx از توصیههای انجام یافته توسط Remy van Elst در وبسایت cipherli.st استفاده کردیم. این وبسایت به منظور ارائه تنظیمات رمزنگاری با استفاده آسان برای نرمافزارهای رایج طراحی شده است.
تنظیمات پیشنهادی وبسایت فوق موجب ایجاد امنیت بالایی میشوند. برخی اوقات ممکن است برای بهرهمندی از این تنظیمات، مجبور باشید مطابقت بیشتر با کلاینتها را فدا کنید. اگر میخواهید از کلاینتهای قدیمی نیز پشتیبانی کنید، میتوانید از لیست جایگزینی که در لینک «Yes, give me a ciphersuite that works with legacy / old software» قرار دارد استفاده کنید. انتخاب این که کدام تنظیمات برای شما مناسب است به طور عمده به مرورگرهایی که میخواهید پشتیبانی کنید مربوط میشود؛ اما به طور کلی هر دو تنظیمات، امنیت بالایی ارائه میکنند.
با توجه به مقاصد این راهنما، ما میتوانیم کل تنظیمات به یکباره کپی کنیم. تنها چند تغییر کوچک ایجاد خواهیم کرد. ابتدا DNS resolver ترجیحی برای درخواستهای بالادستی را تعیین میکنیم. ما در این راهنما از گوگل استفاده میکنیم.
سپس کامنت خطی که هدر امنیت انتقال الزامی را غیر فعال کرده است، حذف میکنیم. بدین ترتیب امنیت پروتکل HTTPS به میزان زیادی افزایش مییابد؛ اما در صورتی که به صورت تصادفی آن را فعال یا غیر فعال کنید، عواقب بسیار نامطلوبی خواهد داشت. متن زیر را در فایل اسنیپست ssl-params.conf کپی کنید.
ssl_protocols TLSv1.2; ssl_prefer_server_ciphers on; ssl_dhparam /etc/nginx/dhparam.pem; ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384; ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0 ssl_session_timeout 10m; ssl_session_cache shared:SSL:10m; ssl_session_tickets off; # Requires nginx >= 1.5.9 ssl_stapling on; # Requires nginx >= 1.3.7 ssl_stapling_verify on; # Requires nginx => 1.3.7 resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; # Disable strict transport security for now. You can uncomment the following # line if you understand the implications. # add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header X-XSS-Protection "1; mode=block";
از آنجا که ما از گواهیهای خود-امضا استفاده میکنیم، از SSL stapling استفاده نخواهیم کرد. Nginx بدین منظور یک هشدار میدهد اما مشکلی در عملکرد خود نخواهد داشت. فایل را ذخیره کرده و خارج شوید.
تنظیم پیکربندی Nginx برای استفاده از SSL
اینک که فایلهای خود را آماده کردیم، میتوانیم پیکربندی Nginx را برای فعالسازی SSL تنظیم کنیم. در این راهنما فرض میکنیم که شما از یک فایل پیکربندی بلوک سرور سفارشی در دایرکتوری etc/nginx/sites-available/ استفاده میکنید. ما از etc/nginx/sites-available/example.com/ در این راهنما استفاده میکنیم. شما میتوانید نام فایل پیکربندی خود را در صورت لزوم تعیین کنید.
پیش از هر کار دیگری از فایل پیکربندی خود یک پشتیبان میگیریم.
sudo cp /etc/nginx/sites-available/example.com /etc/nginx/sites-available/example.com.bak
سپس فایل پیکربندی را باز میکنیم تا تغییراتی ایجاد کنیم.
sudo nano /etc/nginx/sites-available/example.com
درون این فایل احتمالاً بلوک سرور با عبارتی مانند زیر آغاز میشود:
server { listen 80; listen [::]:80; server_name example.com www.example.com; root /var/www/example.com/html; index index.html index.htm index.nginx-debian.html; ... }
ممکن است ترتیب موارد در فایل شما متفاوت باشد و به جای root و index از location، proxy_pass با عبارتهای پیکربندی سفارشی دیگر استفاده شده باشد. در این صورت مشکلی وجود ندارد ما تنها میخواهیم مقدار listen را بهروزرسانی کنیم و اسنیپستهای SSL خود را در فایل قرار دهیم. این بلوک سرور موجود را برای عرضه ترافیک SSL روی پورت 443 اصلاح میکنیم، سپس یک بلوک سرور جدید برای پاسخدهی روی پورت 80 و ریدایرکت خودکار ترافیک به پورت 443 ایجاد میکنیم.
توجه داشته باشید که تا زمانی که مطمئن شویم همه چیز به درستی کار میکند، از ریدایرکت 302 استفاده میکنیم و پس از آن میتوانیم از ریدایرکت دائمی 301 بهره بگیریم.
در فایل پیکربندی موجود عبارتهای listen را بهروزرسانی کنید تا از پورت 443 و SSL استفاده کنند، سپس دو فایل اسنیپست را که در مراحل قبلی ایجاد کردیم، در این فایل وارد نمایید:
server { listen 443 ssl; listen [::]:443 ssl; include snippets/self-signed.conf; include snippets/ssl-params.conf; server_name example.com www.example.com; root /var/www/example.com/html; index index.html index.htm index.nginx-debian.html; ... }
سپس بلوک دوم سرور را در فایل پیکربندی پس از کروشه ({) بسته شدن بلوک قبلی وارد کنید:
... server { listen 80; listen [::]:80; server_name example.com www.example.com; return 302 https://$server_name$request_uri; }
این بلوک پیکربندی اصلی است که روی پورت 80 گوش میدهد و ریدایرکت به HTTPS را انجام میدهد. زمانی که کار ویرایش به پایان رسید، فایل را ذخیره کرده و خارج شوید.
گام 3 – تنظیم فایروال
اگر فایروال ufw را چنان که در بخش پیشنیازها توصیه شده است، فعال کرده باشید باید تنظیمات آن را تغییر دهید تا امکان ترافیک SSL فعال شود. خوشبختانه Nginx در هنگام نصب چند پروفایل در این خصوص ثبت میکند.
پروفایلهای موجود را میتوانید با دستور زیر ببینید:
sudo ufw app list
خروجی دستور فوق چیزی شبیه زیر خواهد بود:
Available applications: ... Nginx Full Nginx HTTP Nginx HTTPS ...
تنظیمات کنونی را با دستور زیر میتوانید ببینید:
sudo ufw status
خروجی دستور فوق احتمالاً چیزی شبیه زیر خواهد بود که معنی آن این است که تنها ترافیک HTTP به این وبسرور مجاز است:
Status: active To Action From ------------ OpenSSH ALLOW Anywhere Nginx HTTP ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Nginx HTTP (v6) ALLOW Anywhere (v6)
برای این که علاوه بر آن امکان ترافیک HTTPS نیز فعال شود، باید از پروفایل «Nginx Full» استفاده کنیم و سپس پروفایل «Nginx HTTP» را حذف کنیم:
sudo ufw allow 'Nginx Full' sudo ufw delete allow 'Nginx HTTP'
وضعیت شما اینک باید به شرح زیر باشد:
sudo ufw status
خروجی
Status: active To Action From ------------ OpenSSH ALLOW Anywhere Nginx Full ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Nginx Full (v6) ALLOW Anywhere (v6)
گام 4 – فعالسازی تغییرات در Nginx
اینک که تغییرات لازم را در فایروال ایجاد کردیم، میتوانیم Nginx را ریاستارت کنیم تا تغییرات جدید اعمال شوند.
ابتدا بررسی میکنیم تا مطمئن شویم که هیچ خطای ساختاری در فایلهای ما وجود ندارد. این کار از طریق وارد کردن دستور زیر ممکن است:
sudo nginx -t
اگر همه چیز موفقیتآمیز باشد، نتیجهای شبیه زیر به دست میآورید:
nginx: [warn] "ssl_stapling" ignored, issuer certificate not found nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
به هشداری که در ابتدا داده میشود توجه کنید. همان طور که قبلاً اشاره کردیم، این تنظیمات خاص، یک هشدار ایجاد میکند که چون گواهی ما از نوع خود-امضا است، نمیتواند از SSL Stapling استفاده کند. این وضعیت قابل انتظار است و با این حال سرور ما همچنان میتواند اتصالها را به طرز صحیحی رمزنگاری کند. اگر خروجی شما مطابق کد فوق بود، نشان میدهد که فایل پیکربندی، هیچ خطای ساختاری ندارد. میتوانید NginX را ریاستارت کنیم تا تغییرات اعمال شوند:
sudo systemctl restart nginx
گام 5 - تست کردن رمزنگاری
اینک ما آمادگی داریم که سرور SSL خود را رمزنگاری کنیم. مرورگر خود را باز کنید و نام دامنه یا آیپی سرور خود را پس از //:https در نوار آدرس آن وارد کنید:
https://server_domain_or_IP
از آن جا که این گواهی که ایجاد کردیم به وسیله یکی از مراجع مورد اعتماد مرورگرها تأیید نشده است، احتمالاً یک هشدار با ظاهر ترسناک مانند تصویر زیر میبینیم (این هشدار مربوط به مرورگر گوگل کروم است):
این وضعیت قابل انتظار و نرمال است. ما تنها به جنبه رمزنگاری گواهی خود علاقهمند هستیم و نیازی به تأیید اعتبار شخص ثالث در مورد احراز هویت میزبان نداریم. بر روی گزینه «ADVANCED» کلیک کنید و سپس لینک ارائه شده را بزنید تا به هر ترتیب به سرور خود وصل شوید:
بدین ترتیب وارد وبسایت خود میشوید. اگر به نوار آدرس مرورگر نگاه کنید میبینید که آیکون یک قفل با علامت x روی آن دیده میشود. در این مورد منظور از این علامت ضربدر آن است که گواهی نمیتواند تأیید اعتبار شود؛ اما اتصال شما همچنان رمزنگاری شده است.
اگر Nginx را با دو بلوک پیکربندی کرده باشید، به طور خودکار اتصالهای HTTP را به HTTPS ریدایرکت میکند و میتوانید بررسی کنید که آیا کارکرد ریدایرکت درست مل میکند یا نه:
http://server_domain_or_IP
وارد کردن آدرس فوق در مرورگر باید شما را به همان صفحه قبلی ببرد و بدین ترتیب میفهمیم که ریدایرکت به طور درستی عمل میکند.
گام 6 – تغییر دادن ریدایرکت دائمی
اگر ریدایرکت شما به طرز صحیحی عمل میکند و مطمئن هستید که تنها میخواهید به ترافیک امن اجازه اتصال دهید باید پیکربندی Nginx را طوری تغییر دهید که این ریدایرکت، دائمی باشد. بدین منظور فایل پیکربندی بلوک سرور را مجدداً باز کنید:
sudo nano /etc/nginx/sites-available/example.com
عبارت return 302 را یافته و آن را به return 301 تغییر دهید:
return 301 https://$server_name$request_uri;
فایل را ذخیره کرده و خارج شوید. فایل پیکربندی را برای خطاهای ساختاری بررسی کنید:
sudo nginx –t
زمانی که آماده بودید، Nginx را ریاستارت کنید تا این ریدایرکت به صورت دائمی در آید:
sudo systemctl restart nginx
سخن پایانی
بدین ترتیب شما در این نوشته با مراحل پیکربندی وبسرور Nginx برای استفاده از رمزنگاری قوی برای اتصالهای کلاینتها آشنا شدید. این ترافیک امن باعث میشود که درخواستهای کاربران امن باشند و از مشاهده شدن ترافیک از سوی اشخاص ثالث جلوگیری میکند.
اگر این نوشته مورد توجه شما واقع شده، ممکن است به موارد زیر نیز علاقهمند باشید:
- ۷ دلیل برای این که از گواهی امنیتی SSL برای وبسایت خود استفاده کنید
- مجموعه آموزشهای دروس مهندسی کامپیوتر
- مجموعه آموزشهای شبکههای کامپیوتری
- آموزش امنیت در شبکه های کامپیوتری و اینترنت
- گواهی های SSL وایلدکارد Let’s Encrypt با استفاده از اعتبارسنجی کلودفلیر روی CentOS 7
- معرفی برترین سریال ها در زمینه هک و امنیت سایبری
==
تشکر، خیلی مفید بود