אישורים למחשב המקומי (localhost)

עדכון אחרון: | הצגת כל התיעוד

לפעמים יש אנשים המעוניינים לקבל אישור לשם המארח „localhost”, או לשימוש בפיתוח מקומי או להפצה עם יישומון טבעי שדורש תקשורת לשרת אינטרנט. ל־Let’s Encrypt אין אפשרות לספק אישורים ל־„localhost” כיוון שלאף אחד אין בעלות ייחודית עליו ואין לו מקור בשם תחום עליון כגון „‎.com” או „‎.net”. אפשרי להקים שם תחום משלך שבמקרה מתפענח לכתובת 127.0.0.1 ולקבל אישור עבורו באמצעות אתגר ה־DNS. עם זאת, באופן כללי מדובר ברעיון די גרוע וישנן אפשרויות מוצלחות יותר.

לפיתוח מקומי

אם כרגע עיסוקך הוא פיתוח של יישום רשת, נוח מאוד להריץ שרת אינטרנט מקומי כגון Apache או Nginx ולגשת אליו דרך http://localhost:8000/‎ בדפדפן שלך. עם זאת, דפדפנים מתנהגים בדרכים מעט שונות בדפי HTTP לעומת HTTPS. ההבדל העיקרי: בעמוד HTTPS, כל בקשה שהיא לטעינת JavaScript מכתובת HTTP תיחסם. לכן אם מזדמן לך לפתח באופן מקומי באמצעות HTTP, ייתכן שתגית script שעובדת מצוין על מחשב הפיתוח שלך, לפתע תפסיק לעבוד לאחר הטמעה לאתר הפעילות המלאה שלך ב־HTTPS. כדי לאתר תקלות שכאלה, מומלץ להגדיר HTTPS בשרת המקומי שלך. עם זאת, זה קצת מעצבן לראות אזהרות אישורים כל הזמן. איך משיגים מנעול ירוק לגישה מקומית?

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

ליישומים טבעיים שמשוחחים עם יישומוני רשת

לעתים מפתחים מעוניינים להציע יישום טבעי שניתן להוריד ולהשתמש בו לצד אתר כדי להציע תכונות נוספות. כמו למשל, יישומי שולחן העבודה של Dropbox ושל Spotify מנסים לאתר קבצים במכונה שלך, מה שליישומון דרך הדפדפן אסור לבצע. אחת הגישות הנפוצות ליישומים הטבעיים האלה היא להציע שירות מקוון על גבי localhost ולתכנן כך שהיישומון המקוון ישלח אליו בקשות דרך XMLHTTPRequest (XHR) או דרך WebSockets. היישומון המקוון כמעט תמיד משתמש ב־HTTPS, מה שאומר שהדפדפנים ימנעו ממנו לבצע בקשות XHR או WebSockets לכתובות בלתי מאובטחות. מצב כזה נקרא חסימת תוכן מעורב. כדי לתקשר עם היישומון המקוון, היישום הטבעי יצטרך לספק שירות רשת מאובטח.

למרבה המזל, דפדפנים מודרניים מתייחסים אל http://127.0.0.1:8000/‎ כאל כתובת בעלת „סבירות גבוהה למהימנות” כיוון שהיא מפנה לכתובת לולאה פנימית. מובטח לחלוטין שתקשורת שנשלחת אל 127.0.0.1 אינה עוזבת את המכונה שלך ולכן נחשבת אוטומטית כמאובטחת מפני יירוט דרך הרשת. משמעות הדבר היא שהיישום שלך הוא HTTPS וההיצע שלך הוא שירות מקוון ליישום טבעי על גבי 127.0.0.1, שני אלו יכולים לתקשר בשמחה דרך XHR. לרוע המזל, localhost עדיין לא זוכה להתייחסות שכזאת. כמו כן, WebSockets לא מקבלים טיפול שכזה כלפי אף שם שהוא.

אולי יפתה אותך לעקוף את המגבלות האלו על ידי הגדרת שם מתחם ב־DNS הגלובלי שבמקרה מתפענח ל־127.0.0.1 (למשל: localhost.example.com), קבלת אישור עבור שם התחום הזה, שליחת האישור הזה והמפתח הפרטי התואם עם היישום שלך ולהנחות את היישומון המקוון שלך לתקשר עם https://localhost.example.com:8000/‎ במקום עם http://127.0.0.1:8000/‎. לא עושים דבר כזה. זה יכול לסכן אותך והאישור שלך עלול להישלל.

הגשת שם תחום במקום כתובת IP מאפשרת לתוקף לבצע התקפת אדם בתווך (MitM) על החיפוש ב־DNS ולהזריק תגובה שמצביעה לכתובת IP אחרת. התוסף יכול להתחזות ליישום המקומי ולשלוח תגובות מזויפות ליישום המקוון, שעשויות לפגוע בחשבון שלך מצד היישומון המקוון, בהתאם לאופן התכנון שלו.

הצלחת מתקפת אדם בתווך (MitM) במקרה שכזה אפשרית כיוון שכדי שהמתקפה תצליח, היה עליך לשלוח את המפתח הפרטי לאישור שלך יחד עם היישום הטבעי שלך. משמעות הדבר היא שכל מי שמוריד את היישום הטבעי שלך מקבל עותק של המפתח הפרטי, לרבות התוקף. מצב שכזה נחשב לפגיעה במפתח הפרטי שלך ורשות האישורים (CA) שלך נדרשת לשלול את האישור שלך אם הם מודעים לכך. למגוון רחב של יישומים טבעיים נשלל האישור עקב שליחת המפתח הפרטי שלהם.

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

כמו כן, יש לשים לב שחשיפת שירות מקוון שמציע מנשקי API טבעיים עם הרשאות ניהוליות מסוכן מטבעו, כיוון שאתרים שלא תכננת להרשות את הגישה שלהם בכל זאת יכולים לגשת אליהם. אם התחלת לצעוד בדרך שכזו, כדאי לקרוא על Cross-Origin Resource Sharing (שיתוף משאבים ממקורות צולבים), להשתמש ב־Access-Control-Allow-Origin, ולוודא שנעשה גם שימוש במפענח HTTP שמגן על הזיכרון (memory-safe) כיוון שאפילו מקורות שלא קיבלו הרשאה לגשת יכולים לשלוח בקשות טרום המראה (preflight), שעלולות לנצל חולשות במפענח שלך.

יצירה ומתן אמון באישורים משלך

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

הדרך הפשוטה ביותר לייצר מפתח פרטי ואישור בחתימה עצמית עבור localhost היא פקודת ה־openssl הבאה:

openssl req -x509 -out localhost.crt -keyout localhost.key \
  -newkey rsa:2048 -nodes -sha256 \
  -subj '/CN=localhost' -extensions EXT -config <( \
   printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

לאחר מכן אפשר להגדיר את השרת המקומי שלך עם localhost.crt ועם localhost.key, ולהתקין את localhost.crt ברשימת האישורים העליונים המהימנים שלך.

אם מעניין אותך להעניק ממד מוחשי לאישור שלך למטרות פיתוח, ניתן להשתמש ב־minica כדי לייצר אישור עליון מקומי משלך, ולהנפיק אישורי יישות קצה (ידועים בשם עלה) שנחתמו על ידה. לאחר מכן יהיה עליך לייבא את האישור העליון במקום את אישור יישות הקצה שנחתם עצמית.

ניתן גם לבחור להשתמש בשם תחום עם הפרדה בנקודות, כגון www.localhost, על ידי הוספתו ל־‎/etc/hosts ככינוי ל־127.0.0.1. זה משנה במעט את איך שהדפדפנים מטפלים באחסון עוגיות.