הפעלת VPN שמור של Mac מהטרמינל עם scutil --nc
השתמשו ב-scutil --nc כדי להפעיל, לבדוק ולעצור שירות macOS VPN שמור, הרחיקו פרטי התחברות מ-argv, והוכיחו שהתעבורה אכן עוברת במנהרה.
יש לכם שירות VPN שמור בהגדרות המערכת, ואתם רוצים שהטרמינל יעלה אותו. ב-macOS הנתיב הנתמך הוא scutil --nc, אך רק לשירותים שנמצאים בבעלות מנהל חיבורי הרשת של המערכת עצמה. שורת התפריטים אינה ה-API: ללקוחות צד שלישי יש בדרך כלל אוטומציה משלהם, ופרופיל שנדחף על ידי שירות ניהול עשוי לסרב להתחלה מקומית. זו רשימת הבדיקה שאני מבצע: מצאו את השירות המדויק, קראו את מצבו, הפעילו אותו, המתינו לשינוי המצב, ואז הוכיחו שהתעבורה באמת עוברת במנהרה. עצרו בצעד הראשון שלא מסתדר, כי כל פקודה מאוחרת מניחה שהקודמת הצליחה.
מצאו את השירות לפני שאתם מנסים להפעיל אותו
התחילו מהמלאי ולא משם הפרופיל שאתם זוכרים:
scutil --nc help
scutil --nc list
כל שורה מצמידה מצב למזהה שירות, סוג ושם תצוגה. המזהה הוא הערך שעליו כותבים סקריפטים, כי שמות התצוגה חוזרים על עצמם וניתנים לעריכה. מדריך scutil של אפל מתעד את מצב חיבור הרשת, בעוד --nc help המותקן הוא הרשימה המוסמכת של תת-הפקודות ב-Mac הזה; אל תניחו שדגל ממדריך ישן עדיין קיים בגרסת ה-macOS שלכם.
רשימה ריקה היא תוצאה, לא שגיאה. שירות שנוצר על ידי לקוח ספק או פרופיל ניהול יכול להיות פעיל כשהוא בלתי נראה כאן, או גלוי עם סוג שהבקר הנייטיבי אינו יכול להפעיל. במקרה כזה, השתמשו בכלי הספק או בתיעוד הפרופיל. יצירת פרופיל נייטיבי מקביל רק כדי שיהיה משהו להפעיל היא עסקה גרועה.
קראו את המצב הנוכחי ואשרו את הבורר
שאלו את השירות לפני ההפעלה, כדי שתדעו מה הפעלה מוצלחת אמורה לשנות:
scutil --nc status "Office VPN"
אם שני שירותים חולקים שם תצוגה, השם דו-משמעי. העבירו את המזהה במקום; הפקודה מקבלת את שניהם, אבל רק המזהה מובטח לבחור שירות אחד. בדקו שמילת המצב היא אחת שאתם מזהים — בדרך כלל Connected, Disconnected, Connecting או Disconnecting — לפני שאתם מנתחים אותה בסקריפט. בדקו גם אם הפרופיל מנוהל, כי תצורה נעולה יכולה לקבל את הפקודה ובכל זאת להתעלם ממנה או לבקש אישור.
קריאת המצב הזו זולה, אז השתמשו בה כשומר באוטומציה: הפעילו רק כשהמצב הוא Disconnected, ואל תתייחסו ל-Connecting ככישלון. אם השירות כבר Connected, דלגו על ההפעלה במקום להפריע למנהרה שעובדת.
הפעילו את החיבור והמתינו שהמצב יתייצב
בקשת ההפעלה א-סינכרונית. הפקודה חוזרת כשהבקשה התקבלה, לא כשהאימות הסתיים או כשהמסלולים הותקנו. הריצו אותה, ואז בדקו את המצב עם המתנה מוגבלת וצאו אם השירות נופל חזרה ל-Disconnected:
scutil --nc start "Office VPN"
n=0
while [ "$n" -lt 30 ]; do
state=$(scutil --nc status "Office VPN" | head -n 1)
[ "$state" = "Connected" ] && break
[ "$state" = "Disconnected" ] && { echo "start failed"; exit 1; }
sleep 2
n=$((n + 1))
done
מצב Connecting שלעולם אינו נפתר מצביע בדרך כלל על פרטי התחברות, MFA או השרת, לא על scutil. הפקודה אינה יכולה לספק התחברות אינטראקטיבית, כך שפרופיל שמצפה לאסימון או למפתח חומרה יישאר ב-Connecting ובסוף ייפול חזרה. קראו את מילת המצב לפני שאתם מוסיפים ניסיונות חוזרים; לולאה מול בקשת אימות אינה יכולה להצליח.
אל תתייחסו לקוד היציאה של ה-shell כאל מוכנות. האות השימושי הוא מחרוזת המצב, ואחריה הוכחה שהמנהרה נושאת תעבורה. פקודת הפעלה שחוזרת בשקט עדיין יכולה להשאיר אתכם עם חיבור שלעולם אינו מאמת.
הוכיחו שהמנהרה נושאת תעבורה, לא רק שהיא אומרת Connected
Connected מתאר את החיבור, לא את החלטת הניתוב. שירותי PPP ו-IKEv2 נייטיביים יוצרים ממשק ppp או utun ומתקינים מסלולים, בעוד מנהרה מפוצלת משאירה בכוונה את ברירת המחדל של המסלול בלי שינוי. בדקו את הממשקים ואת שתי משפחות הכתובות:
ifconfig -l
netstat -rn -f inet
netstat -rn -f inet6
scutil --dns
מצאו את הממשק שהשירות יצר במקום לנחש מספר, ואז שאלו את טבלת הניתוב איזה ממשק יעד מסוים משתמש בו: route -n get 10.0.0.10, עם מארח פנימי במקומו. אם היא מדווחת על הממשק הפיזי, המנהרה פעילה אך אינה נושאת את הזרימה הזו. בדקו מסלולי מנהרה מפוצלת, סדר הפותר וכל כלל חומת אש מקומי שמתיר את ממשק המנהרה אך לא את התהליך.
פתרון שמות הוא השלילה הכוזבת הרגילה. שמות פנימיים יכולים להיפתר דרך הפותר הלא נכון בזמן שהמנהרה בריאה לחלוטין, מה שנראה כמו תקלת VPN ואינו. scutil --dns מציג את הסדר שבו macOS ישתמש; לאחר שינוי פותר, רוקנו את המטמון עם dscacheutil -flushcache ו-sudo killall -HUP mDNSResponder.
הרחיקו פרטי התחברות והרשאות משורת הפקודה
לעולם אל תשימו סיסמה, מפתח משותף מראש או אסימון בארגומנטים. ארגומנטים גלויים ברשימות תהליכים ומגיעים להיסטוריית ה-shell, ותמליל תמיכה מועתק יכול להדליף אותם. טיפול פרטי ההתחברות של הפרופיל עצמו — בין אם פריט Keychain, בקשת מערכת או זרימת האימות של הלקוח — הוא המקום לסודות.
הרצת הפקודה עם sudo אינה הופכת התחברות אינטראקטיבית ללא מפוקחת. היא משנה את המשתמש האפקטיבי, לא את הזמינות של בקשת GUI, אסימון חומרה או ה-Keychain של ההתחברות. LaunchAgent יכול להפעיל שירות לאחר שהמשתמש התחבר וה-Keychain נפתח; LaunchDaemon בדרך כלל אינו מגיע לחלקים האלה של הפעלת המשתמש. אם ארגון מנהל את השירות, כללי מחזור החיים שלו גוברים על כל סקריפט מקומי.
עצרו את השירות ואמתו שהוא נשאר עצור
עצרו עם אותו בורר שהשתמשתם בו כדי להפעיל, ואז קראו את המצב חזרה במקום להניח שהמנהרה נעלמה:
scutil --nc stop "Office VPN"
scutil --nc status "Office VPN"
עצירה שחוזרת ל-Disconnected עדיין משאירה דבר אחד לבדוק: אם הפרופיל מוגדר להתחבר לפי דרישה, מה שיכול להחזיר אותו בלי הסקריפט שלכם. אם לקוח אחר מחזיק מסלולים באותו Mac, המסלולים האלה יכולים לשרוד עצירה נייטיבית. בדקו שוב את המסלול לפני שאתם מסיקים שהמכונה מחוץ ל-VPN.
לעטיפה שאתם מריצים ביד, שמרו על הסדר קבוע: רשימה, מצב, הפעלה, בדיקה, מבחן מסלול, עצירה, אימות. אל תנתחו את השם הידידותי מפלט חופשי כשהמזהה זמין, ואל תתייחסו ליציאת פקודת ההפעלה כאל מוכנות. מנהל החיבורים מדווח מצב; ההוכחה שלכם היא המצב ועוד מסלול שמצביע על המנהרה.