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

המעבר דורש שלוש בדיקות, לא מנהרה אחת

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

לכן בדיקת כל מנהרה בנפרד מוכיחה כל כך מעט. פינג לכתובת ה-LAN של המרכז מפעיל את ההחלטה הראשונה, ופינג למרכז מהמטה מפעיל את השלישית. החבילה שנכשלת מקורה במאגר המשתמשים ויעדה האתר השני, אז רשמו קודם את הקידומות האלה. כאן המאגר הוא 10.80.0.0/24, ה-LAN של המרכז הוא 10.10.0.0/24 והמטה הוא 10.20.0.0/24.

דחפו את הקידומת המרוחקת אל הלקוח המרוחק

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

push "route 10.20.0.0 255.255.255.0"

נתיב שנדחף נכנס לתוקף כשהלקוח מתחבר, ולכן משתמש שנשאר מחובר לא רואה דבר עד שיתחבר מחדש. בדקו בלקוח: ip route get 10.20.0.50 ב-Linux, route print ב-Windows. הפלט צריך לנקוב בשם ממשק המנהרה.

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

תנו למרכז נתיב יציאה אמיתי

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

ip route get 10.20.0.50 from 10.80.0.25
sudo ip route add 10.20.0.0/24 via 172.30.0.2 dev s2s0

כאשר רגל האתר-לאתר היא עצמה OpenVPN, הנתיב יכול לחיות באותה תצורה עם כתובת המנהרה של העמית כשער: route 10.20.0.0 255.255.255.0 172.30.0.2. השער אינו אופציונלי. אם תשמיטו אותו, הצעד הבא נופל לברירת מחדל של המימוש, ששונה בין לקוח עם נקודה מרוחקת אחת למרכז עם כמה עמיתים.

IPsec מבוסס מדיניות שונה: הקרנל של המרכז שולח את החבילה לשער ה-LAN הרגיל שלו והמדיניות לוכדת אותה ביציאה, ולכן נתיב מנהרה או שלא עושה דבר או מוביל תנועה מעבר למדיניות. שימו לב למקור בפקודה שלמעלה, כי 10.10.0.1 במקום כתובת המאגר פירושו שהקרנל בחר כתובת שהצד המרוחק ידחה. גם iroute אינו התשובה; הוא אומר לשרת איזה לקוח מחזיק תת-רשת מאחורי המנהרה שלו, לא לאן לשלוח תנועה לאתר שלישי.

הרחיבו את הצד המרוחק אל מאגר המשתמשים

המטה כבר מכסה את ה-LAN של המרכז, 10.10.0.0/24. מאגר המשתמשים הוא קידומת שנייה והוא חייב להיות גם בבוררים, אחרת שום מדיניות לא מכסה תשובה המיועדת ל-10.80.0.25. כל עמית נוקב באותו זוג של קבוצות קידומות מהצד שלו:

# strongSwan swanctl.conf, on the hub
local_ts  = 10.10.0.0/24, 10.80.0.0/24
remote_ts = 10.20.0.0/24
# on the headquarters peer
local_ts  = 10.20.0.0/24
remote_ts = 10.10.0.0/24, 10.80.0.0/24

ה-local_ts של התקן אחד הוא ה-remote_ts של האחר. העתיקו את הבלוק של המרכז אל המטה והזוג מתהפך, ולכן ה-SA הבן לעולם לא עולה.

התחביר הישן יותר של ipsec.conf משתמש ב-leftsubnet מופרד בפסיקים. התאחדות האבטחה הפעילה שומרת על הבוררים שעליהם ניהלה משא ומתן, אז הקימו מחדש את המנהרה לאחר העריכה. בורר ששונה ב-10:00 ונבדק מול SA שעלה ב-09:40 עדיין נכשל, בעוד שקובץ התצורה נראה תקין כל הזמן.

לאחר מכן בדקו את הצעד האחרון. ip route get 10.80.0.25 בנקודת הקצה המרוחקת צריך להצביע אל תוך המנהרה. אם השירות משתמש בנתב LAN כשער ברירת המחדל שלו, גם הנתב הזה זקוק לנתיב החזרה, אחרת התשובה מתה שם. הרצת tcpdump -ni eth1 host 10.80.0.25 בקטע הזה מראה אם התשובה בכלל יצאה מנקודת הקצה.

אשרו את הזרימה במרכז

ההעברה חייבת להיות מופעלת והנתיב חייב להיות מותר. הגבילו את הכללים לשתי הקידומות במקום לקבל הכול בין הממשקים.

sysctl -w net.ipv4.ip_forward=1
iptables -I FORWARD -i tun0 -o s2s0 -s 10.80.0.0/24 -d 10.20.0.0/24 -j ACCEPT
iptables -I FORWARD -i s2s0 -o tun0 -s 10.20.0.0/24 -d 10.80.0.0/24 -j ACCEPT

סינון נתיב החזרה הוא הכשל השקט שלידו: כששתי הרגליים על ממשקים שונים, rp_filter=1 יכול להפיל את התשובה בעוד מונה כלל הקבלה אינו זז. השוו את iptables -vnL FORWARD לפני ואחרי ניסיון. כלל שלעולם לא גדל לא מגיעים אליו, אז הסתכלו שכבה אחת למטה במקום לשכתב אותו.

אם רק קבוצה אחת זקוקה למעבר, שימו את הנתיב בקובץ לכל לקוח תחת client-config-dir במקום להרחיב את ה-push הגלובלי. Source NAT במרכז גם מסיר את הצורך בנתיב חזרה בצד המרוחק, אבל הוא מסתיר את כתובת המשתמש, ולכן היומנים של האתר המרוחק והכללים מבוססי הכתובות מפסיקים להבחין בין משתמשים.

אמתו מהלקוח, ואז בצעו חזרה אחורה בסדר הפוך

בדקו פורט TCP, לא רק ICMP, כי פינג יכול לעבור בעוד השירות נשאר חסום. nc -vz 10.20.0.50 445 ו-traceroute -n 10.20.0.50 מהלקוח מראים אם הצעד השני הוא כתובת המנהרה של המרכז. במרכז, tcpdump -ni tun0 host 10.20.0.50 ואותו מסנן בממשק האתר-לאתר: בקשה בשניהם בלי תשובה באף אחד מעבירה את הבעיה לצד המרוחק.

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

שמרו רשימת חזרה, כי ארבעה אובייקטים השתנו ושלושה קלים לשכוח: הנתיב שנדחף, הנתיב של המרכז, הבוררים וכללי חומת האש. בטלו אותם בסדר הפוך, הקימו מחדש את ה-SA, ונתנו למשתמש אחד להתחבר מחדש. חזרה חלקית משאירה נתיב שמצביע למנהרה שכבר לא מתאימה, וזה קשה לקריאה יותר מהדממה המקורית. המדריך של OpenVPN 2.6 מתעד את push, route ואת iroute עבור הגרסה שלכם.

מאמרים קשורים