OpenVPN روی SOCKS5: تطبیق نسخه، انتقال و DNS
زنجیره SOCKS وقتی شکست میخورد که نسخه پروکسی، انتقال یا مسیر DNS ناسازگار باشد. SOCKS5 را تطبیق دهید، TCP را حمل کنید و زنجیره را داخل یک فضای نام نگه دارید.
یکی از مسیرهای خروج از این ایستگاه کاری یک پروکسی SOCKS است، و OpenVPN پشت آن فقط یک مهلت اتصال گزارش میکند بدون هیچ جزئیات مفیدی. مرورگر روی همان دستگاه از آن پروکسی کار میکند، اعتبارنامهها درستاند و پورت پاسخ میدهد. سه چیز بهقدر کافی متفاوتاند که اول بررسی شوند: نسخه SOCKS که پروکسی صحبت میکند، انتقالی که کلاینت انتخاب کرده، و جایی که تجزیه نام انجام میشود. پیش از آنکه دیوار آتش را مقصر بدانید، هر یک از اینها را تأیید کنید.
نسخه SOCKS را پیش از دیوار آتش تطبیق دهید
OpenVPN جامعه برای socks-proxy به SOCKS5 صحبت میکند. آن را به پروکسیای وصل کنید که فقط SOCKS4 ارائه میدهد؛ اتصال TCP باز میشود و سپس متوقف میماند، چون کلاینت منتظر پاسخ به سلامی است که طرف مقابل هرگز آن را تجزیه نمیکند. از بیرون، این توقف دقیقاً مانند یک پورت فیلترشده به نظر میرسد و به همین دلیل پرسش نسخه پیش از هر قاعده دیوار آتش میآید. یک واکشی آگاه به SOCKS آن را با یک فرمان روشن میکند.
curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
یک درخواست کامل دو چیز را همزمان ثابت میکند: پروکسی درخواست SOCKS را پذیرفت و نام را تجزیه کرد. هیچ طرح URL لازم نیست، چون curl میزبان خالی را HTTP میداند و این برای این آزمون کافی است.
آن واکشی شکستی را هم که گزارش کلاینت پنهان میکند کنار میگذارد. پروکسی میتواند به مرورگر اجازه دهد و همچنان مقصد VPN را رد کند، که در آن صورت رد در مرحله CONNECT رخ میدهد، پیش از هر احراز هویت VPN. OpenVPN فقط مهلت را گزارش میکند، پس پاسخ خود پروکسی شاهد مورد نیاز شماست.
انتقال باید در هر دو طرف TCP باشد
SOCKS5 در اینجا یک جریان TCP حمل میکند، پس خود تونل به proto tcp-client نیاز دارد. پروفایلی که هنوز روی UDP تنظیم شده از این مسیر کار نخواهد کرد، چون کلاینت از حالت انجمن UDP پروتکل استفاده نمیکند. تغییر پروفایل یک تغییر واقعی است نه تشریفاتی: طرف دور باید روی همان پورت به TCP گوش بدهد. سپس داده به TCP درون TCP تبدیل میشود، جایی که بسته گمشده دو بار دوباره ارسال میشود و آهنگ کند میشود، و جلسههای تعاملی این را بسیار بیشتر از انتقالهای بزرگ حس میکنند.
proto tcp-client
remote gw.lab.example 8443
socks-proxy 127.0.0.1 9050
این دستور میزبان پروکسی، پورت اختیاری و فایل اعتبارنامه اختیاری را میگیرد. آنها را در خود پروفایل بگذارید تا نسخهای دیگر جای دیگری همان رفتار را داشته باشد.
کل زنجیره را در یک کانتینر محدود کنید
انجام زنجیره روی میزبان یعنی تصاحب مسیر پیشفرضش و رها کردن resolver در وضعیتی که بعداً هیچکس نمیتواند توضیح دهد. یک فضای نام یا کانتینر آن را محدود میکند، پس میزبان مسیر خودش را نگه میدارد در حالی که گام SOCKS و تونل با هم زندگی میکنند. هیچ چیز در آن بدون دستگاه تونل، حقوق پیکربندی آن دستگاه و یک پروکسی قابل دسترس بالا نمیآید. سرویس Compose این را با cap_add: NET_ADMIN و /dev/net/tun سوارشده به دست میآورد.
cap_add:
- NET_ADMIN
devices:
- /dev/net/tun:/dev/net/tun
این جفت محدودتر از اجرای کانتینر با امتیاز کامل است و تمام دسترسی دستگاه مورد نیاز را میسازد. یک کلاینت Tor یا کانتینر پروکسی جداگانه میتواند شنونده را فراهم کند. در هر دو حالت آن را به loopback ببندید و از فضای نام از طریق میزبان به آن برسید، نه با افشای پروکسی به شبکه.
تجزیه نام همان جایی است که جداسازی شکست میخورد
تونلی که بستهها را حمل میکند و در همان حال از resolver میزبان میپرسد هیچ چیز را جدا نکرده است. دو چیز جداسازی را واقعی میکند: فضای نام resolver خودش را دارد و پرسوجوهایش از پروکسی یا تونل میگذرند، هرگز از رابط فیزیکی. برای آزمون دو نام به کار ببرید: یکی که فقط پشت تونل وجود دارد و یک نام عمومی که باید همان مسیر را بپیماید.
docker compose exec vpn cat /etc/resolv.conf
docker compose exec vpn getent hosts internal.lab.example
اگر نام طرف دور تجزیه شود و نام عمومی نشود، زنجیره گزینشی است نه خراب، و تفاوت به شما میگوید هر پرسوجو کدام مسیر را رفته است. اگر هر دو روی میزبان تجزیه شوند اما هیچکدام داخل کانتینر تجزیه نشود، کانتینر هنوز resolver میزبان را قرض میگیرد. فایل resolver را که یافتید ثبت کنید، چون همان تنظیمی است که باید تغییر کند.
هر گام را به ترتیب اثبات کنید
فهرست کوتاه است. یک درخواست SOCKS5 پاسخ میگیرد، تونل از طریق پروکسی به شنوندهاش میرسد، و بستههای خارجشده از فضای نام آدرسی را حمل میکنند که طرف دور انتظار دارد. هر یک را جداگانه تأیید کنید به جای افزودن پیکربندی بیشتر. وقتی کلاینت میگوید متصل است و هیچ چیز حرکت نمیکند، شکست تقریباً همیشه در حقیقت دوم یا سوم است.
curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
docker compose exec vpn ip route get 203.0.113.10
docker compose exec vpn getent hosts internal.lab.example
ترکیبی را که کار کرد بنویسید: نسخه SOCKS، انتقال، resolver و تنظیمات فضای نام. حل دوباره این زنجیره از حافظه بیشتر از یادداشت هزینه دارد. آن چهار واقعیت را در تیکت نگه دارید نه در رشته گفتگو.
زنجیرهای که اتصال را گزارش میدهد و هیچ چیز را عبور نمیدهد معمولاً در گامی شکست خورده که هنوز اثباتش نکردهاید. آن گام را پیش از افزودن لایه دیگر بیازمایید.