برنامهای درون فضای نام VPN از LAN قابل دسترسی نیست
فضای نام شبکه به یک برنامه تونل و لوپبک خودش را میدهد. بهجای میزبان تنها پورت آن را با یک پرش socat یا یک جفت veth منتشر کنید.
سرویس شما روی ماشین کار میکند، تونل بالاست و مرورگر روی میز شما هنوز پاسخ نمیگیرد. هیچ چیز به معنای معمول خراب نیست: برنامه داخل یک فضای نام شبکه گوش میدهد و آن پشته برای LAN نامرئی است. لوپبک آن به فضای نام تعلق دارد، بنابراین کلاینتی روی ماشین دیگر هیچ نشانی ندارد که به پورت برسد. یک پرش عمدی، یا یک جفت veth، این را بدون جابهجایی بقیه میزبان درست میکند.
چرا هیچ چیز روی نشانی LAN پاسخ نمیدهد
فضای نام یک پشته کامل شبکه است: واسطها، مسیرها، قواعد دیوار آتش و یک لوپبک خصوصی. فرآیندی که از طریق ip netns exec اجرا میشود آن پشته و هیچ چیز دیگری را نمیبیند، بنابراین نشانی که به آن متصل میشود فقط درون فضای نام حل میشود. 127.0.0.1 خود میزبان یک لوپبک کاملاً دیگر است.
به همین دلیل curl روی میزبان شکست میخورد در حالی که همان فرمان درون فضای نام موفق میشود. برنامه سالم است؛ نشانی بهسادگی در پشته میزبان وجود ندارد.
یک پورت را با یک پرش socat منتشر کنید
socat دو پشته را در فضای کاربر پل میزند، که وقتی فقط یک پورت TCP باید عبور کند کافی است. سمت میزبان روی LAN گوش میدهد و برای هر اتصال پذیرفتهشده یک socat دوم درون فضای نام راه میاندازد که به لوپبک برنامه وصل میشود. فرآیند درونی دقیقاً مانند یک کلاینت محلی به برنامه میرسد. هیچ چیز در مسیریابی فضای نام تغییر نمیکند، بنابراین برنامه همچنان از تونل بهعنوان تنها خروجی خود استفاده میکند.
socat TCP-LISTEN:9100,reuseaddr,fork EXEC:'ip netns exec vpn socat STDIO tcp-connect:127.0.0.1:9100',nofork
فرآیند بیرونی به root یا توانایی ورود به فضای نام نیاز دارد. اگر VPN قطع شود، برنامه مسیرش را از دست میدهد و پورت منتشرشده بسته شکست میخورد، و این همان رفتاری است که از یک زندان میخواهید.
وقتی بیش از یک پورت عبور میکند از یک جفت veth استفاده کنید
جفت veth پاسخ درست است وقتی چند پورت یا پروتکل باید عبور کنند، یا وقتی میزبانهای دیگر باید اتصالها را آغاز کنند. یک سر در میزبان میماند، سر دیگر به فضای نام میرود، و یک /30 کوچک به هر دو طرف نشانی پایدار میدهد. سپس یک مسیر میزبان نشانی فضای نام را از روی جفت میفرستد.
ip link add veth0 type veth peer name veth1
ip link set veth1 netns vpn
ip addr add 10.77.0.1/30 dev veth0
ip link set veth0 up
ip netns exec vpn ip addr add 10.77.0.2/30 dev veth1
ip netns exec vpn ip link set veth1 up
مسیر پیشفرض از طریق میزبان اضافه نکنید مگر اینکه قصد شکستن زندان را داشته باشید. تونل باید خروجی بماند، بنابراین از روی جفت فقط نشانی سرویس منتشرشده قابل دسترسی است. به فضای نام فایل resolver خودش را هم بدهید، زیرا ip netns exec فایل /etc/netns/vpn/resolv.conf را میخواند و بدون آن حل نام درون زندان خالی است.
از ماشین دیگری آزمایش کنید، نه از میزبان
آزمایش را از ماشین دوم اجرا کنید، زیرا میزبان میتواند از راههایی به شنونده محلی برسد که چیزی درباره LAN نمیگویند. ابتدا بررسی کنید برنامه درون فضای نام واقعاً به چه چیزی متصل شده است، سپس از بیرون به نشانی منتشرشده وصل شوید. اتصال به همه نشانیها در آنجا زندان را گسترده نمیکند، زیرا نویسه عام هنوز به فضای نام تعلق دارد و LAN نمیتواند آن را ببیند.
ip netns exec vpn ss -lntp
اگر اتصال از میزبان کار کند و اتصال از LAN نه، قطعه گمشده پرش یا مسیر است، نه نشانی اتصال. بهجای جابهجا کردن یک دستگاه tun زنده به داخل، OpenVPN را درون فضای نام اجرا کنید، چون جابهجا کردن واسط آن را خاموش میکند و میتواند مسیرهایی را پاک کند که بعداً از بیرون نمیتوانید تعمیر کنید. فرمانهای بازیابی را روی کنسول نگه دارید، نه درون زندان.