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

החליטו לכל שם, לא לכל שער

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

Name kindSource of truthWhere it lives
Connected clientThe address OpenVPN just assignedGenerated hosts file, rewritten per session
Service behind the tunnelA fixed address you choseStatic address= drop-in
Anything with a certificate nameThe certificate, not the poolEither, but the name must match the certificate

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

המסלול הדינמי: learn-address והמאגר

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

client-config-dir /etc/openvpn/ccd
ifconfig-pool-persist /etc/openvpn/ip-pool 60
script-security 2
learn-address /etc/openvpn/learn-address.sh

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

#!/bin/sh
HOSTS=/etc/openvpn/hosts.lan
case "$1" in
  add|update) echo "$2 $3" >> "$HOSTS" ;;
  delete)     sed -i "/^$2 /d" "$HOSTS" ;;
esac
kill -HUP $(cat /var/run/dnsmasq.pid)

בהתקן tun הארגומנט השני הוא כתובת המנהרה של הלקוח, כך שהשורה שמישה ישירות. בהתקן tap OpenVPN מעביר במקום זאת את כתובת ה-MAC של הלקוח, מפני שקטע tap יכול לשאת פרוטוקולים שאינם IPv4, ואז עליכם לחפש את הכתובת בקובץ המאגר לפי השם המשותף לפני שתכתבו משהו.

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

המסלול הסטטי: address= והרחבת דומיין

הפנו את dnsmasq לקובץ שנוצר במקום לקובץ hosts של המערכת, ותנו לו דומיין כדי ששמות קצרים יורחבו לשמות מלאים:

domain=corp.example
no-hosts
addn-hosts=/etc/openvpn/hosts.lan
listen-address=127.0.0.1,10.8.0.1
bind-interfaces

כאשר domain מוגדר, שורה כמו 10.8.0.6 alice עונה גם עבור alice וגם עבור alice.corp.example. הגבילו את listen-address לשער המנהרה ול-loopback, מפני שפותרן שמפורסם בטעות בממשק ה-LAN הוא שירות שלא התכוונתם להציע.

שירותים שלעולם לא מגיעים מהמאגר מקבלים רשומות משלהם. שימו אותם בקובץ drop-in נפרד בספריית התצורה של ההפצה כדי שעדכון חבילה לא יוכל לדרוס אותם:

address=/files.corp.example/10.8.0.20
address=/db.corp.example/10.9.0.5

מסרו את הפותרן או ששום דבר לא יקרה

פותרן שאיש לא שואל אותו לא משנה דבר. השרת חייב להכריז עליו:

push "dhcp-option DNS 10.8.0.1"
push "dhcp-option DOMAIN corp.example"

לקוחות Windows מיישמים את שתי האפשרויות בעצמם. רוב לקוחות Linux לא: הם זקוקים לשילוב פותרן נתמך כמו וו update-resolv-conf של ההפצה או טיפול ה-DNS של NetworkManager, או לדומיין חיפוש ולשרת שמות ידניים. בדקו את הפותרן בפועל של הלקוח במקום להניח שה-push כובד, מפני ש-push שמתעלמים ממנו נראה בדיוק כמו שרת שלא עונה.

אמתו בשלוש שכבות

שאלו קודם ישירות את השרת, אחר כך לקוח, ואחר כך את היישום:

dig +short @10.8.0.1 alice.corp.example
getent hosts files.corp.example

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

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

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