איך לנעוץ אפליקציית לינוקס אחת ב-VPN עם כללי UID
כלל UID רואה רק sockets מקומיים, והחרגת ה-loopback הרגילה הורגת את המנהרה. נתבו קודם את החשבון, ואז סננו ואמתו כל שלב.
לנעוץ תוכנית אחת ב-VPN בלינוקס זו בעיקר בעיית ניתוב, וכלל חומת האש קובע רק מה קורה לאחר שנבחר המסלול. אם תתאימו את ה-UID של התוכנית ב-OUTPUT לפני שהמנהרה מחזיקה במסלול ברירת המחדל, הכלל יפיל בדיוק את התעבורה שרציתם להגן עליה. אותו כלל גם לא רואה את תהליך הפותר שעונה לשאילתות ה-DNS של התוכנית. סדרו את הסדר נכון וחשבון אחד ללא הרשאות יהפוך לבורר אמין של המנהרה המפוצלת.
תנו לחשבון מסלול לפני פסק דין
התאמת הבעלים עונה על שאלה אחת: האם socket מקומי השייך ל-UID הזה בנה את החבילה? היא לא בוחרת ממשק, והיא לא יכולה להזיז תעבורה שהטבלה הראשית כבר שולחת דרך ה-NIC הפיזי. לכן כלל UID בלי מסלול מתאים חוסם את התוכנית במקום להפנות אותה מחדש.
שלחו את החשבון קודם דרך הטבלה שלו, ואז תנו לחומת האש לאשר את התוצאה. זה עובד במארח שה-iproute2 שלו מבין uidrange, מה ש-ip rule help מדווח בשורה אחת. טבלה 100 מחזיקה במסלול ברירת מחדל דרך המנהרה, והכלל שולח רק UID 1000 לטבלה הזו. כל השאר נשאר בטבלה הראשית וממשיך להשתמש בקישור הפיזי.
ip rule add uidrange 1000-1000 table 100 ip route add default dev tun0 table 100
חשבון שני שזקוק למנהרה אחרת מקבל טבלה 101 וכלל משלו, כי שני פרופילים לא יכולים שניהם להחזיק במסלול ברירת המחדל באותה טבלה. פרופילי NetworkManager הם ברמת המערכת, כך שהחלק הזה נשאר ידני, והכללים נעלמים באתחול אלא אם משהו משחזר אותם. כתבו את הטבלאות בקובץ אתחול לצד הגדרת המנהרה, כדי שחיבור מחדש לא ישאיר חשבון אחד במסלול הלא נכון.
למה החרגת loopback הורגת את המנהרה
רוב הגרסאות המועתקות של הכלל מפילות כל חבילה שלא יוצאת דרך loopback. המנהרה אינה loopback, ולכן הצורה הזו מפילה גם את תעבורת המנהרה, והתוצאה נראית כמו VPN מת ולא כמו טעות בחומת האש.
כשה-OUTPUT רץ, הליבה כבר בחרה ממשק יציאה, ולכן -o מושווה לתשובת המסלול ולא לכותרת החבילה. התאמת ה-בעלים נבדקת רק ב-OUTPUT וב-POSTROUTING, וחבילות מועברות לא נושאות socket שהיא תוכל לקרוא. השילוב הזה אומר שההחרגה חייבת לנקוב בממשק המנהרה ולשלול את ההתאמה הזו, ולא לשלול את loopback.
ל-loopback עדיין מגיע ACCEPT משלו מעל ה-DROP, כי חבילת ה-DNS הראשונה של התוכנית הולכת לסטאב המקומי דרך lo. שימו את שני הכללים בסדר הזה, והחשבון מגיע לסטאב, ואז למנהרה, ושום דבר אחר.
iptables -I OUTPUT 1 -o lo -m owner --uid-owner vpnapp -j ACCEPT iptables -A OUTPUT -m owner --uid-owner vpnapp ! -o tun0 -j DROP
IPv6 היא מערכת כללים נפרדת, וזוג שמיועד ל-v4 בלבד משאיר את ip6tables ללא נגיעה. תוכנית שמעדיפה רשומות AAAA תצא אז דרך הקישור הפיזי בלי להגיע ל-DROP בכלל. שקפו את שני הכללים ב-ip6tables, או השביתו IPv6 במארח כשהמנהרה לא נושאת כתובת v6. כללים שנוספו ביד נעלמים גם הם באתחול, אז שמרו אותם עם netfilter-persistent save או בנו מחדש את אותה לוגיקה כטבלת nftables שיחידת האתחול טוענת.
תשובות DNS מגיעות מתהליך אחר
השאילתה של התוכנית אל 127.0.0.53 עוברת את ה-ACCEPT של loopback, ושם נעצרת התאמת ה-UID. פותר הסטאב מעביר כלפי מעלה מחשבון השירות שלו, ולכן כלל שמקושר אל vpnapp לא רואה לעולם את השאילתה השנייה. אם הפותר בוחר שרת LAN לקישור, התשובות חוזרות דרך ה-NIC הפיזי בעוד החבילות של התוכנית עצמה נשארות במנהרה. התוצאה הנראית היא מנהרה עובדת עם שמות שבורים, או שמות ששרת שלא בחרתם עונה עליהם.
תקנו את פתרון השמות בקישור המנהרה, לא ביישום. תנו לפרופיל המנהרה שרת DNS ותחום ניתוב, ואז אשרו עם resolvectl query ו-resolvectl status tun0 שהפותר משתמש בו לשמות החשובים. בתוך מרחב שמות של רשת הבעיה נעלמת, כי הפותר של המרחב מכיר רק את המנהרה.
בדקו את הכלל מהחשבון עצמו
שאלו את הליבה איזה מסלול מקבל UID, ואז שלחו בקשה כאותו חשבון והשוו את כתובת היציאה לזו של החשבון שלכם. אם שניהם מדווחים על אותה כתובת, הכלל מתאים משהו אחר מהתעבורה שבדקתם. הפקודה הראשונה למטה מציגה את חיפוש המסלול בלי לשלוח חבילה, מה שמפריד בין טעות ניתוב לטעות בחומת האש.
ip route get 1.1.1.1 uid 1000 sudo -u vpnapp curl -s https://ifconfig.co
מונה מראה אם כלל אי פעם נורה. הריצו iptables -vnL OUTPUT, קראו את מספר החבילות לצד כל כלל, והתייחסו לאפס לצד ה-DROP אחרי תעבורה אמיתית כשגיאת התאמה.
תעבורה מועברת נמצאת מחוץ לעיצוב הזה. לקונטיינר או VM מאחורי גשר אין socket מקומי בבעלות vpnapp, ולכן התאמת הבעלים לא נורית לעולם והחבילות האלה הולכות לפי מדיניות FORWARD במקום. אם צריך לכסות את העומס הזה, בדקו אותו בנפרד וכתבו מדיניות שמקושרת לגשר או לכתובת הקונטיינר. העיצוב מחזיק כשהטבלה, החרגת הממשק, הפותר וכללי v6 כולם מצביעים לאותו כיוון; השאירו אחד מהם בחוץ והחשבון או מדליף או מאבד קישוריות.