הוו עובד בפעם הראשונה, ואחרי שלושה חיבורים מחדש השרשרת מחזיקה שלושה עותקים של אותו כלל. שום דבר לא נכשל בקול; הסקריפט פשוט עשה את מה שנאמר לו בכל פעם שהוא רץ. וו VPN הוא פעולת תצורה שיכולה לרוץ יותר מפעם אחת, ולכן הוא צריך בעלים, מצב רצוי ושינוי מסודר. לכו בסדר הזה והכפילויות ייעצרו.

תן לבעלים לכללים לפני שכותבים אחד

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

iptables -N VPN_HOOK 2>/dev/null || true
iptables -C INPUT -j VPN_HOOK 2>/dev/null || iptables -I INPUT -j VPN_HOOK
iptables -S VPN_HOOK

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

בדוק את המצב הרצוי במקום להוסיף שוב

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

iptables -C VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT ||
  iptables -A VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT

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

עצרו אם הכלל שאתם צריכים לא יכול לבוא לידי ביטוי כבדיקה יציבה. זה בדרך כלל אומר שהמצב הרצוי עדיין מעורפל.

סדר את השינוי במקום לקוות שהוא יחזיק

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

flock /run/vpn-hook.lock /usr/local/sbin/vpn-firewall-apply
nft -f /etc/nftables/vpn-hook.nft

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

פרק רק את מה שבבעלותך

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

iptables -D VPN_HOOK -i tun0 -p tcp --dport 443 -j ACCEPT
iptables -F VPN_HOOK
ip -brief link show type tun

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

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

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