החזיקו כמה מנהרות vpnc עם בדיקות לכל פרופיל
סקריפט החיבור מחדש מהחבילה מניח מנהרה אחת. תנו לכל פרופיל vpnc פורט משלו, בדקו שירות אמיתי, ושרשרו את הבדיקות בסדר קבוע אחד.
פרופיל vpnc אחד מתחבר מחדש בצורה נקייה אחרי נדידה; שלושה מהם שוברים בתורם זה את הסוקטים, הנתיבים ומצב הפותר של זה. סקריפט החיבור מחדש מהחבילה נכתב למנהרה אחת, ולכן הוא מפעיל מחדש כל פרופיל בכל פעם שאחד מהם למטה. תיקון זה דורש שלושה דברים: פורטים מקומיים נפרדים, בדיקה שבוחנת שירות אמיתי לכל פרופיל, ושרשרת מסודרת אחת שלעולם אינה מריצה שני חיבורים בו-זמנית.
תנו לכל פרופיל פורט מקומי משלו
פרופיל vpnc שנשאר על הפורט המקומי המוגדר כברירת מחדל מתחרה בפרופיל שכבר פועל. החיבור השני נכשל בזמן שהראשון מחזיק בפורט, ושורת הלוג נראית כמו בעיית שער ולא כמו התנגשות מקומית. במקום זאת קבעו שורה אחת לכל קובץ פרופיל:
Local Port 0אפס מאפשר לליבה לבחור פורט זמני, כך ששני פרופילים יכולים לקום בו-זמנית. תנו לכל קובץ שם על פי השער והקבוצה שהוא משרת, השאירו אותו קריא ל-root בלבד, ו התחברו תמיד עם הפרופיל המתאים ולא עם ברירת מחדל משותפת. קובץ ברירת מחדל משותף הוא הדרך שבה סקריפט מתחבר מחדש למנהרה הלא נכונה אחרי שמישהו שינה את שם הפרופיל.
קובצי פרופיל נושאים פרטי התחברות, ולכן הרשאות הן חלק מהתכנון ולא מסידור הבית. קובץ קריא לכולם תחת /etc/vpnc מוסר את סוד הקבוצה לכל משתמש מקומי. שמרו על מצב 0600 עם root כבעלים, ותנו לסקריפטים לקרוא את הקובץ כ-root במקום להעתיק סודות לארגומנטים. זו גם הסיבה שסקריפט בדיקה לא צריך אף פעם להדפיס את תוכן הקובץ ללוג.
בדקו שירות אחד לכל פרופיל, לא את כתובת המנהרה
בקשת הד לכתובת של המנהרה עצמה מוכיחה בעיקר שהממשק קיים. היא לא אומרת דבר על האם המארח שמאחוריו עדיין מגיע לאפליקציה שמצדיקה את המנהרה. הממשק יכול להיות למעלה בעוד הנתיב שמעבר לו כבר נעלם.
בדקו שירות אחד לכל פרופיל עם פסק זמן TCP קצר, וחברו מחדש רק את הפרופיל שהבדיקה שלו נכשלה. שתי שניות מפרידות בין נתיב מת לנתיב איטי, ובדיקת TCP אינה תלויה בכך ש-ICMP מותר במקום כלשהו לאורך הדרך. שנו רק את היעד ואת שם התצורה בין הפרופילים:
#!/bin/bash
set -eu
if ! nc -z -w 2 10.63.7.20 8443; then
/usr/sbin/vpnc-connect ops.conf
fiשמרו זאת כקובץ /usr/local/bin/ensure-vpn-ops.sh, הפכו אותו להרצה, וחזרו על כך לכל פרופיל בשינוי היעד של הבדיקה ושם התצורה בלבד. בדיקה שעונה על שאלת פרוטוקול שורדת שערים שמפילים הד אך ממשיכים להעביר את השירותים שחשובים למשתמשים.
שרשרו את הבדיקות כדי שלא יתחרו לעולם
סקריפט החיבור מחדש מהחבילה יכול לקרוא לבדיקות שלכם בסדר, והסדר הוא כל העניין. שתי קריאות vpnc-connect שרצות יחד כותבות מחדש את טבלת הניתוב בסדר שאיש אינו שולט בו, וכך פרופיל בריא מאבד את הנתיב שלו.
השאירו את הקריאות בחזית, הוסיפו השהיית התייצבות קצרה לממשק הבסיסי, ותזמנו את השרשרת מטבלת ה-cron של root, כי רק root יכול לכתוב מחדש את נתיבי המנהרה:
#!/bin/bash
sleep 20
/usr/local/bin/ensure-vpn-ops.sh
/usr/local/bin/ensure-vpn-lab.shשמרו על אותו סדר בין סקריפט האתחול לרשומת ה-cron, כי שרשרת שרצה בסדר אחר באתחול היא למעשה תוכנית אחרת. כשפרופיל אחד תלוי בנתיבים של אחר, הניחו את התלות ראשונה ותנו לבדיקה המאוחרת להיכשל בלי נזק בזמן שהמנהרה המוקדמת עדיין עולה.
עקבו אחרי הלוג, ואז שברו אחת בכוונה
רשמו שורה אחת לכל הרצה עם הפרופיל, יעד הבדיקה, התוצאה והפעולה שננקטה. בלי זה, מנהרה שמרפרפת כל דקה נראית בדיוק כמו אחת שמעולם לא נפלה, ובאג בבדיקה אינו ניתן להבחנה מהפסקת שער. הלוג גם מוכיח שהשרשרת נגעה רק בפרופיל שנכשל. כתבו אותו במקום ששורד אתחול, אחרת הראיות עוזבות עם התהליך.
ואז שברו מנהרה בכוונה וצפו במה שקורה. עצרו פרופיל אחד וודאו אילו תהליכים ונתיבים עדיין קיימים:
pgrep -a vpnc
ip -4 route show | grep -E '10[.]63|10[.]90'
tail -n 5 /var/log/ensure-vpn.logרק הפרופיל שנעצר אמור להתחבר מחדש, והסשנים האחרים אמורים לשמור גם על התהליכים וגם על הנתיבים שלהם. אם שני פרופילים מופעלים מחדש, השרשרת שלכם רצה במקביל במקום שלא ציפיתם לו.
מה אסור לשומר לעשות
שומר שמפעיל מחדש הכול בכל כשל נראה בריא בבדיקות וגורם להשבתה בחלון תחזוקה. הפעילו מחדש לכל פרופיל, אף פעם לא גלובלית.
העדיפו לקוח מתוחזק כשהשער מציע אחד לאותו פרוטוקול, ואל תקבעו סיסמה קשיחה בסקריפט ואל תעבירו אחת בשורת פקודה, כי קובץ הפרופיל כבר מחזיק בסוד. אם משימה חייבת לרוץ כמשתמש רגיל לאחר שהמנהרה עלתה, הקטינו הרשאות מתוך הסקריפט במקום להריץ את כל השרשרת תחת אותו חשבון. לבסוף, קראו שוב את הנתיבים אחרי חיבור מחדש, כי פרופיל יכול לחזור עם כתובת מוקצית אחרת ולהשאיר נתיב מיושן שאף בדיקה המכוונת לכתובת המנהרה לא תבחין בו לעולם.