הקשחת SSH בלינוקס לשנת 2026: הצפנה פוסט-קוונטית, Ed25519 ותעודות CA
מדריך מעשי להקשחת SSH בלינוקס לשנת 2026: מפתחות Ed25519, הצפנה פוסט-קוונטית עם mlkem768x25519, הגדרות sshd_config, Fail2ban, MFA ותעודות SSH-CA. דוגמאות עבודה שנבדקו על Debian 13, Ubuntu 24.04 ו-RHEL 10.
הקשחת SSH בשנת 2026 פירושה שילוב של ארבעה שינויים בסיסיים ב-sshd_config: השבתת אימות סיסמאות, השבתת התחברות root ישירה, מעבר למפתחות Ed25519, והפעלת הצפנה פוסט-קוונטית מסוג mlkem768x25519-sha256 ב-OpenSSH 10 ומעלה. השילוב הזה חוסם את מרבית וקטורי ההתקפה הנפוצים, כולל התקפות "אחסן עכשיו, פענח מאוחר יותר", ומתאים גם לשרתים בודדים וגם לפריסות ארגוניות עם מאות מארחים.
OpenSSH 10.0 (אפריל 2025) הגדיר את mlkem768x25519-sha256 כברירת המחדל לחילוף מפתחות פוסט-קוונטי; גרסה 10.1 מציגה אזהרה כאשר החיבור אינו פוסט-קוונטי.
Ed25519 הוא סוג המפתח המומלץ ל-2026. הוא 256 סיביות בלבד, מהיר יותר מ-RSA וחסין לחלק מהתקפות ה-side-channel שפגעו ב-ECDSA.
חמש הפעולות בעלות ההשפעה הגבוהה ביותר: PasswordAuthentication no, PermitRootLogin no, MaxAuthTries 3, AllowUsers, ו-Fail2ban.
ב-Ubuntu 24.04 ומעלה עדיף להשתמש בקבצי drop-in תחת /etc/ssh/sshd_config.d/ במקום לערוך את הקובץ הראשי.
בסביבה ארגונית, החליפו את authorized_keys לכל שרת ב-SSH Certificate Authority עם תעודות קצרות טווח (TTL של שעות, לא שנים).
לעולם אל תסגרו את החיבור הפעיל לפני שאישרתם התחברות חדשה בטרמינל נפרד; sshd -t לפני כל systemctl reload sshd.
מדוע SSH הוא חזית ההתקפה הראשונה בשרתי לינוקס
כל שרת לינוקס עם כתובת IP ציבורית סופג ניסיונות התחברות SSH אוטומטיים תוך דקות מרגע העלאתו לרשת. הבוטנטים סורקים את כל טווח ה-IPv4, מכוונים לפורט 22, ומריצים מילוני משתמשים וסיסמאות במהירות של אלפי ניסיונות בשנייה. בלוגים של journalctl -u ssh בשרת חשוף אני רואה בממוצע 60,000 עד 250,000 ניסיונות התחברות כושלים ביממה, וזה הבסיס, לא השיא.
המצב בשנת 2026 מחריף בגלל שני כוחות מקבילים. ראשית, זמינות של מודלי שפה גדולים מוזילה את עלות ההנדסה החברתית ואת כתיבת ה-payload. שנית, איום ה"אחסן עכשיו, פענח מאוחר יותר" (Store-Now-Decrypt-Later, או SNDL) הפך מוחשי: יריב יכול להקליט תעבורת SSH מוצפנת היום ולפענח אותה בעתיד, כאשר יהיו זמינים מחשבי קוונטים חזקים מספיק להריץ את אלגוריתם Shor. בדיוק מסיבה זו העביר צוות OpenSSH את חילוף המפתחות לפוסט-קוונטי כברירת מחדל, עוד לפני שקיים איום מיידי.
הבשורה הטובה: SSH הוא פרוטוקול מהונדס היטב, ורוב פני ההתקפה נסגר על ידי חמישה עד שבעה שינויי הגדרה שלוקחים פחות משעה ליישום. אני עובר עליהם כאן לפי סדר עדיפויות, עם דוגמאות עבודה שנבדקו על Debian 13 (Trixie), Ubuntu 24.04 LTS ו-RHEL 10. אגב, את רוב ההגדרות האלה גיליתי בדרך הקשה, אחרי שספגתי אירוע של חדירה מוצלחת דרך חשבון בדיקה שנשכח פתוח לרשת.
איזה סוג מפתח SSH מומלץ בשנת 2026: Ed25519 מול RSA
ההמלצה שלי (ושל הרוב המכריע של קהילת הקריפטוגרפיה) היא פשוטה: Ed25519 כברירת מחדל, עם RSA 3072 או 4096 סיביות רק כאשר תאימות לציוד ישן מכריחה זאת. סוגי מפתח DSA ו-ECDSA (P-256/P-384) נחשבים כיום לגישה נטושה, בעקבות חולשות ב-nonce generation שהובילו בעבר לחשיפת מפתחות פרטיים.
מאפיין
Ed25519
RSA 4096
ECDSA P-256
גודל מפתח
256 סיביות
4096 סיביות
256 סיביות
מהירות יצירה
מיידית
2-30 שניות
מיידית
עמידות ל-side-channel
גבוהה (דטרמיניסטי)
בינונית
נמוכה
תמיכה ב-OpenSSH
≥ 6.5 (2014)
אוניברסלית
≥ 5.7
תמיכה ב-FIPS 140-3
לא (עדיין)
כן
כן
המלצה 2026
ברירת מחדל
Fallback ישן
הימנעו
יצירת מפתח Ed25519 חדש היא שורה אחת. שימו לב לדגל -a 100: הוא מגדיל את מספר סבבי ה-KDF לשמירת המפתח הפרטי מוצפן על הדיסק, ומקשה משמעותית על התקפות offline אם המחשב האישי נגנב.
ssh-keygen -t ed25519 -a 100 -C "yuki@laptop-2026" -f ~/.ssh/id_ed25519
# העתקת המפתח הציבורי לשרת מרוחק
ssh-copy-id -i ~/.ssh/id_ed25519.pub [email protected]
# אימות שהמפתח פועל לפני השבתת סיסמאות
ssh -i ~/.ssh/id_ed25519 [email protected] whoami
הצפנה פוסט-קוונטית ב-OpenSSH 10, מה השתנה
OpenSSH 9.9 (אוקטובר 2024) הוסיף את mlkem768x25519-sha256, שילוב היברידי של ML-KEM-768 (המוגדר ב-FIPS 203) עם Curve25519. OpenSSH 10.0 (אפריל 2025) הפך את האלגוריתם הזה לברירת המחדל, ו-OpenSSH 10.1 (אוקטובר 2025) מציג אזהרה כאשר חילוף המפתחות אינו פוסט-קוונטי: WARNING: connection is not using a post-quantum key exchange algorithm.
הסיבה לדחיפות היא איום SNDL. יריב יכול להקליט היום את כל תעבורת ה-SSH המוצפנת של הארגון שלכם, לאחסן אותה בזול, ולהמתין לזמינות מחשב קוונטי בעל אלפי qubits לוגיים. באותו רגע כל סוד שהוצפן ב-Curve25519 טהור נחשף retroactively. ML-KEM שובר את הכלכלה הזאת: הוא מבוסס על בעיית Module Learning With Errors, שלא ידוע לה פתרון קוונטי יעיל. כדאי לקרוא על הרקע התכנוני בדף OpenSSH הרשמי לפוסט-קוונטי.
בדיקת גרסה ואלגוריתמים נתמכים
# בדיקת גרסת OpenSSH
ssh -V
# רשימת אלגוריתמי חילוף מפתחות שהלקוח תומך בהם
ssh -Q kex
# רשימת אלגוריתמים שהשרת מציע (מהצד הלקוח)
ssh -vv [email protected] 2>&1 | grep -i "kex"
הגישה שאני ממליץ עליה: לא לגעת ב-/etc/ssh/sshd_config הראשי כלל, אלא ליצור קובץ drop-in ייעודי תחת /etc/ssh/sshd_config.d/. הגישה הזאת שורדת שדרוגי חבילה, קלה לביקורת ב-Git, ומאפשרת לחלק את ההקשחה לשכבות לוגיות (חילוף מפתחות, אימות, ניהול סשן). כמו כן, אם משהו משתבש, אפשר לרנום את הקובץ עם סיומת אחרת ולהחזיר את השרת למצב עבודה תוך שנייה.
הנה תבנית drop-in שמכסה את מרבית פני ההתקפה. שמרו אותה ב-/etc/ssh/sshd_config.d/99-hardening.conf:
# --- אימות ---
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
PermitEmptyPasswords no
MaxAuthTries 3
LoginGraceTime 20
UsePAM yes
# --- בקרת גישה ---
AllowGroups ssh-users
AllowTcpForwarding no
X11Forwarding no
PermitTunnel no
GatewayPorts no
AllowAgentForwarding no
# --- ניהול סשן ---
ClientAliveInterval 300
ClientAliveCountMax 2
TCPKeepAlive no
MaxSessions 2
MaxStartups 10:30:60
# --- לוגים ---
LogLevel VERBOSE
SyslogFacility AUTH
לפני restart, אמתו את התחביר עם sshd -t. אם הפלט ריק, ההגדרה חוקית. אם יש שגיאה, היא תודפס עם שם הקובץ ומספר השורה.
sudo sshd -t
# אם ריק, ניתן להמשיך:
sudo systemctl reload sshd
# בטרמינל נפרד, ודאו שאתם יכולים עדיין להתחבר
ssh -i ~/.ssh/id_ed25519 [email protected]
כיצד להשבית התחברות root ולהגביל משתמשים מורשים
התחברות root ישירה היא אחד משני מקורות הכשל הנפוצים ביותר בהקשחת SSH. גם עם אימות מבוסס מפתח, אין סיבה להשאיר את root נגיש: כל ניסיון פריצה מתחיל בניחוש שם המשתמש, וה"root" הוא הכתובת הראשונה שכל בוטנט מנסה. השתמשו במשתמש רגיל עם הרשאות sudo.
עבור חשבונות אוטומציה (לדוגמה, deploy-bot ב-CI/CD), הגבילו את המפתח לפקודה בודדת דרך authorized_keys. הפורמט הזה הוא הגנת עומק חשובה: גם אם המפתח דולף, הוא יכול להריץ רק את הפקודה המוגדרת מראש, מ-IP ספציפי, ללא PTY או port-forwarding.
# ~/.ssh/authorized_keys של deploy-bot
from="10.0.0.15",command="/usr/local/bin/deploy.sh",no-pty,no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA... deploy-key-2026
כדי לחזק את הבקרה בשכבת ה-firewall, שלבו את ההגבלות עם חוקי nftables להקשחת שרתים בלינוקס. הכלל להלן דוגם פורט SSH לרשימת IP מקור מותרת בלבד:
גם אחרי השבתת אימות סיסמאות, בוטים ימשיכו לנסות. הם ממלאים את הלוגים ברעש שמסתיר תוקפים אמיתיים, וצורכים משאבי CPU בכל ניסיון SSH handshake. Fail2ban היא הפתרון הסטנדרטי: היא סורקת את /var/log/auth.log (או journald) ומזרימה חוקי חסימה זמניים ל-nftables או ל-iptables כשמתגלים ניסיונות כשל חוזרים מאותו IP.
הגדרות בסיסיות עבור SSH נמצאות ב-/etc/fail2ban/jail.d/sshd.local. הדוגמה להלן חוסמת IP לשעה אחרי 4 ניסיונות כושלים בטווח של 10 דקות, ומעלה מכסה של 24 שעות אחרי הפרה חוזרת (recidive):
לניתוח מעמיק יותר של Fail2ban, כולל custom filters, אינטגרציה עם Cloudflare, וטיפוסי jail מתקדמים, ראו את המדריך המלא ל-Fail2ban להגנה מפני התקפות brute force. שם מפורטות גם החולשות ב-Fail2ban עצמה (CVE-2021-32749 לדוגמה) והצעדים לצמצומן.
אימות רב-שלבי (MFA) עבור SSH
MFA מוסיף שכבת הגנה שנייה: גם אם מפתח פרטי דולף (מחשב נייד גנוב, גיבוי שנחשף), התוקף עדיין צריך גישה למכשיר השני. הפתרון הרווח הוא Google Authenticator עם TOTP (RFC 6238). הוא פתוח, ללא תלות בספקים, ותומך בכל אפליקציית authenticator תקנית (Aegis, Bitwarden, 1Password, וכן Google Authenticator).
# התקנה על Debian/Ubuntu
sudo apt install libpam-google-authenticator
# עבור כל משתמש שיאמת עם TOTP:
google-authenticator -t -d -f -r 3 -R 30 -w 3
# -t : TOTP (מבוסס-זמן)
# -d : disallow token reuse
# -r 3 -R 30 : 3 ניסיונות ב-30 שניות
# -w 3 : חלון סבילות של ±3 קודים
ההגדרה AuthenticationMethods publickey,keyboard-interactive:pam מחייבת שני גורמים ברצף: קודם מפתח SSH ציבורי, ואז TOTP. הפסיק (,) הוא AND לוגי, לא OR. הבחנה קטנה שגרמה לי שעה של דיבאג פעם אחת, כשלא הבנתי למה השרת מבקש רק מפתח.
SSH Certificate Authority ברמה ארגונית
מודל authorized_keys אינו סקילבילי מעבר לכמה עשרות שרתים. כל הוספה או הסרה של גישת משתמש מחייבת עדכון של כל שרת בנפרד, וגילוי מפתח שנשכח בשרת ישן הוא סיפור אמיתי שקרה ליותר מארגון אחד. SSH Certificate Authority (SSH-CA) פותר את זה: CA אחד חותם מפתחות משתמש, והשרתים בוטחים ב-CA, לא במפתחות עצמם.
היתרונות: תעודות עם תפוגה מובנית (TTL של 8 שעות במקום מפתחות ללא תפוגה), עקרון המשתמש (principals) שממפה חשבונות שרת לזהויות, וביטול תעודות מרוכז דרך Revoked Keys File. הנה תרחיש הקמה מינימלי. מומלץ ליצור שני CA נפרדים (אחד ל-hosts, אחד ל-users) כדי לאפשר סיבוב עצמאי:
# במכונת ה-CA (מבודדת, לא מחוברת לרשת ציבורית)
mkdir -p /etc/ssh-ca && cd /etc/ssh-ca
# יצירת שני מפתחות CA
ssh-keygen -t ed25519 -f user_ca -C "user-ca-2026" -N ""
ssh-keygen -t ed25519 -f host_ca -C "host-ca-2026" -N ""
# חתימה על מפתח host של שרת (תעודה לשנה)
ssh-keygen -s host_ca \
-I "web-01.example.com" \
-h \
-n "web-01.example.com,web-01" \
-V +52w \
ssh_host_ed25519_key.pub
# חתימה על מפתח משתמש (תעודה ל-8 שעות בלבד)
ssh-keygen -s user_ca \
-I "yuki@ops-team" \
-n "yuki,deploy" \
-V +8h \
id_ed25519.pub
לפרטים מלאים על תפעול CA, כולל אוטומציה של הנפקת תעודות, אינטגרציה עם HashiCorp Vault, וסיבוב מפתחות, ראו את מדריך Rocky Linux ל-SSH CA. בפרויקט אחרון שלי, פרסתי CA כזה על צי של 200 שרתים, וה-onboarding של הנדסאי חדש התקצר מ-45 דקות לפחות מ-3.
שרתי קפיצה ו-ProxyJump
ארכיטקטורה מבוססת שרת קפיצה (jump host, לפעמים "bastion") מרכזת את גישת ה-SSH לנקודת כניסה אחת מוקשחת. שרתי הפרודקשן עצמם מקבלים SSH רק מ-IP של ה-bastion, ואילו ה-bastion חשוף לאינטרנט אך עם הקשחה מקסימלית, MFA, וניטור מלא.
OpenSSH 7.3 ומעלה תומך בדגל -J ובהוראה ProxyJump, שמייתרים את הצורך במפתחות בשרת הקפיצה עצמו. החיבור נבנה end-to-end מהלקוח לשרת המטרה, כך שגם אם ה-bastion נפרץ, המפתח הפרטי של המשתמש לא נחשף שם.
# בשורת פקודה
ssh -J bastion.example.com web-01.internal
# ב-~/.ssh/config
Host bastion
HostName bastion.example.com
User yuki
IdentityFile ~/.ssh/id_ed25519
Host *.internal
ProxyJump bastion
User deploy
IdentityFile ~/.ssh/id_ed25519
ForwardAgent no
שימו לב:ForwardAgent yes על שרת bastion הוא anti-pattern מסוכן. הוא מאפשר ל-root על ה-bastion להשתמש בסוכן ה-SSH שלכם כדי להתחבר לכל שרת שהמפתח שלכם מורשה בו. השאירו ForwardAgent no תמיד, והשתמשו ב-ProxyJump במקום.
ניטור וביקורת של אירועי SSH
הקשחה בלי ניטור היא חצי עבודה, ואם אתם לא רואים ניסיונות התחברות אתם גם לא רואים חדירות מוצלחות. ה-baseline המינימלי כולל: journalctl -u ssh לניתוח בזמן אמת, auditd לשמירת רשומות עמידות ב-tampering, ואיסוף מרכזי (Wazuh, Loki, Graylog) לשמירת רצף אירועים מעבר לגבולות המכונה.
# צפייה בכל אירועי אימות SSH מ-24 שעות אחרונות
journalctl -u ssh --since "24 hours ago" | grep -E "Accepted|Failed|Invalid"
# סיכום IP-ים עם ניסיונות כושלים
journalctl -u ssh --since today | \
grep "Failed password" | \
awk '{print $(NF-3)}' | \
sort | uniq -c | sort -rn | head -20
# ניטור בזמן אמת של סשנים מוצלחים
journalctl -f -u ssh | grep --line-buffered "Accepted"
כללי auditd ייעודיים מבטיחים שגם אם תוקף מוחק את /var/log/auth.log, השרשרת המקורית נשמרת ב-/var/log/audit/audit.log. הוסיפו ל-/etc/audit/rules.d/ssh.rules:
# מעקב על כל שינוי בקבצי הגדרה של SSH
-w /etc/ssh/sshd_config -p wa -k ssh-config-change
-w /etc/ssh/sshd_config.d/ -p wa -k ssh-config-change
# מעקב על שינויים ב-authorized_keys של כל המשתמשים
-w /root/.ssh/authorized_keys -p wa -k ssh-auth-change
-a always,exit -F dir=/home -F path=authorized_keys -F perm=wa -k ssh-auth-change
שינוי פורט הוא security through obscurity. הוא לא עוצר תוקף ממוקד, אך מפחית בכ-95% את רעש הבוטנטים בלוגים. אני ממליץ עליו כשכבת עומק, לא כתחליף להקשחה ממשית. פורטים מעל 1024 (למשל 2222) לא מחייבים root להאזין, אך פותחים אותם לניצול על ידי משתמשים לא-root אם sshd יורד.
האם Fail2ban עדיין נחוץ אם השבתי אימות סיסמאות?
כן. Fail2ban מפחית משמעותית את עומס ה-CPU של handshakes כושלים, מקטין את הלוגים לניתוח יעיל יותר של איומים אמיתיים, וחוסם גם ניסיונות פרוטוקול-לבל שאינם קשורים לאימות (כמו סריקות אלגוריתמים ישנים). היא לא מיותרת, היא משלימה.
מה ההבדל בין sntrup761x25519 לבין mlkem768x25519?
שניהם אלגוריתמי חילוף מפתחות היברידיים פוסט-קוונטיים. sntrup761x25519-sha512 היה ברירת המחדל של OpenSSH מגרסה 9.0 (2022) ומבוסס על NTRU Prime. mlkem768x25519-sha256 החליף אותו כברירת מחדל מגרסה 10.0 (2025) והוא הבחירה המועדפת: הוא מהיר יותר, מבוסס על התקן NIST FIPS 203, ותמיכתו רחבה יותר בין ספריות קריפטו.
כיצד לבטל תעודת SSH שדלפה?
עדכנו את קובץ RevokedKeys בכל שרת עם ssh-keygen -k -f /etc/ssh/revoked_keys /path/to/leaked_key.pub, ולאחר מכן טענו מחדש את sshd. עדיף לאוטומט את התהליך דרך configuration management (Ansible/Salt) כדי להבטיח הפצה מיידית לכל השרתים. תעודות עם TTL קצר (שעות) מפחיתות דרמטית את החלון של דליפה.
האם הצפנה פוסט-קוונטית ב-SSH מגן על הזהות שלי מפני זיוף עתידי?
לא במלואו. OpenSSH 10.x מגן על סודיות הסשן באמצעות ML-KEM לחילוף מפתחות, אך חתימות הזהות עדיין משתמשות ב-Ed25519 או RSA, ושניהם שבירים בפני מחשב קוונטי. הפער הזה סגור למחקר: תקינת ML-DSA (FIPS 204) לחתימות SSH נמצאת בפיתוח ב-IETF וצפויה להיכנס ל-OpenSSH בגרסאות עתידיות.