חזרה לבלוג של Webship

Webship הנדסה

תעודות TLS ב-Webship: מרכז הסמכה ACME המובנה

ראו כיצד Webship 1.4.0 מוציא ומסתובב תעודות TLS פרטיות לכל אתר עם CA המשולב שלו, כיצד עובדת האמון של הלקוח, וכיצד זהויות משולבות מתקיימות בצמוד עם תעודות ציבוריות של ACME וידניות.

# תעודות TLS ב-Webship: ה-ACME CA המוטמע

תעודת TLS מבצעת שני תפקידים: היא מסייעת בהצפנת חיבור ומודיעה ללקוח לאיזו זהות הוא מדבר. ההצפנה יכולה להיות חזקה בעוד שהחלטת האמון שגויה עבור הקהל. לכן, אוטומציה של תעודות חייבת להתחיל עם שאלה אחת: מי חייב לסמוך על האתר הזה?

Webship 1.4.0 מקבל את הבחירה הזו באופן עצמאי עבור כל אתר מוגדר. אתר ציבורי יכול להשתמש בתעודת ACME מהימנה על ידי הדפדפן, שירות פנימי יכול להשתמש בסמכות התעודה הפרטית המובנית של Webship, ואתר עם PKI קיים יכול להמשיך להשתמש בקבצי תעודה המנוהלים על ידי המפעיל. כולם יכולים לשתף תהליך Webship אחד מבלי לשתף מפתח פרטי אחד או גבול אמון אחד.

ארבעה מצבי תעודה אוטומטיים, הנבחרים לפי אתר

שדה certificate_mode שייך לכל רשומת [[sites]]. זה לא מתג עולמי.

| מצב | מקור מהימן | ההתאמה הטובה ביותר | מסלול אימות | | --- | --- | --- | --- | | לפי אתר | חנויות אמון ציבוריות לדפדפן ומערכת הפעלה | אתר ציבורי עם שם מארח יחיד ומדויק | ACME ציבורי עם TLS-ALPN-01 | | צי | חנויות אמון של דפדפן ומערכת הפעלה ציבוריות | מערכות גדולות של שמות מדרגה שלישית ורביעית תחת דומיינים רשומים מפורשים | ACME ציבורי עם DNS-01 ושברים יציבים של תעודות | | מוטמע | שורש פרטי Webship שהותקן על ידי המפעיל | שירותים פנימיים, מכשירים מנוהלים, צי פרטי, וסביבות בדיקה | הנפקה בתהליך; ללא אתגר חיצוני | | משותף | מאגרי האמון של דפדפן ומערכת הפעלה ציבוריים | פריסות ישנות שמשתמשות בכוונה בקבוצת רב-SAN ציבורית אחת | ACME ציבורי עם TLS-ALPN-01 |

ברירת המחדל היא per_site. היא מזמינה תעודה ציבורית אחת לשם המדויק של האתר. מצב Fleet הוא האפשרות הציבורית הניתנת להרחבה עבור רבים מתתי-הדומיינים העמוקים. מצב Embedded משתמש ב-Webship CA פנימי פרטי בתהליך. מצב Shared נשאר זמין עבור תאימות, אך הוא אינו ברירת המחדל.

תעודה ומפתח מלאים תחת [sites.tls] תמיד מקבלים קדימות על פני הנפקה אוטומטית עבור אתר זה.

מה משמעות 'ACME CA מוטמע'

קטע התצורה נקרא [acme_ca], אך ה-CA המוטמע אינו שירות ACME ציבורי או נגיש לרשת. הוא אינו חושף נקודת קצה של ספרייה, אינו מקבל הרשמה מרחוק, אינו קורא ל-API של הרשם, ואינו מבצע אתגר הוכחת שליטה.

במקום זאת, Webship שומר את כל מסלול ההנפקה הפרטי בתהליך אחד:

  1. האתר בוחר certificate_mode = "מובנה".
  2. Webship טוען או יוצר את זהות השורש הפרטית בתיקיית המצב שנקבעה.
  3. Webship יוצר מפתח פרטי חדש לאתר.
  4. השורש המוטבע חותם על תעודת עלים עבור השם המדויק הזה.
  5. Webship מאמת את הזהות שהושלמה לפני התקנתה בפתרון ה-TLS החי.
  6. התעודה זמינה אז לכל פרוטוקול מופעל לאותו אתר.

אתגר רשת בסגנון ACME היה מוכיח רק Webship לעצמו, ולכן הנתיב המוטמע לא כולל בכוונה פרוטוקול רשת. החלק [acme_ca] הוא מצב PKI פרטי: הוא מגדיר היכן נמצא השורש וכמה זמן תוקפים תעודות עלים מונפקות נשאר תקף.

הגדר תעודה משובצת לאתר אחד

זו הצורה המינימלית לאתר פרטי:

~~~טומל הקשב = "0.0.0.0:443"

[tls] unknown_sni = "דחה"

[TLS אוטומטי] מופעל = נכון cache_dir = "/var/lib/webship/acme"

[acme_ca] state_dir = "/var/lib/webship/acme-ca" leaf_validity_days = 90

[[אתרים]] domain = "service.internal.example" root = "/srv/service" certificate_mode = "מובנה"

[אתרים.פרוטוקולים] h1 = נכון h2 = נכון h3 = נכון ~~~

זהות השורש נוצרת באופן עצלני כאשר אתר משולב זקוק לה לראשונה. Webship שומר את מפתח השורש עם הרשאות מוגבלות בתיקיית המצב. לתעודת השורש יש חיי מדף של עשר שנים; חיי המדף של העלה נשלטים על ידי leaf_validity_days.

טפל בשני מיקומי האחסון כמצב ייצור:

  • ה-cache של ACME מחזיק זהויות אתר שמנוהלות באופן אוטומטי.
  • תיקיית המצב של ה-CA המוטמעת מחזיקה את הזהות הפרטית של השורש.
  • לחשבון השירות דרוש גישה, אך למשתמשי האפליקציה אין צורך בכך.
  • גיבויים חייבים לשמור על סודיות ועל הרשאות הקבצים.
  • הפקה, פיתוח ובדיקות צריכים להשתמש בשורשים נפרדים ובספריות נפרדות.

מחיקת ספריית השורש לא "מאפסת את TLS." היא יוצרת עוגן אמון חדש. לקוחות שמאמינים בשורש הישן יסרבו לאשרות שמונפקות על ידי ההחלפה עד שחנויות האמון שלהם יעודכנו.

אמון פרטי הוא מכוון

תעודות מה-CA המוטמע אינן מהימנות אוטומטית על ידי דפדפנים ציבוריים או מערכות הפעלה. הן הופכות למהימנות רק לאחר שהמפעיל מתקין את תעודת השורש המיוצאת Webship במאגר האמון של הלקוח.

זה הופך את מצב הטמעה להתאמה טובה ל:

  • מחשבים ניידים וטלפונים המנוהלים על ידי החברה ונרשמים באמצעות ניהול המכשיר;
  • תעבורה פנימית בין שירותים עם חבילת CA מפורשת;
  • מכשירים פרטיים וציים שוליים מבוקרים;
  • סביבות פיתוח ובדיקה שחייבות להפעיל התנהגות TLS אמיתית;
  • רשתות מנותקות שאינן יכולות להסתמך על רשות תעודה ציבורית.

זו לא הדרך הנכונה עבור אתר ציבורי רגיל שבו המבקרים משתמשים בדפדפנים לא מנוהלים. השתמש בהנפקה ציבורית לפי אתר עבור שם ציבורי מדויק, הנפקת צי עבור קבוצות תת-דומיין ציבוריות גדולות, משותפת רק עבור פריסה מכוונת של legacy מרובה-SAN, או קבצים ידניים מ-PKI שכבר מהימן.

הפץ רק את תעודת השורש ללקוחות. אל תפיץ לעולם את מפתח השורש הפרטי. החזקת המפתח הזה נותנת למחזיק בו סמכות להנפיק זהויות שהלקוחות הרשומים סומכים עליהן.

תעודות ציבוריות ופרטיות יכולות להתקיים יחד

Webship 1.4.0 יכול לערבב אסטרטגיות תעודה על אותו מאזין:

~~~טומל הקשב = "0.0.0.0:443"

[tls] unknown_sni = "דחה"

[TLS אוטומטי] מופעל = נכון directory_url = "https://acme-v02.api.letsencrypt.org/directory" cache_dir = "/var/lib/webship/acme" contacts = ["mailto:ops@example.com"] לקבל_את_תנאי_השירות = אמת

[acme_ca] state_dir = "/var/lib/webship/acme-ca" leaf_validity_days = 90

[[אתרים]] דומיין = "www.example.com" root = "/srv/public" certificate_mode = "לפי_אתר"

[[אתרים]] דומיין = "control.internal.example" root = "/srv/control" certificate_mode = "מובנה"

[[אתרים]] domain = "payments.example.com" root = "/srv/payments"

[אתרים.tls] cert = "/etc/webship/payments-fullchain.pem" key = "/etc/webship/payments-private-key.pem" ~~~

כאן, www.example.com מקבל את תעודת ה-ACME הציבורית שלו. control.internal.example מקבל תעודה פרטית מה-CA המובנה. payments.example.com נשאר תחת ה-PKI החיצוני של המפעיל מכיוון שהקבצים המפורשים שלו מקבלים עדיפות.

ספריית ACME הציבורית מתעלמת מאתרים מוטמעים. השורש המוטמע לעולם לא חותם על האתר הציבורי. האתר הידני לעולם לא נרשם בשקט לאף אחד מתהליכי העבודה האוטומטיים.

פותר תעודות אחד עבור H1, H2, H3, ו-WebTransport

בחירת התעודה מתרחשת במהלך הידוק ה-TLS, לפני שקיים בקשת HTTP. Webship משתמש בשם השרת ב-ClientHello כדי לבחור את זהות האתר ואז מנהל משא ומתן על פרוטוקול היישום.

  • HTTP/1.1 ו-HTTP/2 משתמשים ב-TLS מעל TCP.
  • HTTP/3 ו-WebTransport משתמשים ב-TLS בתוך QUIC מעל UDP.
  • זהות אתר חוקית אחת יכולה לשרת כל פרוטוקול מופעל.
  • HTTP/3 דורש גם נגישות UDP; H1 ו-H2 משתמשים במסלול TCP.
  • Alt-Svc יכול לפרסם H3 תוך שמירה על חזרה ל-TCP.

TCP, TLS ו-QUIC משתמשים באותו מודל זהות המודע לאתר. שמות מדויקים מקבלים עדיפות, התו הפונקציונלי הארוך ביותר מנצח כאשר תעודות ג'וקר מוגדרות, ושמות SNI לא ידועים יכולים להיעצר במקום לקבל תעודת ברירת מחדל בלתי קשורה.

השתמש ב-unknown_sni = "reject" במאזין רב-אתרים כאשר שם המארח הלא מוכר חייב להיכשל בצורה סגורה. בדוק שמות מוכרים, שמות לא מוכרים, ואת ההתנהגות הצפויה ללא SNI לפני פריסת הייצור.

סובב זהויות מוטמעות ללא פער שירות

Webship חושף את מצב התעודה ושינויים מבוקרים דרך שרת MCP המאומת שלו, המחובר ל-loopback:

  • webship.tls.get_status מדווח על מתאם התעודה הפעיל ומצב החידוש.
  • webship.tls.reissue_certificate מונפק מחדש מיד תעודה של אתר מנוהל אוטומטית רק כאשר האתר הזה משתמש במצב מוטמע.
  • webship.tls.reload טוען מחדש את מצב התעודה דרך מסלול TLS המוגן הרגיל.
  • webship.acme_ca.status מדווח אם ה-CA הפרטי נבחר, ספריית המצב שלו, משך חיי העלה, ספירת ההנפקות, ספירת הביטולים ודוגמת דומיינים אחרונה.
  • webship.sites.apply מוסיף או מסיר אתרים מול גרסת קונפיגורציה מקובעת.

לגבי השחרור מחדש מוטמע, Webship יוצר ומאמת את ההחלפה לפני שהוא מחליף אותה בשירות. הזהות התקפה הנוכחית ממשיכה לשרת עד שהזהות החדשה מוכנה. הזהות שפורשה נרשמת רק לאחר שההחלפה מותקנת.

פעולת ההנפקה המחודשת המיידית דוחה בכוונה אישורים ציבוריים per_site. חידוש ציבורי חייב להישאר בתוך מחזור החיים הציבורי של ACME במקום להתבלבל עם חתימה פרטית בתהליך. חברות במצב שיתופי גם מוקפאת מחדש כיוון ששינוי קבוצת multi-SAN מחדש בונה את גבול הזהות.

MCP הוא ממשק בקרה פריבילגי. שמרו עליו בלופבק, דרשו TLS וטוקן נושא חזק, השתמשו במנהרה מאומתת לניהול מרחוק, ובצעו ביקורת על כל שינוי.

גבולות כישלון שחשובים

מערכת תעודות מאובטחת חייבת להכשל בכיוון הנכון.

  • אתר משובץ שהוגדר מחדש לא מקבל את זהותו של אתר אחר בזמן שהנפקה בהמתנה.
  • החלפה לא חוקית אינה מותקנת מעל תעודה פעילה.
  • קבצי מדריך מפורשים מונעים בעלות אוטומטית על האתר הזה.
  • ניתן לדחות SNI בשם לא ידוע לפני ניתוב HTTP.
  • תעודת המוסמך המשובצת נותרת פרטית ואין לה נקודת הרשמה מרחוק.
  • זהויות ציבוריות ומוטמעות משתמשות במסלולי מטמון נפרדים בתוך מצב ה-TLS האוטומטי.

אזהרה שה-CA המוטבע לא מאותחל פירושה ש-Webship לא הצליח להפעיל את ספריית המצב המוגדרת. תקן בעלות, הרשאות, התמדדות או זמינות אחסון לפני שליחת תעבורה לאתר הנפגע. אל תנסה לעקוף את השגיאה על ידי העתקת מפתח שורש מסביבת עבודה אחרת.

רשימת בדיקה לייצור

לפני הפעלת מצב מוטבע:

  1. זהה כל אוכלוסיית לקוחות שחייבת לסמוך על האתר.
  2. צור תהליך מבוקר לייצוא ולהתקנת תעודת השורש.
  3. השתמש במצב שורש נפרד לייצור, פיתוח ובדיקות.
  4. התמיד והגן על ספריית המצב של ה-CA המוטמע ומטמון ה-TLS האוטומטי.
  5. הרץ את Webship תחת חשבון שירות ייעודי עם גישה רק לחומר המפתח הנדרש.
  6. בחר certificate_mode בכל אתר שהגבול האמון שלו חייב להיות מפורש.
  7. הגדר ובדוק את מדיניות SNI-הלא-ידועה.
  8. אפשר H1, H2 ו-H3 במודע ואמת גם את מסלולי TCP וגם את UDP.
  9. תרגול הנפקה מחדש, הפעלה מחדש, גיבוי, שחזור, ואימות אמון לקוח מחוץ לייצור.
  10. הרץ webship --check-config לפני הפצה, ואז אמת את המנפיק, השמות, התוקף, השרשרת והפרוטוקולים שהוסכמו מלקוח אמיתי.

בחר בביטחון קודם, באוטומציה אחר כך

ה-CA המוטמע מבטל תלות בשירות תעודה חיצוני עבור תשתית פרטית. הוא אינו הופך שורש פרטי לאמיד באופן גלובלי, ואינו מבטל את האחריות של המפעיל ל-PKI שלו.

Webship מאוטומט יצירת מפתחות, חתימה, אימות, התקנה, רוטציה ובחירת תעודה ברמה של הפרוטוקול. המפעיל עדיין שומר על אחזקת שורש, הרשמת לקוחות, הפרדת סביבות, גיבוי, שחזור וההחלטה להשתמש במסלול אמון ציבורי או פרטי.

ההפרדה הזו היא התכונה. שרת עצמאי יכול לאוטומט אישור TLS פרטי מבלי להעמיד פנים שהוא רשות אישור ציבורית — ואתרים ציבוריים עדיין יכולים להשתמש בהנפקה אמינה לדפדפן לפי אתר או לפי צי באותו התהליך.

קרא את התיעוד בגרסה Webship 1.4.0 לפני ההשקה. RFC 5280 מגדיר פרופילי תעודה ואימות, RFC 6066 מגדיר איתות שם שרת ב-TLS, RFC 8446 מגדיר TLS 1.3, RFC 8555 מגדיר ACME ציבורי, ו-RFC 9525 מגדיר אימות זהות שירות.