איך למדוד את זמן הפעילות של לקוח OpenVPN עם ה-hooks בשם up ו-down
ל-OpenVPN אין מונה זמן פעילות. שמרו חותם epoch מה-hook בשם up, מחקו אותו ב-down, הפחיתו אותו ושמרו עליו נאמן לאורך הפעלות מחדש ומופעים.
לוח בקרה מבקש מספר של כמה זמן החיבור פעיל, ו-OpenVPN אינו מספק אותו. הלקוח יודע מתי המנהרה שלו עלתה, אבל רק אם משהו רושם את הרגע הזה לפני שמצב הסשן הולך לאיבוד. המקום הנתמך הוא ה-hook בשם up, והערך שראוי לשמור הוא שנייה גולמית של epoch ולא מחרוזת מעוצבת. כל מה שאחרי זה הוא אריתמטיקה, ועוד כמה כללי סדר שקובעים אם המספר נשאר נאמן.
ודאו שה-hooks אכן רצים
הוכיחו שה-hook נורה לפני שאתם מתכננים משהו סביבו. תצורת לקוח מינימלית דורשת script-security 2 ועוד נתיבים מפורשים up ו-down; בלי שורת האבטחה OpenVPN מסרב להריץ את הסקריפט ואומר זאת בבירור. הוסיפו up-restart ו-down-pre באותו זמן כדי שנתיבי ההפעלה מחדש והפירוק יתנהגו באופן צפוי.
גרמו לגרסה הראשונה של ה-hook להוסיף את הסביבה שלו לקובץ ולא לעשות דבר אחר. זה אומר לכם את שמות המשתנים שהבנייה שלכם באמת מייצאת, כמו dev ו-script_type, במקום אלה שאתם זוכרים מגרסה אחרת. הריצו חיבור אחד וניתוק אחד, ואז קראו את הקובץ. אם לא מופיע דבר, עצרו כאן, כי עיצוב חותם זמן מעל hook שלעולם לא רץ ייראה כמו כשל ניטור במשך שבועות.
בדקו באיזה משתמש ה-hook רץ. כשמוגדרים user ו-group, OpenVPN מוותר על הרשאות לפני הרצת סקריפטים, ולכן ספרייה ש-root יכול לכתוב בה עשויה להיות סגורה ל-hook. בחרו את הנתיב מנקודת המבט של השירות ולא של ה-shell שלכם.
רשמו ערך epoch אחד ומחקו אותו בכוונה
ה-hook בשם up צריך שורה אחת, date +%s > /run/openvpn-client.started, כשהנתיב מותאם לכל מופע. ערך epoch חוסך בהמשך שאלות של שפה, אזור זמן ופורמט, וזה אותו מספר שסוכן ניטור יכול להשוות לשעון שלו.
מחיקה חשובה לא פחות מכתיבה. ה-hook בשם down אמור לרוקן או להסיר את הקובץ, ו-down-pre גורם לזה לקרות לפני שהממשק נסגר, מה שמסיר את החלון שבו הקובץ מתאר מנהרה שכבר איננה. up-restart לאחר מכן מרענן את החותם בהפעלה מחדש פנימית במקום להשאיר את הערך המקורי במקומו. בלי הצמד הזה, הפעלה מחדש לאחר פסק זמן של ping מייצרת מספר שממשיך לטפס בזמן שהמנהרה נבנית מחדש.
בחרו מיקום עם תוחלת החיים הנכונה. קובץ תחת /run נעלם באתחול, וזה תואם את המציאות, ואילו קובץ תחת /tmp עשוי להיות מנוקה באופן בלתי צפוי ואחד בספריית התצורה שורד באופן מטעה. הגדירו הרשאות כך שרק משתמש השירות וקורא הניטור יוכלו לקרוא אותו.
חשבו זמן פעילות בלי לסמוך על שורות לוג
קראו את השנייה השמורה, קראו את השנייה הנוכחית, החסירו. כשהקובץ חסר או ריק, התשובה הנאמנה היא שאין מנהרה פעילה, ולא שזמן הפעילות הוא אפס, כי שני המצבים האלה אמורים להעלות התראות שונות. שמרו שניות גולמיות במטען הניטור ועצבו ימים ושעות בשכבת התצוגה. מעצב שמעגל בתוך הייצואן זורק דיוק שמישהו ירצה בזמן תקרית.
ניתוח חותמות זמן של לוג הוא קיצור הדרך המפתה, והוא נכשל בשלוש דרכים: הפורמט הולך אחרי כל אפשרות שמוגדרת, רוטציה מסירה את ההיסטוריה, וחיבורים מחדש נראים כסשנים נפרדים ולא כמנהרה רציפה אחת. ה-hook רושם את האירוע פעם אחת, ברגע שהוא קורה.
כשהבדיקה רצה במארח אחר, שלחו את חותם הזמן ולא את המשך כדי שהקורא יחיל את השעון שלו. אז תוצאה שלילית קטנה נקראת כסטיית שעון ולא כ-hook שבור.
כסו חיבורים מחדש, הפעלות מחדש ומספר מופעים
שתי מנהרות במארח אחד צריכות שני קבצים, עם מפתח לפי שם המופע שהשירות כבר משתמש בו. נתיב משותף פירושו שהחיבור האחרון דורס את זמן ההתחלה של כל פרופיל, והתסמין הוא מספר שקופץ אחורה כשמנהרה שנייה מתחילה.
התנהגות החיבור מחדש ראויה לבדיקה משלה, כי שם עיצוב סביר מדווח בשקט על הדבר הלא נכון. כפו הפעלה מחדש על ידי הפלת העמית או שליחת אות לתהליך, ואז השוו את מצב הממשק לקובץ. חותם הזמן אמור לזוז קדימה ברגע שהמנהרה חוזרת.
בצד השרת, קובץ המצב נושא ערך connected-since לכל לקוח, שעונה על שאלה אחרת: מתי השרת ראה את העמית הזה לאחרונה. השתמשו בו להצלבה ולא כתחליף, כי הוא נעלם עם הסשן שהוא מתאר. אף אחת משתי המדידות לא אומרת דבר על בריאות האפליקציה שמאחורי המנהרה.
הריצו את שלוש הבדיקות שתופסות באגים של סדר
בדקו חיבור רגיל, חיבור מחדש כפוי ועצירה נקייה, וקראו את רשימת הממשקים ואת הקובץ יחד אחרי כל אחד. חותם שעדיין קיים אחרי עצירה נקייה, או קובץ שמאשר מנהרה שאינה ברשימת הממשקים, מצביע ישירות על סדר ה-hooks. הריצו את הבדיקות כמשתמש השירות ועם הנתיבים של השירות, כי shell של root עשוי לראות קובץ אחר ולתת תשובה שגויה בביטחון. אחר כך השאירו סקר איטי קורא את הקובץ וודאו שהוא לעולם לא כותב בו.
סקר כל שישים שניות מכסה התראות, ואף hook לא אמור להסתמך על כך שהסקר הזה חי. הפרידו בין שתי האחריות הללו והמספר יישאר אמין כשכל צד נפרס מחדש.