חומת אש ב-VPS: לפתוח רק את פורט ה-VPN ואז להוכיח את זה
פורט אחד חייב להישאר ציבורי, אחרת שום לקוח לא יתחבר. דחו את השאר, הפרידו את ההעברה מהכניסה, והשאירו מסלול התאוששות שבדקתם מראש.
חומת אש שמתירה רק את פורט ה-VPN אינה כלל אחד. אלה שלוש החלטות נפרדות שמתייחסות במקרה לאותו מספר פורט: שרשרת הקלט קובעת מה יכול להגיע לתהליך מקומי, שרשרת ההעברה קובעת מה יכול לעבור דרך המארח בשם לקוחות המנהרה, וטבלת ה-NAT כותבת מחדש את כתובת המקור בדרך החוצה. טעות באחת מהן ולעיתים רחוקות התוצאה היא הפסקה נקייה. תקבלו מארח שמקבל לקוחות אבל לא טוען דבר, או מארח שנראה סגור עד שמישהו קורא את סדר השרשראות.
הפורט היחיד שאי אפשר לסגור
מאזין ה-VPN חייב לקבל חיבורים מכתובות שאינכם יכולים לחזות, ולכן הוא שירות ציבורי בהגדרה. זה החריג היחיד שהתכנון בנוי סביבו: פורט UDP אחד ל-OpenVPN, פורט UDP אחד ל-WireGuard, פורט TCP אחד ל-VPN מבוסס SSL. כל השאר שייך לצד שאחרי המנהרה, כלומר שירותי יישומים צריכים להיקשר לכתובת המנהרה או ל-loopback ולא לכל ממשק.
אבל קישור אינו אכיפה. תהליך שנקשר ל-0.0.0.0 נגיש רק אם כלל מתיר אותו, ומדיניות ברירת המחדל היא הגיבוי לתעבורה שלא תאמה שום כלל, לא הכלל שמנהל את הפורט. הרשאה שממוקמת מעל הדחייה שלכם היא עדיין הרשאה, והעברת שירות מהכתובת הציבורית היא שיפור עצמאי ולא תחליף לשרשרת.
קלט, העברה ו-NAT עונים על שאלות שונות
תעבורת הקלט מיועדת למארח עצמו, ולכן שם נמצאים מאזין ה-VPN והמסלול הניהולי. תעבורת ההעברה עוברת דרך המארח, ולקוחות המנהרה זקוקים לה יחד עם net.ipv4.ip_forward=1. התצורה הקלאסית השבורה למחצה מתירה את הזרימה היוצאת ושוכחת את כיוון החזרה, כך שהלקוח משלים את לחיצת היד ואז שום דבר לא נטען; כלל conntrack לתעבורה מבוססת וקשורה מכסה את הכיוון הזה.
NAT הוא השאלה השלישית. בלי כתיבה מחדש ב-postrouting, חבילות מועברות יוצאות עם מקור פרטי של המנהרה ונזרקות במעלה הזרם, כי שום רשת מעבר למארח לא יודעת לנתב את הבריכה חזרה. קידומת המקור בכלל הזה חייבת להתאים לבריכת ה-VPN, לא לכתובת של המארח עצמו, וכך גם בכלל ההעברה שמזכיר את תת-הרשת של הלקוחות.
IPv6 הוא מדיניות שנייה, לא מחשבה מאוחרת. מארח עם שרשרת IPv4 קפדנית ומדיניות פתוחה ב-ip6tables לא סגר דבר; השירותים עדיין נגישים דרך המשפחה השנייה. או לשקף את מערך הכללים עם ip6tables או להשבית IPv6 בכוונה בממשק הציבורי, ולרשום מה בחרתם.
בסיס שאפשר לקרוא במעבר אחד
התחילו מדחייה, ואז הוסיפו רק את מה שהמארח צריך. קודם loopback ותשובות, אחר כך המסלול הניהולי, אחר כך מאזין המנהרה, אחר כך מדיניות ההעברה ללקוחות:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
iptables -A INPUT -p udp --dport 1194 -m conntrack --ctstate NEW -j ACCEPT
sysctl -w net.ipv4.ip_forward=1
iptables -A FORWARD -i tun0 -o eth0 -s 10.8.0.0/24 -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADEשמות הממשקים, הפורט והבריכה הם מצייני מקום; קראו אותם מהשרת במקום להעתיק אותם. שמירת התוצאה חשובה כמו כתיבתה, כי מערך כללים שחי רק בזיכרון נעלם באתחול הבא ופותח את המארח מחדש בשקט. הפכו אותו לקבוע עם המנגנון של ההפצה, ושמרו עותק מחוץ למכונה ליום שבו המכונה לא תעלה.
לסגור את הפורט האחרון בלי לאבד את המארח
יש מלכוד בתכנון. אם SSH קיים רק דרך המנהרה, שירות VPN שנכשל לוקח איתו את SSH, והדרך היחידה חזרה עשויה להיות קונסולה שלא פתחתם מעולם. לפני שתסגרו את הפורט הציבורי האחרון, ודאו שהקונסולה הזו קיימת ושאתם באמת יכולים להשתמש בה, או השאירו מסלול ניהולי צר אחד שאינו תלוי במנהרה: SSH מכתובת קבועה, מפתחות בלבד, אימות סיסמה כבוי.
החילו את השינוי ממושב שכבר מבוסס, לא דרך החיבור שאתם עומדים לסנן. תזמנו חזרה אחורה כדי שטעות תפוג במקום להפוך לקבועה, למשל משימת systemd-run --on-active=10min שמשחזרת את מערך הכללים הקודם, והשאירו מושב SSH שני פתוח בזמן שאתם בודקים את הראשון. אחר כך ודאו שמשימת החזרה באמת מופעלת, כי התאוששות שלא נבדקה זהה להיעדר התאוששות.
לאמת את המסלול, לא את הסקריפט
קראו את הכללים הנטענים, לא את הקובץ שאמור היה לטעון אותם. ממארח חיצוני מורשה, ודאו ש-רק הפורטים המיועדים עונים; מתוך המנהרה, ודאו שהשירותים שרציתם לפרסם נגישים. מדיניות דחייה כברירת מחדל שחוסמת גם תעבורת מנהרה נראית זהה לנעילה עובדת עד שמישהו מנסה להשתמש בה.
iptables -S
iptables -t nat -S
ss -lntup
ip -4 addr showרשמו את הפורט המותר, את בריכת הלקוחות, את ממשק המנהרה, את המקור הניהולי ואת נוהל הקונסולה לצד התצורה. השינוי הבא בבריכה או בשם הממשק חייב להתאים גם במסנן וגם בכלל ה-NAT, אחרת המארח חוזר למצב חצי פתוח בלי שאיש ישים לב.
הרגל אחד שווה יותר ממערך הכללים: אחרי כל שינוי, הוכיחו את מסלול ההעברה בבקשת לקוח ואת מסלול ההתאוששות במושב שני. נעילה שלא השתמשתם בה היא השערה.