תהליך החיבור ב-HTTP2\TLS 1.3

הסבר פשוט ומוחשי, עם wireshark על פרוטוקול https ותהליך לחיצת היד.

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

אבל, יש מהפיכה סמויה שמתרחשת מתחת לכפות רגלינו והיא הופעת ה-HTTP3 שמשתמש בשיטה אחרת ל-handhsake ובפרוטוקול שנקרא QUIC. בפוסט הבא אני אכתוב עליו. הפוסט הזה עוסק ב-HTTP2 TLS 1.3 שנכון לזמן כתיבת שורות אלו הוא הפרוטוקול הנפוץ ביותר.

כאשר אני מקליד כתובת אינטרנט בשרת שלי, למשל example.com, ישנו ניסיון חיבור ב-HTTPS, מה קורה לפני שאני בכלל מקבל תגובה מהשרת או אפילו רואה את הבקשה בכלי המפתחים? יש סדרה של פעולות שנקראות ״לחיצת יד קריפטוגרפית״ שאמורות לבסס אמון בין הקליינט (שזה הדפדפן) לשרת (שזה לצורך העניין האתר). הפעולות האלו לא נראות בכלי המפתחים. אנו מבצעים לחיצת יד באמצעות מפתח א-סימטרי והמטרה היא להגיע למצב שבו יש לנו מפתח הצפנה סימטרי. אם אין לכם מושג מה ההבדל בינהם – פה יש פוסטים פשוטים שכתבתי המסבירים על הצפנה סימטרית וא-סימטרית.

הפעלת wireshark

אז בואו ונפעיל wireshark. מדובר בתוכנה קטנה ופשוטה לבדיקת רשת וממש כיף לעבוד איתה. היא פשוטה וקלה – כתבתי עליה פה. הבעיה היא שאם אנו משתמשים בתקשורת מוצפנת, היא לא תצליח לפענח את התקשורת. עבור זה, אנחנו צריכים להורות לדפדפן שלנו למסור את מפתחות ההצפנה הסימטריים. כדי לעשות כן, אנו צריכים לפתוח את הטרמינל (בלינוקס או במק) או את ה-powershell בחלונות.

במקרה הזה יותר קל לעבוד עם כרום אז אני ממליץ לעבוד איתו . כדאי לשם הדוגמה לכבות את QUIC כדי לוודא שהדפדפן מתחבר בפרוטוקול http2 ולא בפרוטוקול http3\QUIC יש להכנס אל chrome://flags ואז לכבות את Experimental QUIC protocol ואז יש להקפיד לסגור את כל החלונות של הכרום. כולם. בלי יוצא מהכלל.

דף הגדרות של כרום עם Experimental QUIC protocol במצב disable.

במק יש להקליד את הפקודה:

export SSLKEYLOGFILE=~/Documents/sslkeys.log && open -na "Google Chrome" --args --incognito

ובחלונות

set SSLKEYLOGFILE=%USERPROFILE%\Documents\sslkeys.log
start chrome --incognito

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

עכשיו לחגיגה! נפתח את wireshark. נלך להגדרות ומשם לפרוטוקולים ואז נגלול ברשימה הארוכה ונגיע ל-TLS. נכניס את כתובת ה-sslkeys.log שלנו.

מסך הגדרות של wireshark שבו ב-Pre Master secret log filename יש ~/Documents/sslkeys.log

עכשיו אנחנו יכולים לראות תקשורת מאובטחת. נפתח כלי מפתחים באינקוגניטו, נתחיל את ההקלטה ב-wireshark ונקליד example.com.

האתר הזה עובד עם כמה כתובות IP. אז עדיף להסתכל בכלי המפתחים את ה ip שאליו ניגשנו. רואים את זה ב-network:

תמונה מתוך כלי המפתחים, בו רואים שכתובת ה-IP של example.com היא 23.192.228.80

במקרה הזה, כתובת ה-IP של example.com היא 23.192.228.80. נסגור את ההקלטה ונכניס בפילטר את:

ip.addr == 23.192.228.80 && tls

נוכל לראות את הבקשות!

ניתוח הבקשות לפי הסדר

הבקשה הראשונה מהקליינט לשרת – Client Hello:

הקליינט שלנו שולח "שלום" לשרת. הוא שולח מידע חשוב ואנו נראה את זה ב-Transport Layer Security. המידע החשוב כולל גרסאות TLS נתמכות (1.3,1.2 ו-1.1), רשימת צופנים אפשריים. הנה למשל רשימת הצפנים שאני מקבל:

Cipher Suites (16 suites)
    Cipher Suite: Reserved (GREASE) (0x9a9a)
    Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
    Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
    Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
    Cipher Suite: TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9)
    Cipher Suite: TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
    Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
    Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
    Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
    Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)

יש גם מספר רנדומלי שמשתמשים בו אחר כך:

Random: b7e8782f31b8a9f57d5f9fed90296c3e33e8cddeaf285edb24aa2db16360c6c3

בתקן TLS 1.3 גם הקליינט מציע את המפתח הפומבי שלו.

השלב השני – Server Hello:

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

בחלק הזה הוא גם מציע מפתח פומבי משלו – בתקן TLS 1.3

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

השלב השלישי: מפתח קריפטוגרפי נשלח לדפדפן:

זה שלב חשוב שמחולק לשניים. בחלק הראשון יש את ה-certficiation המפתח הקריפטוגרפי הפומבי נשלח לדפדפן על ידי השרת. אפשר ממש לראות אותו ובמקרה שלנו הערך שלו הוא:

subjectPublicKey: 049a4897842d616c08c96a14a0c83880e600c087fa99570e1b00e2d8879257e708fb3c5eb0d3842837c124118ed3207174bd938f4e0903ce023bb0e46673cfafee

אפשר לראות אותו גם בדפדפן! אם תכנסו ל example.com ותלחצו על שם המתחם ותבקשו לראות את התעודה ותדלגו אל החלק של המפתח הפומבי, תוכלו לראות את אותו מספר בדיוק. כאמור wireshark מראה מה הדפדפן רואה.

יש גם מידע על מי שהוציא את התעודה הזו – Digicert. והמידע הזה חשוב מאד לחתימה.

החלק השני שיש בפקטה הוא יותר חשוב כי הוא החתימה. כל אחד יכול לשלוח מפתח פומבי. איך אני יודע בדיוק שהמפתח הפומבי הוא של example.com ? ולא איזה מיקי זוהר שעומד באמצע ומשחק אותה צנזור דה לה שמאטע כדי לראות אם אני לא עושה דברים שאסור לי? בדיוק בשביל זה יש את הקסם האמיתי – אני מקבל חתימה של כל תקציר ההודעות. הדפדפן יכול לפתוח אותו עם המפתח הציבורי ולוודא שבאמת החתימה הזו נעשתה על ידי example.com והמפתח הפומבי הזה הוא באמת של example.com.

אבל איך אני יודע שבאמת זה example.com האמיתי ולא מישהו שמתחזה? כי באופן עקרוני, השרת יכול להצהיר על עצמו כ example.com אבל הוא יכול להיות מזויף. למשל, אם מיקי זוהר הערמומי רוצה לצנזר, הוא יכול להקים אתר מתחזה ל example.com ולעמוד באמצע ולשכנע את ספקית האינטרנט שלי (עם נבוט) לשלוח את התנועה ל״יעני example.com״ שיש לו תעודה והכל. בדיוק בשביל זה יש לנו בפקטה הראשונה את החתימה של ה-CA שבמקרה הזה הוא Digicert. מה שיש שם זה את התעודה של example.com שנחתמה עם המפתח הפרטי של Digicert. הדפדפן לוקח את התעודה, את המפתח הפרטי ואת התעודה ומוודא שהחתימה תקינה.

החתימה של Digicert מופיעה כמובן במידע של WireShark.

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

מפתח פומבי שמאפשר ללקוח

  1. לאמת את חתימת התעודה (Certificate) – כלומר, לבדוק שהתעודה נחתמה ע"י ה-CA (כמו DigiCert).
  2. לאמת את חתימת ה-Certificate Verify – כלומר, שהשרת שמחזיק במפתח הפרטי תואם לתעודה.

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

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

שלב אחרון: הקליינט שולח Finished

השלב האחרון הוא השלב שבו הקליינט שולח בקשה אחרונה של Finished. בבקשה הזו יש לנו ערך שנקרא Verify Data ומחושב על ידי המפתח הסימטרי. השרת יכול לוודא שכל התהליך הזה תקיןוששני הצדדים מחזיקים במפתח הנכון. השרת מקבל את ההודעה, מחשב בעצמו את ערך ה-Verify Data ומשווה למה שהלקוח שלח. אם הכל תקין. זה השלב שבו לחיצת היד מסתיימת. יש לנו מפתח סימטרי שחושב על ידי דיפי הלמן ואפשר תקשורת.

יש מפתח סימטרי! יש הצפנה!

במקרה שלנו, המפתח הסימטרי עובר ל-Wireshark והוא ישתמש בו על מנת לפתוח את התעבורה. כך שהשלב שבו דף ה-HTML עובר לדפדפן- נצפה בהחלט על ידי wireshark ולא נראה ג׳יבריש.

אפשר לראות עד כמה זה מעניין והתהליך מורכב. התשתית של האינטרנט היא מורכבת מאד והפרעות או בעיות בתהליך ההצפנה, במיוחד על ידי צנזורים, יכולים לשבש אותה. כמתכנתים ואנשים טכניים, מעבר לכך שמדובר בנושא מעניין, הבנה שלו יכולה לחסוך המון זמן בטיפול בתקלות תקשורת כמו handshake failure, mismatched cipher suite, או בעיות תעודות) ולהבין מה עומד מאחורי התקנים והמילים המוזרות.

בפוסט הבא, נדבר ונראה את העולם המופלא של TLS3\QUIC.

פינת הניטפיקרים/הבהרות:

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

לא הסברתי פה על דיפי הלמן

עשיתי כמה קיצורי דרך 🙂

פוסטים נוספים שכדאי לקרוא

רשת האינטרנט

איך בונים custom GPT משלכם?

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

בניית אתרי אינטרנט

לאחסן שרת בבית? זה לגמרי אפשרי

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

פתרונות ומאמרים על פיתוח אינטרנט

Retry decorator בפייתון

לא מזמן יצא לי לכתוב קוד בפייתון. הקוד משתמש ב-API של openAI ולפעמים ה-API הזה קצת מפשל. הוא מחזיר לי שגיאה ואומר שהגזמתי עם הקריאות,

גלילה לראש העמוד