דילוג לתוכן
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after a top-up of $10 or more. Until Nov 30.

How it works

TCP/IP ופורטים: איך שירותים מאזינים על המכונה שלך

פורט הוא דלת ממוספרת במכונה שלך. איך TCP ו-UDP משתמשים בפורטים, ואיך מפעילים, מוצאים ובודקים שרת מקומי על 127.0.0.1.

מתחילים9 דקות קריאהמאת NotHoly

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

המאמר מה DNS עושה מסביר איך שם הופך לכתובת. כאן נראה מאיפה באים פורטים, איך שני פרוטוקולי התעבורה העיקריים משתמשים בהם, ואיך רואים על אילו פורטים המכונה שלך מאזינה. המעבדה רצה על 127.0.0.1, כתובת ה-loopback שתמיד פירושה "המכונה הזו", כך ששום דבר לא יוצא מהמחשב שלך.

מה זה פורט

פורט הוא מספר של 16 ביט, כלומר טווח מ-0 עד 65535. גם בכותרת TCP וגם בכותרת UDP יש פורט מקור ופורט יעד. כשחבילה מגיעה למחשב, מערכת ההפעלה קוראת את פורט היעד ומעבירה את הנתונים לתוכנה שביקשה לקבל במספר הזה.

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

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

למה זה חשוב

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

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

השכבות במעבר אחד

TCP/IP הוא אוסף הפרוטוקולים שהאינטרנט רץ עליו. הוא בנוי משכבות, ועדיין לא צריך את כולן. כאן רלוונטיות ארבע שכבות:

  • Link: מעבירה מסגרות על מקטע רשת מקומי אחד, כמו Wi-Fi או Ethernet.
  • Internet: פרוטוקול IP מעביר חבילות בין מארחים ובין רשתות, לפי כתובות IP.
  • Transport: פרוטוקול TCP או UDP מעביר נתונים בין תוכנות, לפי פורטים.
  • Application: הפרוטוקול שהתוכנה מדברת, כמו HTTP, DNS או SSH.

כל שכבה עוטפת את הנתונים של השכבה שמעליה בכותרת משלה. כותרת ה-IP נושאת את כתובות המקור והיעד. כותרת ה-TCP או ה-UDP נושאת את פורטי המקור והיעד. נתוני האפליקציה יושבים בפנים. כשהחבילה מגיעה, כל שכבה מסירה את הכותרת שלה ומעבירה את השאר למעלה.

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

איך TCP פותח חיבור

TCP, שמוגדר ב-RFC 9293, נותן לתוכנה זרם בתים אמין ומסודר. לפני שנתוני אפליקציה עוברים, שני הצדדים מסכימים על מספרי רצף התחלתיים ומוודאים שכל צד יכול לשלוח ולקבל. ההסכמה הזו היא לחיצת היד המשולשת.

  1. הלקוח שולח מקטע SYN. בפשטות, הוא אומר: אני רוצה להתחבר לפורט 8000, ומספר הרצף ההתחלתי שלי הוא X.
  2. אם תוכנה מאזינה בפורט 8000, השרת עונה ב-SYN-ACK. הוא מאשר את X ושולח מספר התחלתי משלו.
  3. הלקוח עונה ב-ACK. החיבור פתוח עכשיו, והלקוח יכול לשלוח את הבקשה שלו.

כשאף תוכנה לא מאזינה בפורט, מכונת היעד לא שולחת SYN-ACK. היא שולחת מקטע RST (reset), והלקוח מוותר מיד עם הודעה כמו "connection refused". התשובה המהירה הזו שימושית. היא מלמדת שהמארח קיבל את החבילה ושאף תוכנה לא מקבלת חיבורים בפורט הזה.

המתנה שקטה שנגמרת ב-timeout אומרת משהו אחר. הרבה פעמים חומת אש זרקה את החבילות בלי לענות. לכן "refused" ו-"timed out" הם שני רמזים שונים, וכדאי ללמוד לקרוא אותם.

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

במה UDP שונה

UDP, שמוגדר ב-RFC 768, פשוט בהרבה. הכותרת שלו היא 8 בתים: פורט מקור, פורט יעד, אורך ו-checksum. אין לחיצת יד, אין אישורים, אין שליחה חוזרת ואין סדר. השולח משדר datagram, והרשת מעבירה אותו או שלא. המקבל לא מאשר כלום, אלא אם האפליקציה בונה את הלוגיקה הזו בעצמה.

לפשטות הזו יש שימושים. שאילתות DNS עוברות בדרך כלל ב-UDP בפורט 53, כי שאלה קצרה ותשובה קצרה נכנסות בחילוף אחד, ולחיצת יד הייתה מוסיפה סבבים. קול ווידאו בזמן אמת משתמשים הרבה פעמים ב-UDP, וכך גם QUIC, התעבורה שמתחת ל-HTTP/3. כל אחד מהפרוטוקולים האלה מביא כללים משלו לאובדן חבילות ולניסיונות חוזרים.

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

מי קובע איזה מספר אומר מה

Internet Assigned Numbers Authority (IANA) מתחזק את Service Name and Transport Protocol Port Number Registry. המרשם מתעד איזה שירות מקושר בדרך כלל לכל מספר פורט ב-TCP, ב-UDP ובעוד כמה פרוטוקולי תעבורה. רשומות מוכרות הן 22 עבור ssh, 53 עבור domain (DNS), 80 עבור http ו-443 עבור https.

RFC 6335 מחלק את מרחב המספרים לשלושה טווחים:

  • 0 עד 1023: פורטי מערכת, שנקראים גם well-known ports. במערכות רבות רק תהליכים עם הרשאות גבוהות יכולים להיקשר אליהם.
  • 1024 עד 49151: פורטי משתמש, שבהם ספקים רושמים שירותים רבים.
  • 49152 עד 65535: פורטים דינמיים או פרטיים. לקוחות משתמשים בהם הרבה פעמים כפורטי מקור זמניים.

המרשם מתעד הקצאות ומוסכמות. שום דבר ב-TCP או ב-UDP לא אוכף אותן. כל תוכנה עם הרשאה יכולה להיקשר כמעט לכל פורט פנוי. המרשם אומר מה רץ בדרך כלל על מספר, והוא יכול לטעות לגבי המכונה שלך. לפני שמסיקים מסקנה, צריך להסתכל על מה שבאמת מאזין.

מעבדה מעשית: שרת ווב מקומי על 127.0.0.1

צריך טרמינל ו-Python 3. המעבדה משתמשת בשרת ה-HTTP שמובנה ב-Python, כך שאין צורך להתקין שום דבר נוסף.

את פקודות Windows שלמטה הרצתי על Windows 11 Pro עם Git Bash, Python 3.12.10 ו-curl 8.12.1. את פקודות Linux ו-macOS לא הרצתי במכונה הזו, ולכן הפלט שלהן לא מוצג. כל בלוק פלט שמופיע הגיע מהפקודה שמעליו.

הערה על Python: בסשן Git Bash שלי הפקודה python3 לא נמצאה, ואילו הפקודה python הריצה Python 3.12. אם ב-Windows הפקודה python3 נכשלת, אפשר להשתמש בפקודה python. שאר הפקודה נשאר אותו דבר.

שלב 1: ליצור תיקייה עם קובץ אחד

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

bash
mkdir -p ~/port-lab && cd ~/port-lab
printf '<!doctype html><title>lab</title><h1>Port 8000 lab</h1>\n' > index.html

ב-PowerShell, ליצור את אותה תיקייה ולכתוב את שתי השורות האלה בקובץ index.html בכל עורך.

שלב 2: להפעיל את השרת ולהשאיר אותו רץ

צריך להשאיר את הטרמינל הזה פתוח. השרת רץ עד שעוצרים אותו.

bash
cd ~/port-lab
python3 -m http.server 8000 --bind 127.0.0.1

הדגל --bind 127.0.0.1 אומר ל-Python להאזין רק בממשק ה-loopback. בלעדיו, Python מאזין בכל הממשקים של המכונה. ההבדל הזה חשוב בהמשך, כשקוראים את רשימת המאזינים.

שלב 3: למצוא את ה-socket המאזין

לבחור את הפקודה למערכת ההפעלה שלך. כל אחת מציגה את ה-sockets במצב LISTEN שמשתמשים בפורט 8000.

Linux:

bash
ss -tlnp | grep 8000

macOS:

bash
lsof -iTCP -sTCP:LISTEN -n -P | grep 8000

Windows PowerShell:

powershell
Get-NetTCPConnection -State Listen -LocalPort 8000

זה הפלט שקיבלתי מפקודת ה-Windows במכונה שלי, דרך Format-Table:

text
LocalAddress LocalPort  State OwningProcess
------------ ---------  ----- -------------
127.0.0.1         8000 Listen         45608

מזהה התהליך יהיה שונה במכונה שלך. כדי לוודא שהבעלים הוא תהליך ה-Python שהופעל, צריך להריץ Get-Process -Id <OwningProcess> עם המספר שלך. בהרצה שלי זה היה python.

על מה להסתכל:

  • הערך של LocalAddress הוא 127.0.0.1. ה-socket מקבל חיבורים רק מהמכונה הזו. בלי הדגל --bind, הציפייה היא לראות כאן 0.0.0.0. לא בדקתי את הווריאנט הזה במכונה הזו, אז זו התוצאה הצפויה ולא תוצאה שנצפתה.
  • הערך של State הוא Listen. ה-socket ממתין לחיבורים.
  • הערך של OwningProcess מצביע על התוכנה הצפויה. אם הוא מצביע על משהו לא מוכר, צריך לעצור ולברר מה זה לפני שממשיכים.

שלב 4: להתחבר אליו

לפתוח טרמינל שני ולהריץ:

bash
curl -v http://127.0.0.1:8000/

זה הפלט מההרצה שלי, מקוצר לשורות הרלוונטיות:

text
* Trying 127.0.0.1:8000...
* Connected to 127.0.0.1 (127.0.0.1) port 8000
> GET / HTTP/1.1
> Host: 127.0.0.1:8000
< HTTP/1.0 200 OK
< Server: SimpleHTTP/0.6 Python/3.12.10
< Content-type: text/html
<!doctype html><title>lab</title><h1>Port 8000 lab</h1>

קוראים אותו לפי הסדר. Trying אומר ש-curl פותח חיבור TCP. הכתובת כבר IP, ולכן אין שאילתת DNS. Connected אומר שלחיצת היד המשולשת הסתיימה. GET / HTTP/1.1 הוא שכבת האפליקציה: עכשיו curl מדבר HTTP על החיבור הזה. 200 OK אומר שהשרת מצא את הקובץ וענה. שורת ה-HTML בתחתית היא הקובץ שלך.

השרת כותב שורה על הבקשה בטרמינל שלו. אצלי הופיע:

text
127.0.0.1 - - [08/Nov/2026 06:07:56] "GET / HTTP/1.1" 200 -

כתובת המקור היא אותה כתובת loopback, ולכן הבקשה הגיעה מהמכונה הזו.

שלב 5: לעצור את השרת ולנסות שוב

לחזור לטרמינל של השרת וללחוץ Ctrl+C. זו הדרך הנקייה לעצור אותו. במכונה שלי עצרתי את התהליך עם Stop-Process -Force, שמסיים אותו בלי לתת לו הזדמנות להיסגר בצורה נקייה. בכל מקרה, ה-socket המאזין נעלם כשהתהליך מסתיים.

לוודא שה-socket נעלם:

powershell
Get-NetTCPConnection -State Listen -LocalPort 8000

הפלט שלי היה ריק. אחר כך להריץ שוב את אותה פקודת curl:

bash
curl -v http://127.0.0.1:8000/

זה הפלט מההרצה שלי:

text
* Failed to connect to 127.0.0.1 port 8000 after 2048 ms: Could not connect to server
curl: (7) Failed to connect to 127.0.0.1 port 8000 after 2048 ms: Could not connect to server

קוד היציאה של curl היה 7, הקוד שפירושו שלא הצליח להתחבר.

מה קרה: ה-SYN הגיע אל 127.0.0.1 בפורט 8000. אף תוכנה לא האזינה שם, ולכן מערכת ההפעלה ענתה ב-reset. curl דיווח על הסירוב מיד, בלי לחכות ל-timeout. אם במקום זה יש המתנה ארוכה שאחריה timeout, החשד הוא חומת אש או נתיב שזורק חבילות.

מה המעבדה מראה

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

טעויות נפוצות

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

התייחסות למספר פורט כהוכחת זהות. פורט 80 בדרך כלל אומר HTTP, אבל שום דבר לא מכריח תוכנה לדבר בו HTTP. צריך להתחבר ולקרוא מה השירות שולח, או לבדוק איזה תהליך מחזיק ב-socket.

שכחה של UDP. הפקודה ss -tlnp מציגה רק מאזיני TCP. בשביל UDP יש ss -ulnp, או Get-NetUDPEndpoint ב-Windows. למכונה יכול להיות שירות UDP עמוס שאף פעם לא מופיע בבדיקת TCP.

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

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

למה זה בא ראשון בעבודת אבטחה

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

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

איך ממשיכים

לחזור על התרגיל עם UDP. בהרצה שלי, מאזין Python קצר על 127.0.0.1 בפורט 5399 קיבל datagram משולח. המאזין לא עשה שום דבר מיוחד:

python
import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("127.0.0.1", 5399))
data, addr = s.recvfrom(1024)
print("got", data, "from", addr)

להריץ אותו בטרמינל אחד, ואז לשלוח datagram מטרמינל אחר עם socket.sendto. הפלט שקיבלתי היה got b'hello' from ('127.0.0.1', 63411). לא הייתה שום לחיצת יד, החבילה פשוט הגיעה. פורט 5353 כבר היה בשימוש במכונה שלי, וקשירה אליו נכשלה בשגיאת הרשאות, ולכן בחרתי 5399 לבדיקה.

אחר כך לקרוא את החלק על הקמת חיבור ב-RFC 9293 ולהשוות אותו לזרימת החבילות שלמעלה. ואז להמשיך אל איך HTTP עובד, שמסביר איך HTTP רץ מעל TCP ומה יש בבקשה ובתשובה.

מקורות

RFC 9293, Transmission Control Protocol (TCP), IETF, אוגוסט 2022. https://www.rfc-editor.org/rfc/rfc9293

RFC 768, User Datagram Protocol, IETF, אוגוסט 1980. https://www.rfc-editor.org/rfc/rfc768

Service Name and Transport Protocol Port Number Registry, IANA. https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml

RFC 6335, Internet Assigned Numbers Authority (IANA) Procedures for the Management of the Service Name and Transport Protocol Port Number Registry, IETF, אוגוסט 2011. https://www.rfc-editor.org/rfc/rfc6335

מקורות

  1. RFC 9293: Transmission Control Protocol (TCP)
  2. RFC 768: User Datagram Protocol
  3. IANA: Service Name and Transport Protocol Port Number Registry
  4. RFC 6335: IANA Procedures for the Service Name and Port Number Registry

עוד בנושא רשתות ואינטרנט

רשתות ואינטרנט

מה זה TLS? איך HTTPS מגן על תעבורה

TLS 1.3 נותן ל-HTTPS סודיות, שלמות ואימות שרת. לחיצת היד, שרשראות תעודות, ומה המנעול בדפדפן לא מוכיח.

מתחילים10 דקות קריאה