mitmproxy، DevTools، Gradle: سه لایه پشت VPN
loopback هرگز وارد تونل نمیشود. نشانه را در شنونده، مخزن اعتماد یا فیلتر بسته دستهبندی کنید و لایهای را که واقعاً خراب شده ترمیم کنید.
VPN وصل میشود، و سه ابزار بیارتباط به سه شیوه متفاوت شکست میخورند در همان بعدازظهر. mitmproxy دیدن درخواستها را متوقف میکند، Chrome دیباگر را رد میکند و Gradle BindException هنگام اتصال یک سوکت محلی پرتاب میکند. گمان مشترک این است که تونل localhost را مسدود میکند. نمیتواند: 127.0.0.1 درون هسته پردازش میشود و هرگز به آداپتور نمیرسد، چه رسد به دروازه.
سه لایه، سه خرابی متفاوت
آنچه با کلاینت تغییر کرد مسیر رسیدن به loopback نیست. یک واسط محلی، یک مخزن اعتماد ماشین و یک فیلتر بسته است، و هر یک بخش متفاوتی از جریان کار توسعهدهنده را میشکند. قرار دادن نشانه در سطر درست بیشتر تشخیص است:
| Symptom | Layer | First check |
|---|---|---|
| Proxy sees no traffic | Local proxy or listener | ss -lntp, or netstat -ano on Windows |
| TLS error in one tool only | Trust store | Which CA bundle does that runtime read? |
| Local bind or connect refused | Packet filter or port owner | Who holds the port, and what rule drops it? |
تقریباً هر گزارش از این نوع از سطر آخر شروع میشود و بالا میرود، که برعکس است. تونل تنها لایهای است که اثباتاً نمیتواند ترافیک loopback را ببیند، پس سزاوار کمترین شک است. با آنچه فرایند اتصال داده شروع کنید، سپس بپرسید به کدام گواهیها اعتماد دارد، و تنها پس از آن سیاست روی ماشین را ببینید.
با شنونده شروع کنید، نه با تونل
وقتی یک واسط روی 127.0.0.1:8080 دریافت ترافیک را متوقف میکند، یکی از سه چیز رخ داده است: هرگز شروع نشده، پورت دیگری را اتصال داده، یا فیلتر اتصال loopback را انداخته است. فهرست کردن سوکتهای شنونده با یک فرمان پاسخ میدهد و همچنین نشان میدهد وقتی دو ابزار درباره اینکه کدام اول بوده اختلاف دارند، کدام فرایند صاحب پورت است.
یک نشانی محلی در جستوجوی مسیر همان را از جهت دیگر تأیید میکند. ip route get به سمت مقصد loopback دستگاه loopback را گزارش میدهد، هرگز تونل را، که جمله مفیدی است برای آماده داشتن وقتی کسی تغییر مسیریابی را به عنوان راهحل پیشنهاد میکند.
لایه واسط: محیط، پیکربندی نیست
بسیاری از کلاینتهای شرکتی یک واسط HTTP اجرا میکنند و انتظار دارند برنامهها از آن استفاده کنند. تنظیم HTTPS_PROXY در یک پوسته ابزارهای خط فرمانی را که آن را رعایت میکنند درست میکند و برای ابزاری که فایل تنظیمات خودش را میخواند کاری نمیکند. Gradle و Selenium و gRPC هر یک پیکربندی خود را مشورت میکنند و واسطی که در یک ترمینال صادر شده برای دیمنی که IDE راهاندازی کرده نامرئی است.
ابزارهای کانتینر معمولترین جایی است که این موضوع آشکار میشود. loopback یک کانتینر مال خودش است، پس 127.0.0.1 درون کانتینر هرگز به معنای واسط میزبان نیست؛ نشانی میزبان یا تنظیم شبکه میزبان لازم است. اصلاحی که در پوسته کار میکند و در ساخت شکست میخورد معمولاً همین سطر است، نه تونل.
لایه اعتماد: ابزار مخزن دیگری را میخواند
رهگیری تغییر دوم است و گمراهکنندهترین خطاها را تولید میکند. کلاینت گواهی خودش را برای اتصالهای بازرسیشده ارائه میدهد، بنابراین مرورگری که به ریشه شرکتی اعتماد دارد موفق میشود، در حالی که ابزاری با مخزن CA همراه شکست میخورد. درخواستهای Python از طریق certifi نمونه کلاسیک است: مخزن سیستمعامل میتواند درست باشد و درخواست باز هم شکست بخورد، چون آن محیط اجرا هرگز آن را نمیخواند. متن خطا بهندرت رهگیری را ذکر میکند، و به همین دلیل این سطر اشتباهاً نقطه پایانی خراب تشخیص داده میشود.
آنچه نقطه پایانی واقعاً ارائه میدهد را با آنچه ابزار اعتبارسنجی کرده مقایسه کنید. openssl s_client زنجیرهای را که سرور فرستاده نشان میدهد؛ خروجی اعتبارسنجی خود ابزار نشان میدهد چه تصمیمی گرفته است. وقتی همخوانی ندارند، REQUESTS_CA_BUNDLE یا SSL_CERT_FILE اهرم آن محیط اجراست، و ریشه شرکتی جای آن در مخزنی است که آن محیط اجرا میخواند، نه در مکانی جهانی که فقط برخی ابزارها رعایت میکنند.
تغییر نسخهای که خطای SSL را رفع میکند شاهدی درباره سیاست اعتماد و رمز است، نه درباره VPN. کاهش نسخه Python که یک کلاینت SOAP را به کار انداخت مخزن CA همراه و تنظیمات پیشفرض TLS را تغییر داد؛ مسیر شبکه تکان نخورد.
لایه فیلتر: میتواند loopback را هم بیندازد
تغییر سوم یک فیلتر بسته است و برخی محصولات قوانینی نصب میکنند که ترافیکی را که وارد تونل نمیشود میاندازند. شنوندههای محلی میتوانند شامل شوند. این یک سوکت سالم را به اتصال ردشده یا منقضی تبدیل میکند و خطای حاصل بیشتر شبیه اشکال برنامه است تا سیاستی روی ماشین.
مالکیت پورت نیمه دیگر این لایه است. BindException یعنی سوکت باز نشده است، که شکستی متفاوت از رد شدن اتصال است. پیش از سرزنش فیلتر بررسی کنید آیا فرایند دیگری پورت را گرفته است، سپس قانونی را که ترافیک محلی را میاندازد پیدا کنید و باریکترین اجازهای را که محصول پشتیبانی میکند اضافه کنید. دو ابزاری که برای یک پورت دیباگ رقابت میکنند دقیقاً همان پیام مسدودسازی سیاست را تولید میکنند و تنها یکی از آنها با تغییر دیوار آتش درست میشود.
پورت دیباگ Chrome در همان خانواده شکست میخورد. مرورگر شروع میشود، درایور نمیتواند به نقطه پایانی DevTools برسد و پیام به جای شبکه، DevTools را نام میبرد. پرچمهای اجرای اضافی و یک مدیر درایور زائد تغییر میدهند کدام فرایند صاحب پورت است، و به همین دلیل حذف آنها گاهی به نظر میرسد VPN را درست میکند.
لایهای را که شکست خورد ترمیم کنید
لایهای را که شکست خورد ترمیم کنید، نه تونل را. شنونده loopback دور از دسترس نیاز به تصحیح شنونده یا پورتش دارد. گواهی نامطمئن نیاز دارد ریشه شرکتی جایی نصب شود که همان محیط اجرا نگاه میکند، با نگه داشتن استثنا باریک. فیلتری که ترافیک محلی را میاندازد نیاز به قانون اجازه مشخص دارد نه فیلتر غیرفعال، چون غیرفعال کردن همه چیز دیگری را که محافظت میکرد نیز دوباره باز میکند.
اتصال دوباره VPN هیچیک از این لایهها را آزمون نمیکند. فقط همان تغییری را دوباره اجرا میکند که آنها را شکست، و به همین دلیل همان سه شکست پس از هر اتصال دوباره برمیگردد و پس از هر راهاندازی دوبارهای که کلاینت را غیرفعال بگذارد ناپدید میشود.