ProxyChains-NG אינו יוצר מנהרה. הוא טוען מראש ספרייה שמחליפה קריאות libc הקשורות לרשת בתוך התוכנית האחת שהוא מפעיל, ולכן הגבול הוא קריאה בתהליך ולא מסלול ברמת המכשיר. ההבחנה הזו קובעת מה באמת מוכיחה בדיקה מוצלחת. curl שעובד דרך השרשרת מאשר קריאה אחת שנתפסה, ולא שפתרון שמות, UDP או כל תהליך בן הלכו באותו מסלול. המדריך שלהלן מאמת את הכיסוי בשלושה שלבים, ואז מפרט מה הקרס לא מצליח להגיע אליו.

איך הטעינה המוקדמת מגיעה לחיבור

בעת ההפעלה המפעיל מכניס את libproxychains אל תוך LD_PRELOAD ואז מריץ את תוכנית היעד. הספרייה מפענחת את סמלי ה־libc האמיתיים ומחליפה אותם בגרסאות משלה של פונקציות כמו connect ו־getaddrinfo. קריאות שעוברות דרך הסמלים האלה נכתבות מחדש אל פרוקסי SOCKS או HTTP מקובץ התצורה. קריאות שלוקחות מסלול אחר לא פוגשות את הקרס אף פעם, ולכן האחריות היא לכל קריאה ולא לכל מכונה.

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

ודאו שהספרייה נטענה בתהליך הזה

התחילו את הבקשה ובדקו את התהליך החי ולא את המעטפת שהפעילה אותו. קובץ maps מציג כל אובייקט משותף שממופה כרגע לתהליך.

proxychains4 -q curl -sS --max-time 8 https://example.com/ -o /dev/null &
pgrep -a curl
grep libproxychains /proc/$(pgrep -n curl)/maps

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

עקבו אחרי החיבורים שיוצאים מהתהליך

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

strace -f -e trace=connect -o /tmp/pc.trace proxychains4 -q curl -sS https://example.com/ -o /dev/null
grep -o "sin_port=htons([0-9]*)" /tmp/pc.trace | sort -u

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

החליטו מה הקרס לא יכול לכסות

פרויקט proxychains-ng מגביל הפניה ל־TCP ומזהיר שסקריפטים, תהליכי רקע ומודולים טעונים יכולים להתנהג אחרת מהתוכנית הראשית. UDP ו־ICMP נמצאים מחוץ למנגנון, ולכן כל דבר שמסתמך עליהם זקוק למסלול נתמך משלו. DNS הולך אחרי הגדרת proxy_dns ואחרי התנהגות הפותר של היישום עצמו, כלומר בקשה מוצלחת אחת ב־HTTPS לא אומרת לכם דבר על פתרון שמות. שמרו גם על אימות תעודות במקומו: הגעה לשרת דרך פרוקסי אינה סיבה לכבות בדיקות זהות.

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

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