הפעלה מחדש של שירות ב-OpenVPN up: hooks עדיפים על tun0.device
יחידת התקן עוקבת אחר הממשק, לא אחר החיבור. בחרו up או route-up עבור התנאי שהשירות צריך, ואז שלחו הפעלה מחדש לא חוסמת.
חיבור שירות תלוי ל-tun0.device נראה כמו מינוי למנהרה, וזה לא. יחידת התקן משקפת שהממשק קיים, מה שיכול להישאר נכון לאורך חיבור שנכשל וההתחברות מחדש שאחריו. אז השירות פועל ברגע הלא נכון, או בכלל לא, בהתאם לשאלה אם הממשק נעלם בינתיים. ה-hook שמתאר את האירוע שבאמת מעניין אתכם הוא זה ש-OpenVPN קורא, לא זה ש-systemd מסיק.
החליטו איזה תנאי דרוש לשירות לפני בחירת הטריגר, כי שלושת המועמדים אינם ניתנים להחלפה.
מה יחידת ההתקן באמת עוקבת אחריו
systemd יוצר יחידת התקן מתוך תפיסת הקרנל את ממשק הרשת, לכן tun0.device הופך לפעיל כשהממשק מופיע ולא פעיל כשהוא מוסר. עם persist-tun, הפעלה מחדש רכה משאירה את הממשק במקומו, כך שהיחידה לעולם אינה מהבהבת ושום דבר הקשור אליה אינו מופעל. אפילו בלי התמדה, היחידה אינה אומרת דבר על נתיבים, DNS או האם הצד המרוחק עונה.
זה הופך אותה לתחליף גרוע ל'ה-VPN מוכן'. מאזין שצריך רק את הכתובת המקומית עשוי להסתפק בקיומו של הממשק, בעוד שירות שקורא ליישום ברשת המרוחקת צריך נתיבים ונגישות, שיחידת ההתקן אינה יכולה לבטא.
up, route-up ו-up-restart אומרים דברים שונים
up רץ לאחר שהתקן TUN/TAP נפתח והממשק הוגדר, וזה הרגע הנכון למאזין שקושר את הכתובת שהוקצתה. route-up רץ לאחר התקנת נתיבים, בכפוף לכל עיכוב נתיב מוגדר, ומתאים לעבודה שדורשת ששלב הנתיבים יושלם. אף אחד מהם לא מוכיח שהיישום המרוחק עונה. הבחירה ביניהם היא שאלה של מה שהשירות צריך, לא של איזה hook נשמע גמור יותר.
עם persist-tun, הפעלות מחדש משתמשות שוב בהתקן, כך ש-up אינו רץ שוב אלא אם up-restart מוגדר. אפשרות זו מפעילה את סקריפט ה-up עבור מחזור החיים המתועד של הפעלה מחדש, והסביבה שלו מצומצמת לעומת התחלה ראשונה. סקריפט שמניח את הסביבה המלאה עובד בחיבור הראשון ונכשל בחיבור הבא.
שלחו את הפעולה בלי להמתין לה
hook שקורא ל-systemctl restart באופן סינכרוני עלול להיקלע למבוי סתום מול יחידה שסדרה ממתין למנהרה. systemctl --no-block try-restart vpn-dependent.service מכניס את המשימה לתור וחוזר, מה שמונע מה-hook לחסום את החיבור שהוא הגיב לו. try-restart פועל רק על יחידה פועלת, בעוד restart גם מתחיל יחידה לא פעילה; בחרו בכוונה, לא מתוך הרגל.
הכנסה לתור אינה אימות. ה-hook מחזיר הצלחה ברגע שהמשימה מתקבלת, לכן הבדיקה חייבת להתרחש ביומן יחידת היעד או במצב המאזין בפועל שלה.
מדיניות ההפעלה מחדש נמצאת ביחידה, לא ב-hook
יחידת oneshot עם RemainAfterExit=yes נשארת פעילה לאחר שהפקודה שלה מסתיימת, ובקשת התחלה שנייה לא עושה דבר כי systemd רואה אותה ככבר התחילה. זו תכונה שצריך לתכנן סביבה, לא פגם שיש לעקוף בקריאות התחלה חוזרות. אם הפעולה חייבת לרוץ בכל חיבור, היחידה צריכה צורה שמאפשרת זאת.
After= מסדר יחידות, ו-BindsTo= קושר תוחלות חיים, אבל אף אחד מהם לא אומר 'הפעל מחדש את זה בכל פעם שה-VPN מתחבר מחדש'. יחידה הקשורה למנהרה נעצרת כשהמנהרה נעצרת; היא אינה מפעילה את עצמה מחדש כשהמנהרה חוזרת, אלא אם משהו מתחיל אותה שוב.
בדקו שלוש התחברויות מחדש, לא אחת
אתחול קר, הפעלה מחדש מלאה של הלקוח והתחברות מחדש רכה כל אחד מתרגל נתיב אחר. ההתחברות מחדש הרכה היא זו שחושפת up-restart חסר, סביבה מצומצמת או יחידת התקן שמעולם לא הפכה ללא פעילה. הריצו את שלושתם ואשרו את שני הכיוונים: השירות פועל כשהמנהרה עולה, והוא אינו מופעל מחדש בשינויי קישור לא קשורים כמו נדידת Wi-Fi.
שמרו על נתיב התאוששות עצמאי כשהשירות התלוי נושא את גישת הניהול שלכם. hook שמפעיל מחדש את הדבר שדרכו אתם מחוברים הוא שינוי שעלול לנעול אתכם בחוץ.