רשימת הפורטים הפתוחים היא רשימת הדרכים להגיע לשרת שלכם. כל השאר — חומות אש, חומות אש לאפליקציות, זיהוי חדירות — נבנה מעליה. לכן השאלה «מה מאזין כאן» באה ראשונה בכל ביקורת, ולכן גם זו הבדיקה שלרוב נותנת תשובה לא נעימה: מחצית ממה שצץ לא אתם פתחתם אלא תוכנית ההתקנה של חבילה כלשהי.
קריאת הפלט
sudo ss -tulpn
הדגלים: t ל-TCP, u ל-UDP, l רק למה שמאזין, p לתהליך, ו-n כדי שהמספרים יישארו מספרים. בלי sudo עמודת התהליך ריקה והתרגיל מאבד את משמעותו.
מה שחשוב היא העמודה Local Address:Port, וההבדל שם עקרוני:
127.0.0.1:3306— השירות נגיש רק מהמכונה עצמה. זה טוב;0.0.0.0:3306— מכל כתובת IPv4, כלומר מהאינטרנט. את זה צריך לבדוק;[::]:3306— אותו דבר ל-IPv6. שורה נפרדת, ובאופן קבוע מפספסים אותה;203.0.113.25:443— בכתובת מסוימת, בדרך כלל במכוון.
אחר כך לכל שורה עם 0.0.0.0 או [::] שאלו שאלה אחת: האם אדם זר צריך להיות מסוגל להגיע לכאן. ל-80 ול-443 התשובה היא כן. כמעט לכל השאר היא לא.
הממצאים הרגילים
Redis, פורט 6379. השורה המסוכנת ביותר שם. כברירת מחדל Redis אינו דורש סיסמה, והפקודות שלו מאפשרות לכתוב קובץ לדיסק — כלומר מפתח זר ב-authorized_keys. בין הופעת Redis בכתובת ציבורית לבין השימוש בו עוברות שעות, לפעמים פחות. בדקו אם בהגדרות יש bind 127.0.0.1 ו-protected-mode yes.
Memcached, 11211/UDP. גם אם אין בפנים שום דבר בעל ערך, השרת שלכם הופך למגבר להתקפות של אחרים — והתלונה תגיע דווקא מהספק שלכם.
MySQL ו-PostgreSQL, 3306 ו-5432. יש סיסמה, אבל הניחוש מולה נמשך ברציפות, וגרסאות מסדי הנתונים מתעדכנות לעיתים רחוקות יותר מכפי שהיינו רוצים. כמעט אף פעם אין להם צורך להביט החוצה: האפליקציה נמצאת באותה מכונה, ולעבודה שלכם עצמכם די במנהרת SSH.
Elasticsearch 9200, MongoDB 27017. היסטורית ללא אימות כברירת מחדל. המופעים הציבוריים שלהם הם מקור קבוע לחדשות על דליפות נתונים.
ה-API של Docker, 2375. פורט בקרה פתוח של Docker פירושו root במארח בלי שום סיסמה כלל. הוא מופיע בדרך כלל אחרי ניסויים עם גישה מרוחקת ל-Docker.
לוחות בקרה ו-phpMyAdmin בפורטים משלהם: 8080, 8083, 10000. לא שאסור לפתוח אותם לעולם, אבל דווקא הם אוספים את עיקר הניסיונות.
תקנו בשירות עצמו, לא בחומת האש
הרצון לסגור כל ממצא בכלל של UFW מובן, אבל זה הקו השני ולא הראשון. כלל עלול להימחק בטעות, חומת אש עשויה להיות מכובה זמנית בזמן איתור תקלות, ו-Docker מפרסם פורטים בעקיפה מוחלטת של UFW. הגדרת הקישור בקובץ ההגדרות של השירות עצמו שורדת את כל אלה:
- MySQL/MariaDB —
bind-address = 127.0.0.1; - PostgreSQL —
listen_addresses = 'localhost'; - Redis —
bind 127.0.0.1 ::1; - Docker Compose — פרסמו כ-
"127.0.0.1:5432:5432".
וחומת האש באה מעל זה כביטוח, לא במקומו.
למצוא את התהליך כשלא ברור
ss נותן את השם ואת מזהה התהליך. אחר כך:
sudo systemctl status <pid>
sudo lsof -i :8080
הפקודה הראשונה מציינת את יחידת ה-systemd שאליה שייך התהליך — וזה בדרך כלל מספיק כדי להבין מה זה והאם זה נחוץ. אבל תהליך לא מוכר שמאזין בפורט גבוה והופעל מחוץ לתיקיות המערכת — נניח מ-/tmp או מ-/dev/shm — הוא כבר לא שאלה של הגדרות אלא עילה לחקירה נפרדת.
בדיקה מבחוץ היא חובה
ss עונה על «מה מאזין», לא על «למה אפשר להגיע». ביניהם עומדים חומת האש, NAT והכללים של הספק עצמו. התשובה הכנה היחידה מגיעה מסריקה ממכונה אחרת:
nmap -Pn -p- 203.0.113.25
nmap -Pn -p- -6 2001:db8::1
אל תדלגו על הפקודה השנייה: כמעט לכל VPS יש כתובת IPv6, הכללים שלה נכתבים בנפרד, והשירות מאזין לשתי גרסאות הפרוטוקול בו-זמנית.
זו אינה בדיקה חד-פעמית
רשימת הפורטים הפתוחים משתנה מעצמה. התקנתם חבילה והיא הביאה שירות ופתחה פורט. עדכנתם לוח והוא החזיר ערך ברירת מחדל. הפעלתם מכולה והיא פרסמה פורט בעקיפת חומת האש. בדיקה חד-פעמית עונה על היום ותו לא.
הערך אינו ברשימה עצמה אלא בשינויים שלה: פורט חדש שאתמול לא היה הוא אות קצר ואינפורמטיבי ביותר. ובדיוק כך שווה לעקוב אחריו — כתצלום עם היסטוריה, ולא כפלט של ss שנזכרים בו מהזיכרון. עמוד ההדגמה למטה מראה בדיוק את זה.