مسیریابی ترافیک میزبان از طریق VPN در ماشین مجازی: شش بررسی
شش بررسی به ترتیب برای تبدیل ماشین مجازی به دروازه VPN که میزبان خودش ترافیکش را از آن مسیر میدهد: حالت آداپتور، ارسال، NAT، مسیرهای میزبان، DNS، MTU.
شش بررسی، که به ترتیب اجرا میشوند، تعیین میکنند آیا یک ماشین مجازی میتواند دروازه VPN برای میزبان خودش باشد. هایپروایزر هیچکدام از این کارها را برای شما انجام نمیدهد: مهمان صاحب تونل است، میزبان صاحب یک مسیر است، و شبکه میان آنها مسیریابی معمولی است. این فهرست را نگه میدارم چون رد کردن یک گام همیشه همان نشانه را میدهد، سکوت، جایی که میزبان با خوشحالی مهمان را ping میکند و به هیچ چیز داخلی نمیرسد.
با دلیل شروع کنید. یا کلاینت شرکتی فقط داخل مهمان نصب میشود، یا سیاست آن را همانجا نگه میدارد، و شما هنوز سرور ساخت داخلی را از میزبان لازم دارید. اگر میزبان اجازه کلاینت خودش را دارد، بهجای آن همین کار را بکنید: یک تونل روی میزبان همیشه از دو شبکه بهعلاوه یک NAT بهتر است.
بررسی 1: میزبان به پیوندی نیاز دارد که بتواند به آن نشانی بدهد
میزبان باید واسطی داشته باشد که در همان پیشوند آداپتور دوم مهمان قرار بگیرد. حالت host-only در VirtualBox، host-only یا VMnet سفارشی در VMware Workstation، پل داخلی یا دستگاه tap در QEMU/KVM، و سوییچ Internal در Hyper-V همه واجد شرایطاند. مهمان 192.168.56.2، میزبان 192.168.56.1، پیشوند 192.168.56.0/24 چیدمانی است که در آزمایشگاهها استفاده میکنم.
شبکهسازی حالت کاربر QEMU (-netdev user، بکاند پیشفرض SLIRP) و NAT در VirtualBox در این بررسی کاملاً شکست میخورند. بستکهای مهمان به یک فرایند پروکسی روی میزبان میرسند، پس میزبان هرگز دستگاهی که نشانیهای مهمان را حمل کند نمیبیند و چیزی برای اشاره مسیر ندارد. Default Switch در Hyper-V هم همان داستان است. اگر ping 192.168.56.2 از میزبان شکست بخورد، متوقف شوید: هیچ مسیری که بعداً اضافه شود آن را درست نمیکند.
بررسی 2: مهمان ارسال و ترجمه میکند
بستکهای میزبان با نشانی مبدأ از شبکه host-only و مقصد داخلی میرسند، پس مهمان باید آنها را ارسال کند و سپس پشت نشانی تونل خود پنهانشان کند. در مهمان Linux این یعنی ارسال، یک جفت پذیرش FORWARD، و source NAT به سمت تونل:
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -A FORWARD -i eth1 -o tun0 -j ACCEPT
sudo iptables -A FORWARD -i tun0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 192.168.56.0/24 -o tun0 -j MASQUERADE
قاعده MASQUERADE همان بخشی است که مردم جا میاندازند. روترهای شرکتی بهندرت میدانند که 192.168.56.0/24 وجود دارد؛ با این قاعده، سرورهای داخلی نشانی تونل مهمان را میبینند و به آن پاسخ میدهند، و پاسخ راه بازگشت به مهمان را پیدا میکند.
مهمان Windows دستوپاگیرتر است. IPEnableRouter=1 زیر SYSTEM\CurrentControlSet\Services\Tcpip\Parameters ارسال را بدون ترجمه روشن میکند، پس فقط جایی کار میکند که مسیریابی شرکتی از قبل به پیشوند host-only شما برمیگردد. اشتراک اتصال اینترنت ترجمه میکند، اما آداپتور مشترک را به 192.168.137.1 شمارهگذاری مجدد میکند، پس نشانیای را که واقعاً گرفت بخوانید، پیش از نوشتن مسیرهای میزبان.
بررسی 3: مسیرهای میزبان مهمان را نام میبرند، نه تونل را
فقط پیشوندهایی را که میزبان نیاز دارد از مهمان عبور دهید. در Linux یک مسیر برای هر پیشوند کافی است و تمیز برمیگردد:
sudo ip route add 10.20.0.0/16 via 192.168.56.2
ip route get 10.20.30.40
در Windows معادل آن route add 10.20.0.0 mask 255.255.0.0 192.168.56.2 است. تا وقتی در حال آزمایش هستید -p را کنار بگذارید تا مسیر بد هنگام راهاندازی مجدد بمیرد، و پس از کار کردن مسیر آن را اضافه کنید. مسیر پیشفرض میزبان را حذف نکنید مگر اینکه هر برنامه میزبان باید از تونل استفاده کند؛ اگر واقعاً تونل کامل لازم است، دو مسیر /1 را اضافه کنید و مسیر مستقیم به شبکه هایپروایزر را نگه دارید:
sudo ip route add 0.0.0.0/1 via 192.168.56.2
sudo ip route add 128.0.0.0/1 via 192.168.56.2
روی میزبان Windows معیار واسط را هم بررسی کنید. مسیری که وقتی آداپتور host-only غیرفعال بود اضافه شده در جدول میماند اما هرگز ترافیک حمل نمیکند، و آداپتور دومی با معیار کمتر میتواند جستوجوی همان پیشوند را ببرد.
بررسی 4: DNS از مسیر پیروی میکند، نه از پیشفرض تونل
مسیرها بستکها را جابهجا میکنند؛ حلکننده تعیین میکند کدام نامها بستک تولید میکنند. حلکننده شرکتی را به منطقه شرکتی محدود کنید، بهجای جایگزینی حلکننده میزبان، و آن را به سرور DNSی اشاره دهید که مسیر جدید از قبل به آن میرسد. با systemd-resolved روی میزبان:
resolvectl dns eth1 10.20.0.53
resolvectl domain eth1 '~corp.example.com'
در Windows یک ورودی در جدول سیاست حل نام کار مشابهی میکند: Add-DnsClientNrptRule -Namespace ".corp.example.com" -NameServers 10.20.0.53. اگر مهمان حلکننده خودش را روی نشانی host-only اجرا میکند، بهجای آن از همان نشانی استفاده کنید، اما تنها پس از تأیید اینکه روی 192.168.56.2 پاسخ میدهد و نه روی loopback.
سپس MTU را بررسی کنید، پیش از آنکه DNS را برای صفحههای کند سرزنش کنید. واسط تونل کوچکتر از واسط 1500 بایتی میزبان است، پس میزبانی که قطعههای بزرگ با بیت DF روشن میفرستد، آنها را جایی داخل مهمان دور میریزد. نشانه کلاسیک، ping کارا و یک برنامه وب داخلی است که پس از دستدادن TLS متوقف میشود. MSS را در مسیر ارسال مهمان محدود کنید:
sudo iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
بررسی 5: از هر دو سر تأیید کنید
از میزبان، traceroute یا tracert به یک نشانی داخلی باید 192.168.56.2 را بهعنوان گام اول نشان دهد، نه دروازه فیزیکی را. در مهمان، همان تلاش را هنگام خروج ببینید: tcpdump -ni any host 10.20.30.40 درخواست ارسالشده را در سمت host-only و درخواست ترجمهشده را روی تونل نشان میدهد. درخواستی که بیرون میرود، برمیگردد و باز هم میزبان را بیصدا میگذارد، به مسیر بازگشت اشاره میکند.
دو شکست بیشتر این وضعیت را توضیح میدهند. یا تونل مهمان مسیر بازگشتی برای پیشوند host-only حمل نمیکند چون قاعده NAT وجود ندارد، یا مسیر میزبان به نشانیای اشاره میکند که مهمان پس از راهاندازی مجدد دیگر ندارد. نشانیها را با ip -br addr و ip route get دوباره بخوانید، بهجای اعتماد به یادداشتهای نشست قبل.
بررسی 6: آن را از راهاندازی مجدد و ارتقای هایپروایزر جان سالم بهدر ببرید
هر دو نیمه را پایدار کنید: پیکربندی مسیر با netplan یا NetworkManager روی میزبان، route add ... -p در Windows، و net.ipv4.ip_forward=1 در /etc/sysctl.d/ بههمراه مجموعه قواعد فایروالی که در مهمان دوباره بارگذاری میشود. بهمحض اینکه پیکربندی تأیید شد، پیش از رسیدن بهروزرسانی بعدی کلاینت شرکتی، از مهمان snapshot بگیرید.
شبکههای host-only وقتی هایپروایزر آداپتورهایش را از نو میسازد شمارهگذاری مجدد میشوند، و این بیصدا همه مسیرها و قواعد NATی را که روی 192.168.56.0/24 ساخته شدهاند بیاعتبار میکند. پس از ارتقا، سه بررسی اول را به ترتیب دوباره اجرا کنید؛ این یک دقیقه وقت میگیرد و حالتی را میگیرد که میزبان هنوز مسیر خودش را دارد ولی مهمان به زیرشبکهای جدید رفته است.
IPv6 پاس خودش را لازم دارد. قواعد ip6tables، رکوردهای AAAA و خانواده دوم مسیرهای میزبان از پیکربندی IPv4 پیروی نمیکنند، و سرویس شرکتی که از طریق IPv6 قابل دسترسی است در حالی که IPv4 کار میکند دائماً خراب به نظر میرسد.
قبول یا رد، به ترتیب: میزبان میتواند نشانی host-only مهمان را ping کند؛ مهمان به سمت تونل ارسال و MASQUERADE میکند؛ ip route get مهمان را بهعنوان دروازه پیشوند داخلی برمیگرداند؛ نامهای شرکتی از طریق حلکننده محدود حل میشوند؛ traceroute مهمان را اول نشان میدهد؛ و همان شش پاسخ از راهاندازی مجدد جان سالم بهدر میبرند.