רשתות ואינטרנט
TCP/IP ופורטים: איך שירותים מאזינים על המכונה שלך
פורט הוא דלת ממוספרת במכונה שלך. איך TCP ו-UDP משתמשים בפורטים, ואיך מפעילים, מוצאים ובודקים שרת מקומי על 127.0.0.1.
TLS 1.3 נותן ל-HTTPS סודיות, שלמות ואימות שרת. לחיצת היד, שרשראות תעודות, ומה המנעול בדפדפן לא מוכיח.
TLS (Transport Layer Security) הוא פרוטוקול שעוטף חיבור רשת בהצפנה. HTTPS הוא HTTP רגיל שנשלח דרך חיבור TLS. כשהדפדפן מציג מנעול, הוא עשה שלושה דברים. הוא הצפין את הנתונים. הוא בדק שאיש לא שינה את הנתונים בדרך. והוא בדק שהשרת הוכיח שהוא מחזיק בתעודה מהימנה עבור השם שהוקלד.
הנקודה השלישית היא זו שאנשים קוראים לא נכון. HTTPS אומר עם איזה שרת מדברים. הוא לא אומר כלום על השאלה אם השרת הזה מהימן, ישר או מנוהל היטב.
באיך HTTP עובד, בקשות ותגובות הן הודעות טקסט, ו-HTTP לא עושה כלום כדי להסתיר אותן. כל מכשיר בינך לבין השרת יכול לקרוא אותן: הראוטר הביתי, נקודת הגישה בבית הקפה, ספק האינטרנט והרשתות שבדרך.
צופה פסיבי יכול לקרוא טופס התחברות שנשלח ב-HTTP רגיל. תוקף פעיל בנתיב יכול לעשות יותר. הוא יכול לשנות דף לפני שהוא מגיע אליך, להכניס סקריפט או להחליף הורדה בקובץ ששונה. TLS תוכנן לעצור את שני האיומים. הוא גם נותן ללקוח דרך לבדוק מי עונה, דבר ש-HTTP רגיל אף פעם לא עושה.
הגרסה הנוכחית היא TLS 1.3, שמוגדרת ב-RFC 8446. TLS 1.0 ו-1.1 הוצאו משימוש, כפי ש-RFC 8996 מסביר, ו-TLS 1.2 עדיין פרוס באופן נרחב. גרסה 1.3 הסירה אפשרויות ישנות רבות, כך שיש פחות דרכים להגדיר את לחיצת היד בצורה גרועה.
TLS 1.3 נותן שלוש תכונות.
נתוני האפליקציה מוצפנים במפתחות סשן שרק שתי נקודות הקצה מחזיקות. צופה רואה טקסט מוצפן. הגודל והתזמון של התעבורה נשארים גלויים, אבל התוכן לא.
לחיצת יד מלאה של TLS 1.3 משתמשת בהחלפת מפתחות זמנית. שני הצדדים יוצרים ערכי מפתח זמניים לסשן ומשליכים אותם אחר כך. זה נותן forward secrecy: אם המפתח הפרטי של תעודת השרת דולף שנים מאוחר יותר, סשנים ישנים שהוקלטו אמורים להישאר בלתי קריאים. מפתח שדלף עדיין מאפשר לתוקף להתחזות לשרת מאותה נקודה והלאה, כך ש-forward secrecy מגן על העבר ולא על העתיד.
כל רשומה נושאת תג אימות של צופן AEAD, כמו AES-GCM או ChaCha20-Poly1305. TLS 1.3 מתיר רק צפנים מהסוג הזה. אם תוקף הופך ביט בדרך, בדיקת התג נכשלת והרשומה נדחית.
השרת מוכיח שהוא מחזיק במפתח הפרטי שתואם לתעודה שלו. התעודה קושרת את המפתח הציבורי הזה לשם כמו example.com. הלקוח בודק את התעודה ואת שרשרת האמון שמאחוריה, ואז בודק את השם. רוב ההמשך של המאמר עוסק בחלק הזה.
לחיצת היד קובעת מפתחות ומוכיחה זהות לפני שנתוני HTTP כלשהם עוברים. ב-TLS 1.3 לחיצת היד הרגילה לוקחת סבב אחד. השלבים הבאים הולכים בעקבות RFC 8446 במבט על.
הלקוח שלך שולח ClientHello. הוא מפרט את גרסאות ה-TLS וחבילות הצפנים שהוא תומך בהן, וכולל key share, הערך הציבורי הזמני של הלקוח להחלפת המפתחות. הוא גם נושא את server name indication (SNI), שם המארח שביקשת, כטקסט גלוי. שרתים שמארחים אתרים רבים צריכים את השם הזה כדי לבחור את התעודה הנכונה.
השרת בוחר גרסה וחבילת צפנים ושולח key share משלו. כל צד משלב את הערך הפרטי שלו עם הערך הציבורי של הצד השני וגוזר את אותו סוד משותף. צופה שראה את שני הערכים הציבוריים לא יכול לחשב את הסוד הזה. מכאן והלאה לחיצת היד מוצפנת.
השרת שולח את התעודה שלו. ב-TLS 1.2 התעודה הייתה גלויה ברשת. ב-TLS 1.3 היא עוברת בתוך החלק המוצפן של לחיצת היד.
אחר כך השרת שולח הודעת CertificateVerify, חתימה על תמליל לחיצת היד שנעשתה עם המפתח הפרטי של התעודה. זה מוכיח שהשרת מחזיק במפתח במהלך לחיצת היד הזאת. תעודה שהועתקה לבדה חסרת ערך לתוקף. הודעת Finished, MAC על התמליל, סוגרת את החלק של השרת.
הלקוח שלך בודק את שרשרת התעודות, את תאריכי התוקף, את השם שבתעודה מול המארח שביקשת, ואת חתימת ה-CertificateVerify. אם כל הבדיקות עוברות, הלקוח שולח הודעת Finished משלו, ונתוני האפליקציה יכולים לזרום.
אם בדיקה נכשלת, הלקוח עוצר. דפדפן מציג אזהרת תעודה, ו-curl יוצא עם שגיאה. ההודעות האלה הן החלק השימושי ביותר של TLS למתחילים, כי הן מציינות איזו בדיקה נכשלה.
תעודה היא מבנה X.509, ו-RFC 5280 מגדיר את הפרופיל שבשימוש באינטרנט. אלה השדות החשובים ביותר כאן.
| שדה | מה הוא אומר |
|---|---|
| Subject | הישות ששמה מופיע בתעודה. בתעודות web הוא חוזר לעיתים קרובות על שם המארח. |
| Subject Alternative Name (SAN) | השמות שהתעודה מכסה, כמו example.com או *.example.com. לקוחות מתאימים את המארח המבוקש מול הרשימה הזאת. |
| Issuer | רשות התעודות (CA) שחתמה על התעודה הזאת. |
| Validity | התאריכים notBefore ו-notAfter. מחוץ לחלון הזה התעודה לא תקפה. |
| Basic Constraints | האם התעודה הזאת רשאית לחתום על תעודות אחרות. תעודות CA מסומנות כך. |
לקוחות מודרניים מתעלמים מ-Common Name (CN) שב-Subject בבדיקות שם מארח ומשתמשים ברשימת ה-SAN. מי שמסתכל רק על ה-CN עלול לטעות בהערכת תעודה.
שרת כמעט אף פעם לא מציג תעודה שהלקוח יכול לאמת ישירות. בדרך כלל CA ביניים חותם על תעודת הקצה, שמכסה את שם המארח, ו-CA שורש חותם על ה-CA של הביניים. הלקוח סומך על קבוצת שורשים שמגיעה עם מערכת ההפעלה או עם הדפדפן.
הלקוח בונה נתיב מתעודת הקצה לשורש מהימן. בכל חוליה הוא מאמת את החתימה, בודק את תאריכי התוקף ומוודא שהמנפיק רשאי לחתום על תעודות. אחר כך הוא בודק את שם המארח. שתי הבדיקות חייבות לעבור.
כל שורש מהימן יכול, עקרונית, להנפיק תעודה לכל שם. האמון תלוי אפוא בנהלים של הרשויות שבמאגר. בגלל זה ספקים מסירים רשויות שמנפיקות תעודות באופן שגוי.
אפשר לבטל תעודה לפני שהיא פגה, למשל אחרי שהמפתח שלה נפרץ. לקוחות יכולים לבדוק ביטול דרך רשימות ביטול תעודות (CRLs) או OCSP, אבל הבדיקות האלה מתנהגות באופן לא אחיד. חיבור נקי לא מוכיח שתעודה מעולם לא בוטלה.
TLS מאמת את זהות השרת. הוא לא מעריך את ההתנהגות שלו. אתר פישינג יכול להשיג תעודה תקפה עבור דומיין דומה שבשליטתו. המנעול מראה אז שהחיבור מגיע למי שמחזיק במפתח של הדומיין הזה, ולא שהדומיין שייך לבנק שלך. כדאי לקרוא את שם המארח בשורת הכתובת לפני שסומכים על הדף. גם שרת עם תעודה תקינה יכול להיפרץ או להיות מנוהל גרוע.
TLS מסתיר תוכן, ולא כל עובדה על החיבור. כל מי שנמצא בנתיב עדיין רואה את כתובות ה-IP בכל קצה, את הפורט, את הגודל והתזמון המשוערים של התעבורה ואת שם השרת ב-ClientHello, כי SNI נשלח כטקסט גלוי. Encrypted Client Hello הוא מאמץ של IETF להסתיר את ה-SNI, אבל כדאי לבדוק עד כמה הוא פרוס לפני שמניחים שאתר משתמש בו. שאילתות DNS הן פרוטוקול נפרד וחושפות את השמות שמבוקשים, אלא אם משתמשים ב-DNS מוצפן.
TLS מגן על נתונים בזמן שהם עוברים בין שתי נקודות קצה. הוא לא מגן על נקודות הקצה. נוזקה במחשב שלך יכולה לקרוא נתונים מפוענחים, ותוסף דפדפן יכול לקרוא כל דף שנפתח. חברה יכולה גם להתקין שורש מהימן משלה על המחשב שלך ולפענח את תעבורת ה-HTTPS שלך דרך proxy לבדיקת תעבורה. הלקוח עובד אז בדיוק כפי שהוגדר, והחלטת האמון שייכת למי ששולט במאגר השורשים.
example.com הוא אחד השמות ש-IANA שומר לתיעוד ולדוגמאות. כל פקודה בהמשך מתחברת רק לדומיין example.com. המעבדה לא משנה כלום בשרת ולא צריכה חשבון. צריך טרמינל עם curl ו-openssl. פקודות ה-openssl הורצו עם OpenSSL 3.2.4.
הפלט אצלך יהיה שונה מהפלט שמופיע כאן. כתובות IP משתנות, תעודות מתחדשות ותאריכים מתקדמים.
curl -vI https://example.comהדגל -v מדפיס פרטי חיבור, והדגל -I שולח בקשת HEAD, שמבקשת כותרות בלבד. במחשב שבו השתמשנו למאמר הזה (Windows 11 עם Git Bash, curl 8.12.1, בהרצה ב-8 בנובמבר 2026), השורות הרלוונטיות נראו כך:
* Host example.com:443 was resolved.
* IPv4: 172.66.147.243, 104.20.23.154
* Connected to example.com (172.66.147.243) port 443
* using HTTP/1.x
> HEAD / HTTP/1.1
> Host: example.com
< HTTP/1.1 200 OKה-build הזה של curl משתמש ב-Schannel, ספריית ה-TLS של Windows, והפלט המפורט שלו שונה מזה של curl שנבנה עם OpenSSL. כאן curl לא הדפיס את גרסת ה-TLS, הצופן או שורות התעודה שהמעבדה מבקשת. ב-curl מבוסס OpenSSL מחפשים את השורה שמציינת את גרסת ה-TLS ואת הצופן, ואת בלוק התעודה עם subject, issuer ותאריך תפוגה. השלבים הבאים מקבלים את אותן עובדות מ-openssl.
200 OK אומר שהשרת ענה בתוך חיבור ה-TLS. הכותרות עוברות מוצפנות, ו-curl מפענח אותן מקומית.
openssl s_client -connect example.com:443 -servername example.com -brief </dev/nullפלט:
Connecting to 172.66.147.243
CONNECTION ESTABLISHED
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Peer certificate: CN=example.com
Hash used: SHA256
Signature type: ECDSA
Verification: OK
Server Temp Key: X25519, 253 bits
DONEקוראים שורה אחר שורה:
הדגל -servername מגדיר SNI. בלעדיו, שרת שמארח כמה אתרים עשוי להחזיר תעודת ברירת מחדל שלא תואמת לשם המבוקש. ההפניה </dev/null סוגרת את הקלט הסטנדרטי כדי שהפקודה תסתיים.
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -datesפלט:
subject=CN=example.com
issuer=C=US, O=SSL Corporation, CN=Cloudflare TLS Issuing ECC CA 3
notBefore=Sep 26 22:49:11 2026 GMT
notAfter=Dec 25 22:56:35 2026 GMTה-subject מחזיק רק CN. ה-issuer הוא CA ביניים ולא שורש. חלון התוקף היה פתוח ביום המעבדה והוא נסגר ב-25 בדצמבר 2026. כדאי להשוות את notAfter לתאריך במערכת שלך, כי תעודה שפג תוקפה נכשלת גם כשהשרשרת שלה תקינה.
ה-subject לא מפרט את השמות המכוסים, ולכן מבקשים את רשימת ה-SAN:
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltNameפלט:
X509v3 Subject Alternative Name:
DNS:example.com, DNS:*.example.comה-wildcard מכסה שמות כמו www.example.com. הלקוח משווה את הרשימה הזאת למארח שב-URL.
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null 2>/dev/null | grep -E '^ *[0-9] s:|^ *i:'פלט:
0 s:CN=example.com
i:C=US, O=SSL Corporation, CN=Cloudflare TLS Issuing ECC CA 3
1 s:C=US, O=SSL Corporation, CN=Cloudflare TLS Issuing ECC CA 3
i:C=US, O=SSL Corporation, CN=SSL.com TLS Transit ECC CA R2
2 s:C=US, O=SSL Corporation, CN=SSL.com TLS Transit ECC CA R2
i:C=US, O=SSL Corporation, CN=SSL.com TLS ECC Root CA 2022
3 s:C=US, O=SSL Corporation, CN=SSL.com TLS ECC Root CA 2022
i:C=GB, ST=Greater Manchester, L=Salford, O=Comodo CA Limited, CN=AAA Certificate Servicesכל שורת s: היא subject וכל שורת i: היא ה-issuer שלו. רשומה 0 היא תעודת הקצה, וכל רשומה מונפקת על ידי זו שאחריה. תעודות יכולות לעבור חתימה צולבת, כך ששרשרת יכולה להגיע לשורש ביותר מנתיב אחד. הלקוח צריך נתיב תקף אחד שמסתיים בשורש שבמאגר שלו.
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | grep 'Verify return code'פלט:
Verify return code: 0 (ok)אפס אומר שמאגר האמון של ה-build הזה של openssl קיבל את השרשרת. ערכים אחרים מציינים כשל מסוים, כמו תעודה שפג תוקפה.
openssl s_client -connect example.com:443 -servername example.com -verify_hostname example.org -brief </dev/nullפלט, מקוצר:
depth=0 CN=example.com
verify error:num=62:hostname mismatch
CONNECTION ESTABLISHED
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Peer certificate: CN=example.com
Verification error: hostname mismatchהפקודה עדיין מתחברת רק לדומיין example.com. הדגל -verify_hostname מבקש מ-openssl לבדוק את התעודה מול example.org, שהתעודה לא מכסה. דפדפן מציג כשל מאותו סוג. הבדיקה הזאת היא מה שמונע משרת עם תעודה תקפה לדומיין אחד להיראות כדומיין אחר.
בחיבור סוכם על TLS 1.3, והלקוח קיבל שרשרת עבור example.com ודחה את אותה תעודה עבור example.org. אף אחת מהתוצאות לא אומרת אם החברה שמאחורי example.com מהימנה. המעבדה מראה שהלקוח שלך הגיע למי שמחזיק במפתח של example.com, ותו לא.
-k או --insecure ל-curl כדי להעלים שגיאה. זה מכבה את הבדיקות שתוארו כאן. משתמשים בזה רק מול שרת בדיקה חד־פעמי, ולעולם לא עם פרטי התחברות אמיתיים.verify=False בלקוח HTTP של Python. הנתונים עדיין מוצפנים, אבל למי שענה.קוראים את סעיפי הסקירה ולחיצת היד ב-RFC 8446, ואז עוברים על RFC 5280 כדי להכיר את שדות התעודה. קוראים את המדריך של Mozilla ל-TLS בצד השרת ומריצים בדיקת קונפיגורציה מול שרת שבניהולך.
המאמר הבא בסדרה עוסק במפתחות ציבוריים ופרטיים, המתמטיקה שמאחורי התעודה. אם שלב חיפוש השם חדש, כדאי לקרוא קודם את מה זה DNS?, כי התוצאה שלו קובעת לאיזו כתובת לחיצת היד מגיעה.
רשתות ואינטרנט
פורט הוא דלת ממוספרת במכונה שלך. איך TCP ו-UDP משתמשים בפורטים, ואיך מפעילים, מוצאים ובודקים שרת מקומי על 127.0.0.1.
רשתות ואינטרנט
קריאה של חילופי HTTP אמיתיים שורה אחר שורה: מתודות, כתובות URL, כותרות, מחלקות של קודי סטטוס ועוגיות, עם בדיקות curl מול שרת מקומי.
רשתות ואינטרנט
איך DNS הופך שמות לכתובות: resolvers, שרתים סמכותיים, מטמון TTL, הרשומות A, AAAA, CNAME, MX ו-TXT, ובדיקה בטוחה.