אם אתם מנהלים שרת לינוקס החשוף לאינטרנט, במוקדם או במאוחר תראו אלפי ניסיונות גישה באמצעות SSH מכתובות IP אקראיות ביומני הגישה . זה לא שהם לא אהבו אתכם: מדובר בבוטים אוטומטיים שסורקים טווחי IP בחיפוש אחר נקודות כניסה חלשות.
בשרת קטן, ניסיונות אלה עלולים לגרום לקפיצות חדות בניצול המעבד, ירידה בביצועים ואפילו להפסקות שירות זמניות . החדשות הטובות הן שלינוקס מציעה ארסנל של כלים להגבלת ניסיונות סיסמה, חסימת כתובות IP אגרסיביות והקשחת SSH כדי להקשות מאוד על תוקף.
זיהוי מתקפות SSH Brute-Force והשפעתן על השרת
לפני שנתחיל להגדיר משהו, חשוב להבין כיצד לזהות שאנו סובלים מהתקפת Brute-Force נגד SSH או שירותים אחרים , ואיזו השפעות יש לה על המכונה.
תסמין אופייני מאוד הוא עלייה פתאומית בניצול המעבד ללא כל שינוי בתעבורה הלגיטימית או בעומס מסד הנתונים . לדוגמה, ייתכן שתיתקל בעלייה חדה במעבד למשך מספר דקות בעוד שניצול הזיכרון והדיסק נשאר כמעט ללא שינוי, דבר שבדרך כלל מצביע על תהליכים עתירי מחשוב (כגון ניסיונות אימות רבים) ולא על שאילתות כבדות.
כדי לנתח מה קרה במהלך פרק זמן מסוים, שימושי מאוד להשתמש ב-journalctl , הכלי של systemd לקריאת יומני מערכת, שירות, ליבה ואימות. דוגמה קלאסית לשאילתה תהיה:
journalctl --since "2025-11-16 13:10" --until "2025-11-16 13:16"
בעזרת שאילתה מסוג זה ניתן לסקור בפירוט אילו הודעות המערכת רשמה במהלך החלון בו המעבד עלה בעוצמה : שירותים שהופעלו מחדש, כשלי אימות, שגיאות ליבה וכו'.
במקרים רבים, תיתקלו בשורות חוזרות הקשורות ל-SSH, כגון "Failed password for", המציינות ניסיונות התחברות כושלים . זהו למעשה שם נרדף לבוטים המנסים בכוח גס את פרטי ההזדהות.
כימת ניסיונות כושלים בקובץ /var/log/auth.log
במערכות דביאן/אובונטו, קובץ המפתח למעקב אחר כל מה שקשור לאימות הוא /var/log/auth.log . הוא מתעד כניסות מוצלחות, ניסיונות כושלים, אירועי PAM, נעילת חשבונות ועוד.
אם ברצונך לדעת כמה פעמים התבנית "סיסמה נכשלה" נרשמה ביומן הנוכחי , תוכל להשתמש ב:
sudo grep 'Failed password' /var/log/auth.log | wc -l
התוצאה יכולה להיות מפתיעה: לא נדיר לראות אלפי ניסיונות כושלים מצטברים תוך שעות ספורות . וזכרו, זה רק הקובץ הנוכחי.
מכיוון שהיומנים מסובבים, חשוב לבדוק גם את הקבצים הישנים יותר. ניתן לראות את מרווח הזמן שהיומן הנוכחי מכסה באמצעות משהו כמו:
head -n 1 /var/log/auth.log
tail -n 1 /var/log/auth.log
זה יגיד לך את התאריך של הרשומות הראשונות והאחרונות בקובץ auth.log . כל הניסיונות הקודמים יהיו בקובץ auth.log.1 ובקבצי auth.log.N.gz הדחוסים.
כדי לסקור יומני רישום ישנים דחוסים ולספור ניסיונות כושלים של סיסמה, ניתן להשתמש ב:
zgrep 'Failed password' /var/log/auth.log.*.gz | wc -l
אם תסכמו את מה שאתם רואים ב- auth.log, auth.log.1 ו-auth.log.*.gz תקבלו מושג טוב על ההיסטוריה של מתקפות Brute Force שתועדו , תוך קחו בחשבון שייתכן שהישנות ביותר כבר נעלמו עקב רוטציה.
כיצד פועלת סבב יומני אימות
האופן והתדירות שבהם מסובבים לוגים תלויים בתצורת logrotate . באובונטו, הסיבוב של auth.log מוגדר בדרך כלל ב-/etc/logrotate.d/rsyslog, שם תמצאו בדרך כלל משהו כמו:
weekly
rotate 4
compress
משמעות הדבר היא שהלוג עובר סיבוב שבועי, ארבעה עותקים ישנים נשמרים, והישנים נדחסים לקבצי .gz . משימת cron יומית אחראית על הרצת logrotate ויישום כללים אלה.
לכן, בעת חישוב ניסיונות Brute-Force, נניח שאתה מסתכל רק על ההיסטוריה מלפני מספר שבועות . כל דבר שקרה רחוק יותר בזמן לא יהיה עוד במערכת.
זיהוי משתמשים וכתובות IP תוקפות
מעבר לספירה הכוללת, כדאי לדעת אילו משתמשים מכוונים ומאילו כתובות IP מגיעות ההתקפות . פקודה מהירה של `awk` ב-`auth.log` תיתן לכם מידע זה.
כדי לראות אילו שמות משתמש מנסים בניסיונות שנכשלו:
sudo grep 'Failed password' /var/log/auth.log \
| awk '{print $(NF-5)}' \
| sort | uniq -c
וכדי לראות את כתובות ה-IP עם הפעילות החשודה ביותר:
sudo grep 'Failed password' /var/log/auth.log \
| awk '{print $(NF-3)}' \
| sort | uniq -c | head
זה יאפשר לך לזהות במהירות האם חשבונות אמיתיים במערכת שלך מותקפים, או משתמשים גנריים כמו root, admin, test, user וכו', ואילו כתובות IP עליך לחסום בדחיפות רבה.
האם זה באמת כל כך רציני שיש אלפי ניסיונות?
עליך להניח שאם השרת שלך נגיש מהאינטרנט ויש לו SSH מאזין בפורט 22 או כל פורט אחר , הוא יקבל תעבורה מסוג זה 24 שעות ביממה. זה נורמלי לראות אלפי ניסיונות כושלים אם השרת פועל אפילו לזמן קצר.
כוח המשיכה בפועל תלוי בהגדרות שלך:
| תצורה | סיכון משוער |
|---|---|
| סיסמאות חלשות + SSH פתוח לאינטרנט | סיכון גבוה מאוד לפשרה |
| סיסמאות חזקות | סיכון בינוני, אך צריכת משאבים |
| Fail2ban מוגדר כראוי | התקפות בעלות סיכון נמוך ומופחתות מאוד |
| גישה רק עם מפתחות SSH | סיכון קרוב מאוד לאפס בכוח גס |
במילים אחרות, התקפות אוטומטיות הן דבר שבשגרה, אך אם הגדרת האבטחה שלכם רופפת, סיסמה אחת שנכשלה עלולה לעלות לכם בשרת כולו . לכן חשוב כל כך להגביל ניסיונות התחברות, לחסום כתובות IP, ובמידת האפשר, לבטל סיסמאות לחלוטין.
הקשחת SSH בסיסית: אפשרויות קריטיות ב-sshd_config

קו ההגנה הראשון נמצא בתוך הדמון SSH עצמו (sshd) וקובץ התצורה שלו /etc/ssh/sshd_config (וקבצי .d נלווים). מספר הנחיות מכווננות היטב מפחיתות משמעותית את משטח ההתקפה.
קחו בחשבון שבהפצות מודרניות כמו אובונטו 22.04 ואילך, sshd קורא תחילה את /etc/ssh/sshd_config ולאחר מכן את הקבצים ב-/etc/ssh/sshd_config.d/*.conf בסדר אלפביתי. כל דבר שמופיע מאוחר יותר יכול לדרוס פרמטרים שהוגדרו קודם לכן, לכן היזהרו מאוד מה אתם משנים.
השבתת גישה ללא סיסמה והפעלות מיותרות
למרות שזה כבר מוגדר כהלכה ברוב ההפצות המודרניות, כדאי לוודא שכניסות ללא סיסמה מוגדרת אינן מותרות . המדיניות המרכזית היא:
PermitEmptyPasswords no
בדרך כלל זה מושבת בהערות או מוגדר במפורש כ-"לא". כמו כן, ודא שתכונות שלא תשתמש בהן מושבתות, כגון העברת X11 אם אינך מבצע הפעלות גרפיות מרחוק.
X11Forwarding no
בנוגע לפרוטוקולים, אם מסיבה כלשהי אתם מנהלים מערכת ישנה מאוד, ודאו שרק פרוטוקול SSH 2 מותר :
Protocol 2
שנה את הפורט ברירת המחדל והגבל את הממשק עליו הוא מאזין.
טריק פשוט נוסף, אם כי לא חסין תקלות, הוא להעביר SSH מפורט 22 לפורט לא סטנדרטי . זה לא יגן עליכם מפני תוקף רציני, אבל זה מסנן כמות משמעותית של רעש אוטומטי שסורק רק את פורט 22.
Port 2222
ListenAddress 192.168.56.8
בנוסף לשינוי הפורט, ניתן לציין כתובת ספציפית שאליה SSH יאזין, לדוגמה, כתובת ה-IP הפנימית שלך אם ברצונך להגביל אותה לרשת ספציפית. עם זאת, אם ההפצה שלך משתמשת ב-`ssh.socket` של systemd, ייתכן שתצטרך להשבית את ה-socket ולחזור ל-`ssh.service` הקלאסי כדי שהוא יכבד את תצורת הפורט.
sudo systemctl disable ssh.socket
sudo systemctl daemon-reload
sudo systemctl enable ssh.service
sudo systemctl start ssh.service
בכל פעם שאתה משנה את הפורט, בדוק את החיבור מטרמינל אחר לפני סגירת הסשן הראשי, כדי שלא תיתקע ללא גישה מרחוק.
חסימה או הגבלה של גישת root
משתמש ה-root הוא מטרה עיקרית לתוקפים, לכן הגיוני למנוע מהם להתחבר דרך SSH , אפילו עם מפתחות. ניתן לשלוט בהתנהגות זו באמצעות ההנחיה הבאה:
PermitRootLogin no
בהרבה התקנות מודרניות, זה מגיע במצב "prohibit-password", שמונע כניסות באמצעות סיסמה אך משאיר את הדלת פתוחה לאישורים. אם אתם רוצים להיות בטוחים, השאירו את זה מוגדר על "no" והשתמשו בחשבון רגיל עם sudo לניהול.
הגדר מי יכול לגשת: AllowUsers ו-AllowGroups
כברירת מחדל, כל משתמש עם מעטפת חוקית וסיסמה מוגדרת יכול לנסות להתחבר דרך SSH. זה בדרך כלל לא אידיאלי בשרתי ייצור, שבהם אולי רק שניים או שלושה חשבונות צריכים לקבל גישה.
כדי להגביל את המשתמשים המורשים, יש לך את ההנחיות AllowUsers ו- AllowGroups . לדוגמה:
AllowUsers harry hermione
AllowGroups gryffindor
הרשימה מופרדת באמצעות רווחים ומשתמשת בגישת "רשימה לבנה": רק חשבונות וקבוצות המפורטים יוכלו לאמת . כמו כן, שימו לב ש-AllowUsers מקבל עדיפות על פני AllowGroups, לכן הימנעו משילוב ביניהם אלא אם כן אתם מבינים בבירור את הסדר שבו הם מוערכים.
נוהג טוב הוא לעבוד בעיקר עם קבוצות כמו sshuser או admins ולהוסיף שם חשבונות מורשים, במקום לתחזק רשימה של משתמשים אחד אחד בקובץ.
הגבלת ניסיונות אימות וזמן השבתה
שכבת הגנה נוספת כרוכה בהפחתת מספר ניסיונות החיבור הכושלים המותרים ומשך חוסר הפעילות בסשן יחיד. עבור הראשון, ניתן להשתמש ב:
MaxAuthTries 3
פעולה זו תגרום לשרת לסגור את החיבור לאחר שלושה ניסיונות שגויים, מה שיהפוך כל התקפה שתנסה סיסמאות רבות כנגד אותה הפעלת SSH לפחות יעילה.
לגבי זמן סרק, SSH מאפשר לך לסיים חיבורים שנותרו פתוחים ללא פעילות מעבר לסף המוגדר על ידי ClientAliveInterval (בשניות):
ClientAliveInterval 180
לאחר שלוש דקות של חוסר פעילות, השרת ישלח הודעות keepalive, ואם הלקוח לא יגיב, הסשן ייסגר אוטומטית . זוהי דרך להפחית סיכונים כתוצאה מטרמינלים פתוחים.
הגבלת גישה לפי כתובת IP: עטיפת TCP והתאמה
בתרחישים מסוימים, ייתכן שתרצו להגביל את גישת SSH לכתובות IP או טווחים מסוימים בלבד . ישנן מספר דרכים לעשות זאת: החל משימוש בחומת האש עצמה (iptables/nftables), דרך מעטפות TCP, או אפילו שימוש בבלוקים של Match ב-sshd_config.
עם TCP Wrappers, שעדיין בשימוש בהפצות רבות, הגישה נשלטת באמצעות `/etc/hosts.allow` ו-`/etc/hosts.deny`. הזרימה היא: ראשית, `hosts.allow` מוערך, ולאחר מכן `hosts.deny` . דוגמה מגבילה תהיה:
# /etc/hosts.deny
ALL: ALL
# /etc/hosts.allow
sshd: 192.168.1.89 192.168.1.55
sshd: ALL: DENY
עם תצורה זו, רק שני מארחים ספציפיים יוכלו להתחבר דרך SSH , וכל האחרים ייחסמו. זה יעיל מאוד בסביבות סגורות, אם כי פחות גמיש מחומת אש מודרנית טובה.
אפשרות נוספת, אופיינית יותר ל-SSH, היא להשתמש בבלוקים של Match בתוך sshd_config כדי להחיל כללים המבוססים על כתובת או משתמש. דמיינו שאתם רוצים שמשתמש בשם "git" יוכל להתחבר מכל מקום, אבל משתמש המנהל שלכם "greg" יוכל להתחבר רק מה-LAN 192.168.1.0/24. אתם יכולים לשלב את AllowUsers עם כללי Match Address, אם כי עליכם להיזהר מאוד לא להגביל את הגישה לעצמכם.
Fail2ban: חסימות אוטומטיות לעומת כוח ברוט
אפילו אם תחזקו את ה-SSH, בוטים עדיין ינסו אישורים, מה שיגרום לשימוש במעבד ורעש בלוג. כדי למתן זאת , נכנסת Fail2ban - מערכת למניעת חדירות מבוססת יומן שחוסמת אוטומטית כתובות IP עם יותר מדי כשלים.
Fail2ban כתוב בפייתון ומסתמך על "jails ", שכל אחד מהם משויך לשירות ולקובץ יומן אחד או יותר . כאשר הוא מזהה דפוס שגיאה חוזר (סיסמאות כושלות, גישה אסורה וכו'), הוא מפעיל פעולות, בדרך כלל כללי חומת אש, כדי לחסום את המקור.
התקנת Fail2ban על הפצות לינוקס נפוצות
ההתקנה הבסיסית די פשוטה באמצעות מנהל החבילות של ההפצה שלך. באובונטו או דביאן, זה יספיק:
sudo apt update
sudo apt install fail2ban
במערכות מבוססות RHEL (RHEL, CentOS, AlmaLinux, Rocky וכו') הפקודה הטיפוסית תהיה עם dnf או yum, בהתאם לגרסה :
sudo dnf install fail2ban
החבילה כוללת בדרך כלל שירות systemd שמופעל אוטומטית, אם כי מומלץ לבדוק ש- Fail2ban מופעל בעת האתחול ופעיל :
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo systemctl status fail2ban
מבנה תצורה: jail.conf, jail.local, ו-jail.d
קובץ התצורה נמצא בקובץ /etc/fail2ban/ . הקובץ הראשי הוא jail.conf, אך עריכה ישירה שלו אינה מומלצת מכיוון שהוא יימחס במהלך עדכונים. במקום זאת, עליך:
- צור או ערוך את /etc/fail2ban/jail.local כדי להחליף ערכי ברירת מחדל.
- או הוסיפו קבצים ספציפיים ל-/etc/fail2ban/jail.d/*.conf.
Fail2ban טוען את התצורה בסדר הזה:
/etc/fail2ban/jail.conf
/etc/fail2ban/jail.d/*.conf
/etc/fail2ban/jail.local
כל מה שאתה מגדיר ב-jail.local מקבל עדיפות על פני כל דבר אחר, כך שאתה יכול להתאים אישית מבלי לגעת בקבצי החבילה.
פרמטרים גלובליים חשובים: bantime, maxretry, ignoreip
בתוך jail.conf (או jail.local) תראו מקטע [DEFAULT] עם פרמטרים גלובליים שמשפיעים על כל הפקודות jail אלא אם כן הן מבוטלות. החשובים ביותר הם:
- bantime: הזמן שבו כתובת IP תיחסם (בשניות) לאחר חריגה ממספר הכשלים המותרים.
- maxretry: מספר מקסימלי של ניסיונות כושלים לפני החלת האיסור.
- למצוא זמן: חלון הזמן שבו נספרים ניסיונות אלה (למשל, 10 דקות במשך עשר דקות).
- ignoreipרשימת כתובות IP או טווחים ש-Fail2ban לעולם לא אמור לחסום (לדוגמה, ה-IP הציבורי שלך או רשת הניהול שלך).
לדוגמה, יכול להיות לך משהו כזה ב-[DEFAULT]:
[DEFAULT]
bantime = 600
findtime = 600
maxretry = 5
ignoreip = 127.0.0.1/8 192.168.1.0/24
עם תצורה זו, כל כתובת IP שתכשל חמש פעמים בעשר דקות תיחסם למשך עשר דקות , אלא אם כן היא חלק מהטווחים שהוזנחו.
הגדר את sshd של jail כדי לעצור התקפות SSH
קובץ ה-Jail הנפוץ ביותר הוא קובץ SSH. בהפצות רבות, הוא מגיע מוגדר מראש ב-jail.conf; אתה רק צריך להפעיל אותו או לכוונן את הערכים שלו ב-jail.local. דוגמה פשוטה:
[sshd]
enabled = true
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 600
findtime = 10m
במקרה זה, שלושה ניסיונות התחברות כושלים שנרשמו ב-auth.log בתוך עשר דקות יגרמו לחסימה של עשר דקות של כתובת ה-IP התוקפת . Fail2ban מזריק כללים לחומת האש (iptables, nftables או UFW, בהתאם למערכת) כדי למנוע מחיבורים מכתובת IP זו אפילו להגיע ל-sshd.
כדי להחיל שינויי תצורה כלשהם, זכור להפעיל מחדש את השירות:
sudo systemctl restart fail2ban
צפה במצב בתי הכלא וכתובות ה-IP החסומות
Fail2ban כולל כלי בקרה שימושי מאוד, fail2ban-client , המאפשר לך לראות אילו בתי כלא פעילים ואילו כתובות IP נחסמו. לדוגמה:
sudo fail2ban-client status
זה יראה משהו דומה ל:
Status
|- Number of jail: 1
`- Jail list: sshd
למידע מפורט על בית הכלא SSHD:
sudo fail2ban-client status sshd
הפלט כולל, בין היתר, את מספר כתובות ה-IP האסורות כעת ואת סך הכתובות שנחסמו לפחות פעם אחת , בנוסף לרשימת כתובות ה-IP החסומות כעת.
בעזרת נתונים אלה תוכל לקבל מושג על כמות התעבורה הזדונית שהשרת שלך מקבל ועד כמה יעילה התצורה הנוכחית.
מנעולים קבועים וזמן איסור מצטבר
אם אתם רוצים להיות קשוחים במיוחד כלפי עבריינים חוזרים, Fail2ban מציעה שתי אסטרטגיות מעניינות: חסימה קבועה וחסימה הדרגתית.
כדי לחסום לצמיתות כל כתובת IP שעולה על סף הכישלון, פשוט הזן:
bantime = -1
עם הגדרה זו, כתובות IP שאושרו לעולם לא יבוטלו אוטומטית חסימה ; ניתן להסיר אותן ידנית רק במידת הצורך.
גמיש יותר הוא המנגנון ההדרגתי, שבו כל חזרה על עבירה מגדילה את זמן האיסור בהתאם לגורם:
bantime = 10m
bantime.increment = true
bantime.rndtime = 0
bantime.factor = 4
bantime.maxtime = -1
עם ערכים אלה, ההתקדמות תיראה בערך כך:
- בלוק שלישי: 10 דקות
- בלוק שני: 40 דקות
- בלוק שלישי: 160 דקות (בערך שעתיים ו-40)
- בלוק רביעי: מסביב 10,6 Horas
- בלוק חמישי: חלק 42 Horas
מכיוון ש-bantime.maxtime הוא ב-1-, משך הזמן יכול להמשיך לגדול ללא הגבלה , ולחסל לצמיתות תוקפים כבדים מאוד.
שימוש ב-Fail2ban מעבר ל-SSH: Apache, WordPress, MySQL, חנויות מקוונות…
ברגע שתשתלטו על Fail2ban, הצעד ההגיוני הבא הוא להרחיב אותו כדי להגן על שירותים רגישים אחרים מלבד SSH : פאנלים לניהול אתרים, CMS, מסדי נתונים וכו'.
לדוגמה, עבור חנות מקוונת (Magento, PrestaShop, WooCommerce וכו'), הגיוני מאוד ליצור jail שעוקב אחר יומני גישה של Apache או Nginx עבור שגיאות 401/403 רבות ב-/admin או /login . תצורה מינימלית מבוססת Apache עשויה להיראות כך:
[apache-auth]
enabled = true
filter = apache-auth
logpath = /var/log/apache2/access.log
maxretry = 5
bantime = 3600
בסביבות וורדפרס, נוהג נפוץ הוא לנטר את /wp-login.php ואת /xmlrpc.php , שהן נקודות כניסה קלאסיות להתקפות Brute-Force ובוטים. ניתן למקם את המסנן ב-/etc/fail2ban/filter.d/wordpress.conf:
[Definition]
failregex = .*"POST /wp-login.php HTTP.*" 403
ignoreregex =
ובית הכלא המתאים ב-jail.local:
[wordpress]
enabled = true
filter = wordpress
logpath = /var/log/apache2/access.log
maxretry = 3
bantime = 3600
אותו רעיון חל על מסדי נתונים חשופים (משהו שבדרך כלל עדיף להימנע ממנו): אם ברצונך להגן על MySQL מפני ניסיונות גישה כושלים מתמשכים, תוכל ליצור מסנן עבור הודעות "גישה נדחתה למשתמש" ביומן השגיאות:
[Definition]
failregex = ^<HOST>.*Access denied for user.*$
ignoreregex =
ואז כלא:
[mysqld-auth]
enabled = true
filter = mysql
logpath = /var/log/mysql/error.log
maxretry = 5
bantime = 1800
Fail2ban משתלב היטב גם עם שרתי אירוח המשתמשים בפאנלים מסוג cPanel או Plesk : הוא יכול לנטר שירותי דוא"ל, Apache, FTP ואפילו את לוח הבקרה עצמו, ולחסום כתובות IP שחורגות מהגבול בניסיונות התחברות.
אימות באמצעות מפתחות SSH: סוף להתקפות סיסמאות
כל האמור לעיל עוזר, אבל הקפיצה האמיתית קדימה מגיעה כשמחליטים להפסיק להשתמש בסיסמאות עבור SSH ולעבור למפתחות ציבוריים/פרטיים . בנקודה זו, מתקפות סיסמאות בכוח ברוט הופכות לחסרות טעם.
הרעיון פשוט: לכל משתמש לגיטימי יש זוג מפתחות, מפתח פרטי שנשאר במכשיר שלו ומפתח ציבורי שמועתק לשרת בקובץ ~/.ssh/authorized_keys של המשתמש המתאים.
כאשר הלקוח מתחבר, הוא לא שולח את המפתח הפרטי; הוא שולח את המפתח הציבורי ואז חותם על אתגר מהשרת עם המפתח הפרטי. השרת בודק את החתימה הזו מול המפתח הציבורי, ורק אם הם תואמים הוא מעניק גישה.
מדוע מקשי SSH מבטלים סיסמה באמצעות כוח ברוט-פורס
בתכנית סיסמאות קלאסית, התוקף פשוט צריך לנסות מחרוזות טקסט עד שאחת מהן תואמת את הסיסמה המאוחסנת (או את ה-hash שלה). למרות שלסיסמה טובה יש צירופים אפשריים רבים, אנחנו מדברים על סדרי גודל כמו 10¹⁰ אפשרויות עבור סיסמאות ממוצעות.
למפתח SSH טיפוסי של 256 סיביות (כמו אלה שב-Ed25519) יש מרחב חיפוש של כ- 10⁶¹⁷ צירופים . בפועל, מבחינה מתמטית, בלתי אפשרי לתוקף לנחש מפתח פרטי בכוח גס באמצעות מחשבים מודרניים.
יתר על כן, השרת אפילו לא מנסה לבצע חישובים אם המפתח הציבורי המוצג אינו נמצא ב- authorized_keys . במקרה כזה, הוא מנתק את החיבור כמעט באופן מיידי, מבלי להפעיל PAM או תהליכי אימות מסורתיים, וכתוצאה מכך צריכת מעבד מינימלית במהלך מתקפה מסיבית.
צור ואמת מפתחות SSH על הלקוח
לפני הגישה לשרת, בדוק אם למחשב שלך כבר נוצר זוג מפתחות SSH. פשוט רשום את התוכן של ~/.ssh:
ls -l ~/.ssh
אם אתם רואים קבצים כמו id_ed25519 ו-id_ed25519.pub או id_rsa ו-id_rsa.pub, כבר יש לכם זוג קבצים תקף. Ed25519 הוא קבץ מודרני וקל יותר, ולכן בדרך כלל הוא האפשרות הטובה ביותר בימינו.
אם אין לך מפתחות, צור חדשים באמצעות:
ssh-keygen -t ed25519 -C "tu_usuario@tu_equipo"
הפקודה תיצור שני קבצים:
- id_ed25519המפתח הפרטי, שאסור לשתף לעולם.
- id_ed25519.pubהמפתח הציבורי, שניתן להעתיק לשרתים.
ניתן לצפות בתוכן המפתח הציבורי באמצעות:
cat ~/.ssh/id_ed25519.pub
העתק את המפתח הציבורי לשרת ובדוק את הגישה
בשרת, ודא שקיימת ספריית ~/.ssh עבור המשתמש שאיתו תתחבר (לדוגמה, git או משתמש מנהל המערכת שלך) ושיש לה 700 הרשאות :
mkdir -p ~/.ssh
chmod 700 ~/.ssh
לאחר מכן הוסף את תוכן קובץ ה-id_ed25519.pub של הלקוח שלך לקובץ ~/.ssh/authorized_keys (יצירת הקובץ אם הוא אינו קיים) ותן לו הרשאות 600:
echo "TU_PUBLIC_KEY" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
זכור להחליף את YOUR_PUBLIC_KEY בשורה המלאה שראית באמצעות `cat` במחשב שלך. משם, תוכל לבדוק את החיבור על ידי ציון מפורש של המפתח אם תרצה בכך.
ssh -i ~/.ssh/id_ed25519 usuario@IP_DEL_SERVIDOR
אם הכל עובד כשורה, השרת לא יבקש סיסמה ותועבר ישירות למעטפת . בשלב זה, אתה מוכן לשקול להשבית את אימות הסיסמה.
השבת לחלוטין את אימות הסיסמה בשרת
לאחר שווידאת שאתה יכול לגשת לחשבונך באמצעות הסיסמה שלך ממחשב אחד לפחות (רצוי שניים, למקרה שתאבד אחד), מומלץ להשבית כניסה באמצעות סיסמה עבור SSH . פעולה זו תמנע כל מתקפת Brute-Force קלאסית.
לפני שנוגעים בתצורה, מומלץ לבדוק אילו קבצים מגדירים את PasswordAuthentication, מכיוון שבהרבה התקנות מודרניות ישנם קבצי .d הדורסים את הערך של הקובץ sshd_config הראשי :
sudo grep -R "PasswordAuthentication" /etc/ssh/
נפוץ למצוא משהו כמו:
/etc/ssh/sshd_config.d/50-cloud-init.conf:PasswordAuthentication yes
/etc/ssh/sshd_config:PasswordAuthentication no
במקרה כזה, התצורה האפקטיבית תהיה "כן" מכיוון שקובץ 50-cloud-init.conf נטען לאחר מכן ודורס את הערך. ניתן לאמת את התוצאה הסופית ש-sshd מחיל באמצעות:
sudo sshd -T | grep passwordauthentication
כדי להשבית סיסמאות אמיתיות, ערוך את הקובץ האחראי (לדוגמה /etc/ssh/sshd_config.d/50-cloud-init.conf) והשאיר:
PasswordAuthentication no
לאחר מכן הפעל מחדש את שירות ה-SSH:
sudo systemctl restart ssh
ובדקו שוב עם:
sudo sshd -T | grep passwordauthentication
אם התוצאה תחזיר "לא", ניסיונות כניסה באמצעות סיסמה יידחו באופן מיידי . תוכניות כמו PuTTY יציגו שגיאה המציינת שהן אינן יכולות לספק אישורים מסוג סיסמה, אך לקוחות מבוססי סיסמה ימשיכו לתפקד ללא בעיה.
שילוב מפתחות SSH עם Fail2ban ואמצעים אחרים
כאשר מסירים את PasswordAuthentication מהמשוואה, הערך של Fail2ban עבור SSH הופך להיות יותר עזר מאשר קריטי, מכיוון שלבוטים אין אפילו שדה להזנת הסיסמה . למרות זאת, מומלץ לשמור על jail של sshd פעיל מכיוון שהוא משמש כשכבה נוספת כנגד ניסיונות חריגים או שימוש לרעה במפתח.
אם תוסיף חומת אש מגבילה (iptables/nftables, UFW, firewalld) ואם מתאים, רשימות בקרת גישה עם TCP Wrappers לשילוב זה של מפתחות SSH בלבד + Fail2ban + נעילת root + רשימות AllowUsers/AllowGroups מכווננות היטב , תצמצם את הסבירות לפריצה בכוח ברוט לרמה זניחה.
בסביבות רגישות אף יותר, ניתן ללכת צעד קדימה ולהכניס אימות דו-שלבי (2FA) עבור SSH , באמצעות מודולים כמו Google Authenticator או דומים דרך PAM, או אפילו להגביל את מי שיכול לגשת לפורט SSH באמצעות VPN ייעודי.
עם כל האלמנטים הללו משולבים היטב - זיהוי ניסיונות בלוג, תצורה מדוקדקת של sshd, שימוש נרחב ב-Fail2ban, מפתחות SSH במקום סיסמאות, ובמידת הצורך, בקרות IP - שרת לינוקס יכול לעמוד בפני התקפות Brute-Force מתמשכות על SSH ושירותים חשופים אחרים מבלי להתאמץ , תוך שמירה על גישה נוחה ומאובטחת למנהלים.