Diperbarui 1 bulan yang lalu
כל חיבור TCP מתחיל עם בעיה: שני מכשירים שמעולם לא הכירו זה את זה צריכים להסכים על נקודת התחלה משותפת לפני שיוכלו לתקשר באופן אמין. האינטרנט שביניהם הוא עוין — מנות נתונים אובדות, מוכפלות, מסתדרות מחדש, מתעכבות. איך בונים אמון בתווך שאינו מהימן?
לחיצת היד התלת-שלבית.
למה שלושה שלבים
TCP מבטיח שהנתונים מגיעים בסדר, ללא פערים, עם זיהוי שגיאות. כדי לקיים הבטחה זו, TCP מקצה מספר רצף לכל בייט. כאשר מנות מגיעות בסדר שגוי, הצד המקבל מסדר אותן מחדש. כאשר מנות נעלמות, הצד המקבל יודע בדיוק אילו בייטים לבקש שוב.
אך מספרי הרצף עובדים רק אם שני הצדדים מסכימים היכן להתחיל לספור. אם הלקוח חושב שהרצף מתחיל ב-100 והשרת חושב שהוא מתחיל ב-5000, הם לעולם לא יסכימו על מה שהתקבל.
לחיצת היד מסנכרנת נקודות התחלה אלו. שלושה חילופים הוא המינימום — לא לפי מוסכמה, אלא לפי לוגיקה. שני הצדדים חייבים לשלוח מספר התחלה וגם לאשר שקיבלו את המספר של הצד השני. לא ניתן לעשות זאת בשני שלבים.
שלושת השלבים
שלב 1: SYN (סנכרון)
הלקוח שולח מנה עם דגל SYN מוגדר: "אני רוצה להתחבר. מספרי הרצף שלי יתחילו ב-X."
מספר ההתחלה (Initial Sequence Number, או ISN) נבחר באופן אקראי. למה? מנות ישנות מחיבורים קודמים עשויות עדיין לצוף באינטרנט. אם כל חיבור היה מתחיל מאפס, מנה מעוכבת מחיבור ישן עלולה להתבלבל עם נתונים בחיבור החדש. נקודות התחלה אקראיות הופכות את ההתנגשות הזאת לבלתי-אפשרית כמעט.
מנת SYN כוללת גם את גודל המקטע המרבי של הלקוח וגודל החלון (כמה נתונים הוא יכול לאחסן בחוצץ).
שלב 2: SYN-ACK (סנכרון-אישור)
השרת מגיב עם מנה שעושה שני דברים בבת אחת:
- מאשר את ה-SYN של הלקוח: "קיבלתי את מספר ההתחלה שלך X. אני מוכן ל-X+1."
- שולח SYN משלו: "מספרי הרצף שלי יתחילו ב-Y."
שילוב אלה במנה אחת הוא הסיבה שזוהי לחיצת יד תלת-שלבית ולא ארבע-שלבית. השרת יכול לשלוח מנות אישור וסנכרון נפרדות, אך מיזוגן חוסך נסיעה הלוך-ושוב.
שלב 3: ACK (אישור)
הלקוח משלים את לחיצת היד על ידי אישור מספר הרצף של השרת: "קיבלתי את מספר ההתחלה שלך Y. אני מוכן ל-Y+1."
עכשיו שני הצדדים מסונכרנים. העברת הנתונים יכולה להתחיל.
כך נראית לחיצת היד
מספר האישור הוא תמיד "מספר הרצף שלך פלוס אחד" — כלומר "קיבלתי הכל עד לנקודה זו, שלח את הבייט הבא."
כשלחיצות היד נכשלות
אף אחד לא מאזין. אם אין יישום מקושר ליציאה המבוקשת, השרת שולח מנת RST (איפוס): "אין כאן כלום. לך משכאן." ניסיון החיבור מסתיים מיידית.
ה-SYN אובד. הלקוח שולח SYN, אך הוא לעולם לא מגיע. לאחר פסק זמן, הלקוח מנסה שוב. מערכות מנסות כמה פעמים עם המתנות ארוכות יותר ויותר לפני שמוותרות. לכן פסקי זמן של חיבור יכולים לארוך 30 שניות ויותר — המערכת מתאזרת בסבלנות מול רשת לא אמינה.
חומת אש מפילה את המנה בשקט. מנקודת המבט של הלקוח, זה נראה זהה לאיבוד מנה רגיל. ה-SYN נבלע לתוך הריק. לא מגיעה תשובה. הלקוח ממתין, מנסה שוב, ממתין זמן רב יותר, מנסה שוב, ובסופו של דבר מוותר. חומות אש מסוימות שולחות מנות RST במקום זאת, מה שלפחות גורם לכישלון מהיר.
הלקוח נעלם באמצע לחיצת היד. השרת מקבל SYN, מגיב עם SYN-ACK, מחכה ל-ACK. אך הלקוח קרס או איבד את הקישוריות. השרת יושב עם משאבים מוקצים לחיבור שלעולם לא יושלם. מנגנוני keepalive של TCP בסופו של דבר מנקים חיבורים חצי-פתוחים אלה, אך זה לוקח זמן.
מתקפת SYN Flood
ללחיצת היד יש פגיעות, ותוקפים מנצלים אותה ללא רחמים.
כאשר שרת מקבל SYN, הוא מקצה זיכרון כדי לעקוב אחר החיבור הממתין — שומר את מספר הרצף של הלקוח, היציאה ומצב נוסף. הוא עושה זאת לפני שלחיצת היד הושלמה, מפני שהוא צריך לזכור את פרטי הלקוח כדי לשלוח את ה-SYN-ACK.
תוקף שולח אלפי מנות SYN עם כתובות מקור מזויפות. השרת מגיב נאמנה לכל אחת מהן עם SYN-ACK, מקצה משאבים לחיבורים שלעולם לא יושלמו. האישורים טסים לכתובות מזויפות שאינן קיימות או שלא ביקשו זאת. השרת מחכה ל-ACK אחרון שלעולם לא יגיע.
תור החיבורים של השרת מתמלא. משתמשים לגיטימיים מנסים להתחבר — אין מקום. השרת מוצף לא על ידי עומס תעבורה, אלא על ידי נימוסיותו שלו — הוא מקצה משאבים לכל זר שדופק בדלת.
ההגנה היא פיקחית. SYN cookies מאפשרים לשרת להימנע מאחסון כל מידע עד שה-ACK האחרון מגיע. במקום לזכור את פרטי הלקוח, השרת מקודד אותם בצורה קריפטוגרפית במספר הרצף שהוא שולח בחזרה. כאשר הלקוח מחזיר את ה-ACK, השרת מפענח את פרמטרי החיבור המקוריים מתוך האישור. אם ה-ACK לא מגיע לעולם, השרת לא הפסיד כלום — הוא מעולם לא הקצה משאבים מלכתחילה.
השרת מפסיק לזכור מבקרים ובמקום זאת כותב את כרטיס הכניסה על מצחם. רק אלה שחוזרים עם כרטיס תקף נכנסים.
שאלות נפוצות על לחיצת היד התלת-שלבית של TCP
מדוע TCP לא יכול להסתפק בשני שלבים במקום שלושה?
לאחר SYN ו-SYN-ACK, לשרת אין הוכחה שהלקוח קיבל את מספר הרצף שלו. הוא שלח מידע לתוך הריק. השלב השלישי — ה-ACK של הלקוח — מאשר שמספר הרצף של השרת הגיע. בלעדיו, השרת היה מתחיל לשלוח נתונים ללקוח שעשוי שלא להיות מסונכרן.
מה קורה ללחיצת היד בחיבורים עם השהייה גבוהה?
כל שלב חייב לחצות את הרשת, כך שהשהייה גבוהה פירושה הקמת חיבור איטית. קישור לוויין עם זמן נסיעה הלוך-ושוב של 600ms לוקח כמעט שתי שניות עבור לחיצת היד בלבד — לפני שמועבר אפילו בייט אחד של נתונים. זו הסיבה שפרוטוקולים כמו QUIC משלבים הקמת חיבור עם הגדרת הצפנה, ומפחיתים את מספר הנסיעות הלוך-ושוב.
מדוע מספרי הרצף הם בני 32 סיביות?
מספר רצף של 32 סיביות סופר כארבעה מיליארד בייטים לפני שהוא "מתגלגל". לחיבורים איטיים, זה מספיק — מנות ישנות פגות הרבה לפני ה"גלגול". לחיבורים מהירים מאוד (10 Gbps ומעלה), TCP משתמש ב-PAWS (Protection Against Wrapped Sequences), שמוסיף חותמות זמן כדי להבחין בין מנות ישנות לחדשות בעלות אותו מספר רצף.
האם ניתן לראות את לחיצת היד התלת-שלבית מתרחשת?
כן. כלים כמו Wireshark לוכדים מנות רשת ומציגים כל שלב. תראו את דגל SYN על המנה הראשונה, SYN+ACK על השנייה, ACK על השלישית. זוהי אחת הדרכים הברורות ביותר להבין מה TCP באמת עושה ברמת הרשת.
Apakah halaman ini membantu?