تنظیم SSL در Traefik با ابرآروان
این روزها با استفاده از ابزارهای متنوعی میتوانیم گواهینامه های SSL برای دامنه هایمان صادر کنیم. در این پست به بررسی روش این کار با Traefik و ابرآروان میپردازیم.
اگر پست های قبلی رو دنبال کرده باشید ، میدونید که Traefik یک reverse proxy و load balancer مدرن و کامله که به توسعه میکروسرویس ها خیلی کمک میکنه. از ویژگی های خوبش اینه که با Endpoint های مختلف سازگاری خوبی داره و میشه همه جا ازش استفاده کرد. برای مثال یک سرویس عادی رو باهاش مسیردهی کنید یا اینکه توی Docker یا Kubernetes ازش استفاده کنید.
پیاده سازی Load Balancer با استفاده از Traefik
نصب و استفاده از Traefik در Kubernetes
افزایش قابلیت های Traefik با Pilot
یکی از بهترین قابلیت هایی که در Traefik وجود داره ، مدیریت خودکار گواهینامه های SSL شامل ساخت ، تمدید و نگهداری اون هاست. شما به راحتی میتوانید با استفاده از یک ACME Provider مانند Let's Encrypt برای دامنه های خودتون گواهینامه SSL بسازید.
نکته ای که اینجا باید در نظر داشته باشیم ، مدیریت این گواهینامه ها در DNS Provider هاست. برای مثال وقتی دامنه خودتون رو در پنل ابرآروان یا Cloudflare تنظیم میکنید ، صدور گواهینامه ها همونجا هم انجام میشه ، پس چطور باید این دو مورد رو باهم تطابق بدیم؟ مسلما گواهینامه ای که Traefik باهاش کار میکنه باید با DNS Provider یکسان باشه.
اول بیاید به سراغ ساخت گواهینامه بریم.
HTTPS در Traefik
Traefik از HTTPS و TLS پشتیبانی می کنه که به دو بخش پیکربندی تقسیم شده:
- روترها
- اتصال TLS
به فرض شما سرویس های مختلفی دارید که برای هر کدام از اونها یک زیر دامنه در نظر گرفتید مانند :
- db.domain.ir
- mail.domain.ir
- git.domain.ir
حال باید یک گواهینامه Wildcard صادر کرده و اون رو برای تمام سرویس های خودتون اعمال کنید. در این مرحله Traefik سه انتخاب پیش روی شما قرار داده :
- TLS Challenge : از چالش
TLS-ALPN-01
برای تولید و تمدید گواهینامه های ACME با ارائه گواهی TLS استفاده میشه. - HTTP Challenge : از چالش
HTTP-01
برای تولید و تمدید گواهینامه های ACME با ارائه یک منبع HTTP تحت یک URI معتبر استفاده میشه. - DNS Challenge : از چالش
DNS-01
برای تولید و تمدید گواهینامه های ACME با ایجاد یک رکورد DNS استفاده میشه.
ساده ترین راه استفاده از گزینه DNS Challenge است. ما مسلما از یک DNS Provider استفاده میکنیم که بدون دردسر و تنظیم اضافه میشه گواهینامه هامون رو هم از همین طریق با چالش DNS-01
بسازیم.
از اونجایی که Traefik با زبان GO نوشته شده ، جهت انجام امور این بخش از کتابخانه LEGO
استفاده میکنه.
LEGO : Let’s Encrypt client and ACME library written in Go 😉
تنظیم DNS Challenge
ابتدا روش کار رو بررسی کنیم. در اینجا ما به دو Entry Point نیاز داریم :
Web
: برای مدیریت درخواست های ساده HTTP روی پورت 80WebSecure
: برای مدیریت درخواست های HTTPS روی پورت 443
پس ابتدا web
را تعریف میکنیم :
version: "3.9"
services:
traefik:
image: traefik
command:
# Set up an insecure listener that redirects all traffic to TLS
- "--entryPoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
با استفاده از web
تمامی درخواست های HTTP را دریافت کرده و اون ها رو به websecure
با HTTPS منتقل ( Redirect ) میکنیم.
حال باید websecure
را تعریف کنیم :
version: "3.9"
services:
traefik:
image: traefik
command:
# Set up an insecure listener that redirects all traffic to TLS
- "--entryPoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
# Set up the TLS configuration for our websecure listener
- "--entryPoints.websecure.address=:443"
- "--entrypoints.websecure.http.tls=true"
- "--entrypoints.websecure.http.tls.certResolver=letsencrypt"
- "--entrypoints.websecure.http.tls.domains[0].main=domain.ir"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.domain.ir"
در اینجا موارد زیر اعمال شده :
- درخواست ها روی پورت 443 دریافت میشه
- برای این درخواست ها TLS اعمال میشه
- برای TLS از
letsencrypt
استفاده شده - دامنه
domain.ir
و تمام زیردامنه های اون مورد قبوله
توجه کنید که اگر نیاز به مدیریت دامنه های متعدد دارید ، همه شون رو باید همینجا تعریف کنید. از اندیس 0 شروع میشه و همینطور ادامه پیدا میکنه
تا به اینجا ، هر دو Entry Point ما حاضر شده و حالا باید اصل کاری یعنی خود Certificates Resolver تنظیم بشه ( همون Let's Encrypt ). خوشبختانه کتابخانه LEGO از ابرآروان هم پشتیبانی میکنه و میتونیم به راحتی ازش استفاده کنیم.
version: "3.9"
services:
traefik:
image: traefik
command:
# Set up an insecure listener that redirects all traffic to TLS
- "--entryPoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
# Set up the TLS configuration for our websecure listener
- "--entryPoints.websecure.address=:443"
- "--entrypoints.websecure.http.tls=true"
- "--entrypoints.websecure.http.tls.certResolver=letsencrypt"
- "--entrypoints.websecure.http.tls.domains[0].main=domain.ir"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.domain.ir"
# Set up LetsEncrypt
- "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=arvancloud"
- "--certificatesresolvers.letsencrypt.acme.email=<YOUR EMAIL ADDRESS>"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme-arvan.json"
در اینجا dnschallenge
رو فعال کرده و arvancloud
رو به عنوان Provider انتخاب میکنیم. سپس آدرس ایمیل مورد نظر که باید گواهینامه ها برای اون صادر بشه رو هم معرفی کرده و در نهایت یک فایل JSON برای ذخیره سازی گواهینامه های صادر شده در نظر میگیریم.
توجه داشته باشید که اسامی عمومی DNS Provider ها با alias اونها که در اینجا استفاده میشه ممکنه متفاوت باشه برای مثال : G-Core -> gcore. جهت مشاهده لیست کامل Provider های پشتیبانی شده توسط LEGO به این لینک مراجعه کنید
تا اینجا همه چیز انجام شده و فقط اعتبارسنجی باقی مونده. این مورد از طریق تعریف یک متغیر ENV با عنوان ARVANCLOUD_API_KEY
صورت میپذیره. شما نیاز به تعریف یک کلید API در پنل ابرآروان دارید که دسترسی شبکه توزیع محتوا برای اون وجود داشته باشه. سپس این کلید رو به صورت ENV تعریف میکنیم :
تنظیمات به این شکل خواهد بود
version: "3.9"
services:
traefik:
image: traefik
command:
# Set up an insecure listener that redirects all traffic to TLS
- "--entryPoints.web.address=:80"
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
# Set up the TLS configuration for our websecure listener
- "--entryPoints.websecure.address=:443"
- "--entrypoints.websecure.http.tls=true"
- "--entrypoints.websecure.http.tls.certResolver=letsencrypt"
- "--entrypoints.websecure.http.tls.domains[0].main=domain.ir"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.domain.ir"
# Set up LetsEncrypt
- "--certificatesresolvers.letsencrypt.acme.dnschallenge=true"
- "--certificatesresolvers.letsencrypt.acme.dnschallenge.provider=arvancloud"
- "--certificatesresolvers.letsencrypt.acme.email=<YOUR EMAIL ADDRESS>"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme-arvan.json"
environment:
- "ARVANCLOUD_API_KEY=Apikey 1a4a4634-9413-5d67-f4a0-3526b893ab"
به همین راحتی تنظیمات Traefik انجام شد و برای دامنه شما یک گواهینامه WildCard صادر و تعریف میشه که در ادامه با فعال شدن و شناسایی هرکدام از سرویس ها ، به دامنه اون سرویس اختصاص پیدا میکنه ، برای مثال :
version: "3.7"
services:
nikas:
image: nikasproject/server:1.1.9
labels:
- "traefik.http.routers.nikas.rule=Host(`nikas.domain.ir`)"
- "traefik.http.routers.nikas.entrypoints=websecure"
فقط کافیه یک Rule برای روتر سرویس تعریف کنید و دامنه/زیردامنه مورد نظر رو براش تنظیم کنید. Traefik خودکار سرویس رو شناسایی کرده ، برای اون گواهینامه صادر و ذخیره میکنه.
چند نکته
-
متغیر های دیگه ای برای کار با ابرآروان وجود داره ، لیست کامل اون ها :
ARVANCLOUD_HTTP_TIMEOUT
: API request timeoutARVANCLOUD_POLLING_INTERVAL
: Time between DNS propagation checkARVANCLOUD_PROPAGATION_TIMEOUT
: Maximum waiting time for DNS propagationARVANCLOUD_TTL
: The TTL of the TXT record used for the DNS challenge
جهت اطلاعات بیشتر به مستندات CDN API ابرآروان مراجعه کنید
-
مسلما Let's Encrypt از Rate Limit بهره میبره. اطلاعات بیشتر. برای تست و آزمون و خطای خودتون در ابتدا از سرور Staging اونها استفاده کنید تا به مشکل نخورید.
-
جهت جلوگیری از بروز خطا در معرفی گواهینامه به DNS Provider میتونید از یک تاخیر کوچیک در کار استفاده کنید. به صورت پیشفرض رکورد TXT ساخته شده باید تایید بشه و ممکنه این مورد زمان بر باشه ( برای ابرآروان همینطوره و مشکل وجود داره ). پس خیلی راحت با استفاده از گزینه
delaybeforecheck
میشه این کار رو انجام داد و برای مثال 1 ثانیه تاخیر ایجاد کنیم. -
تنظیمات بیشتر و کامل تری برای TLS و Let's Encrypt وجود داره. موارد توضیح داده شده در این پست ، بخش های ضروری و اصلی کار بود. با توجه به نیازهای خودتون از تنظیمات کامل تری بهره ببرید.
-
اگر سرویس های متعددی تحت زیردامنه های مختلف اجرا میکنید حتما باید از WildCard و DNS-Challenge استفاده کنید وگرنه Traefik با ابرآروان مشکلات اساسی پیدا میکنه و باهم کنار نمیان 😂
-
هر سوال داشتید ، اول نگاهی به مستندات بندازید و اگر راه حلی پیدا نکردید ، راحت باشید و بپرسید
با توجه به اینکه آروان اخیرا دامنه خودش رو عوض کرده حین صدور گواهینامه ها به مشکل میخورین. به روزرسانی دامنه در LEGO انجام شده ولی خب انتشار نسخه توسط اونها و پس از اون خود Traefik زمانبر خواهد بود.
برای رفع این مشکل من یک نسخه کاستوم از Traefik منتشر کردم که از آخرین نسخه استفاده بشه و API نهایی رو استفاده کنه. جهت رفع مشکل میتونید یک بار با این ایمیج پروژه خودتون رو بالا بیارید تا گواهینامه ها ساخته بشه ٬ سپس به نسخه رسمی برگردید.
version: "3.9"
services:
traefik:
image: hatamiarash7/traefik-r1c
...
اگر مشکل یا سوالی داشتید ٬ تعارف نکنید و پیام بدین 😁