روشن کردن یک کلاینت OpenVPN با تونل کامل روی ماشینی که از طریق SSH به آن می‌رسید می‌تواند نشست را در کمتر از یک ثانیه قطع کند، و ماشین هیچ کار اشتباهی نمی‌کند. تونل تغییر نمی‌دهد که بسته‌ها چگونه به سرور می‌رسند؛ تغییر می‌دهد که پاسخ‌ها چگونه خارج می‌شوند. به محض اینکه مسیر پیش‌فرض به tun0 اشاره کند، پاسخ به کلاینت SSH شما به شبکه ارائه‌دهنده می‌رود که هیچ مسیری برای بازگشت به آدرس شما ندارد. اتصال معلق می‌شود، تلاش بعدی منقضی می‌شود، و دیمن تمام این مدت روی پورت 22 گوش می‌دهد.

جدول مسیریابی را پیش از گزارش VPN بخوانید. گزارش می‌گوید تونل بالا آمده و درست هم می‌گوید. پرسش این است که هر پاسخ به کدام رابط تحویل داده می‌شود، و این جست‌وجویی برای هر بسته در جدولی است که تونل همین حالا بازنویسی کرده است.

چرا پاسخ از در اشتباه بیرون می‌رود

بسته‌های ورودی همچنان روی رابط فیزیکی می‌رسند، چون کلاینت VPN نمی‌تواند تغییر دهد که اینترنت چگونه به آدرس عمومی سرور شما می‌رسد. پاسخ‌ها تصمیمی جداگانه‌اند: برای هر بسته، هسته مقصد را جست‌وجو می‌کند، و پس از --redirect-gateway ورودی پیش‌فرض می‌گوید تونل. خروجی ارائه‌دهنده مقصدی می‌بیند که آن را سرویس نمی‌دهد و بسته را دور می‌ریزد.

محافظت خود OpenVPN دقیقاً یک مقصد را پوشش می‌دهد. راهنمای نسخه 2.6 گزینه --redirect-gateway را به عنوان یک توالی توصیف می‌کند: یک مسیر میزبان برای peer وی‌پی‌ان از طریق دروازه‌ای که پیش از تونل در استفاده بود اضافه می‌کند تا ترافیک رمزنگاری‌شده نتواند به داخل خودش برگردد، و سپس مسیر پیش‌فرض را جایگزین می‌کند. آن مسیر میزبان فقط برای peer است. کلاینت SSH شما فقط یک آدرس اینترنتی دیگر است و هیچ استثنایی نمی‌گیرد.

یک خطای پیشوند ارزش دارد که زود کنار گذاشته شود. فرمان ip route add -net 0.0.0.0 gw 10.8.0.1 dev tun0 بدون طول با آدرس تک 0.0.0.0 مطابقت دارد، نه با اینترنت؛ باید 0.0.0.0/0 باشد. و اگر گرفتن مسیر پیش‌فرض انتقال خود تونل را بشکند، نقطه پایانی را به عنوان مسیر میزبان از طریق رابط فیزیکی اضافه کنید، با استفاده از آدرس واقعی ارائه‌دهنده.

آدرس کلاینت SSH خود را برای تعمیر فوری ثابت کنید

سریع‌ترین تعمیر یک مسیر میزبان برای آدرس کلاینت شما از طریق دروازه‌ای است که سرور پیش از وجود تونل استفاده می‌کرد. از طرف خودتان، آدرسی را که سرور خواهد دید پیدا کنید، سپس جدول سرور را بخوانید تا دروازه قدیمی را بدانید:

curl -s https://ifconfig.co
ip route

روی سرور، استثنا را پیش از شروع کلاینت اضافه کنید. آدرس‌های اینجا جای‌نگهدار هستند؛ شکل مهم است:

sudo ip route add 80.128.240.55 via 192.168.178.1

این همان تعمیری است که در مورد گزارش‌شده استفاده شد و بلافاصله کار می‌کند. همچنین به دو روش قابل پیش‌بینی شکننده است: مسیر هنگام راه‌اندازی مجدد ناپدید می‌شود، و در همان لحظه‌ای که ISP آدرس دیگری به شما می‌دهد غلط می‌شود. آن را یک اقدام اضطراری بدانید و آگاهانه پایدارش کنید، از طریق یک واحد شبکه یا قلاب dispatcher، یا بپذیرید که موقتی است و مسیر بازیابی را بنویسید.

نگذارید کلاینت مسیر پیش‌فرض را بردارد

گزینه پاک‌تر این است که نگذارید تونل اصلاً مسیر پیش‌فرض را جایگزین کند. route-nopull، در ترکیب با --client یا --pull، گزینه‌های فشرده‌شده را می‌پذیرد به جز مسیرها، block-outside-dns و گزینه‌های سبک DHCP مانند سرورهای DNS، پس فقط پیشوندهایی را که لازم دارید اضافه می‌کنید. ابزار باریک‌تر یک فیلتر کشیدن است که یک دستور مشکل‌دار را حذف می‌کند و بقیه را نگه می‌دارد:

route-nopull
pull-filter ignore "redirect-gateway"

یکی یا دیگری را استفاده کنید، نه هر دو را، و روشن باشید چه چیزی تغییر می‌کند. بدون مسیر پیش‌فرض از طریق تونل، سرور دیگر اینترنت را از طریق ارائه‌دهنده مرور نمی‌کند؛ فقط به آنچه صریحاً مسیریابی کرده‌اید می‌رسد. اگر تونل کامل تمام هدف این راه‌اندازی بود، این کلید اشتباه است و مسیر میزبان بالا کلید درست است.

مسیر بازگشت را بر اساس منبع یا اتصال تقسیم کنید

وقتی آدرس ورودی پایدار است، یک قاعده منبع پاسخ‌ها را محلی نگه می‌دارد بدون اینکه به مسیرهای خود تونل دست بزند. به آدرس رابط فیزیکی جدول خودش را بدهید که پیشوند LAN و پیش‌فرض فیزیکی را دارد، سپس آن جدول را برای ترافیکی که از آن می‌آید انتخاب کنید:

ip rule add from 192.168.1.11 table 128
ip route add table 128 to 192.168.1.0/24 dev eth0
ip route add table 128 default via 192.168.1.1

این کار می‌کند چون پاسخ‌های یک اتصال SSH ورودی از آدرسی می‌آیند که کلاینت به آن متصل شده است. یک مورد گزارش‌شده که در آن هر سرویس ورودی باید به کار ادامه می‌داد دقیقاً از همین شکل استفاده کرد. وقتی آدرس ورودی شناور است یا مسیر پویاست، به جای آن اتصال را علامت بزنید: روی اولین بسته رسیده از رابط فیزیکی یک علامت conntrack بگذارید، آن را در OUTPUT روی بسته‌های پاسخ کپی کنید، و بسته‌های علامت‌خورده را از طریق جدولی که به دروازه فیزیکی اشاره می‌کند مسیریابی کنید.

iptables -t mangle -A PREROUTING -i eth0 -m conntrack --ctstate NEW -j CONNMARK --set-mark 1234
iptables -t mangle -A OUTPUT -m connmark --mark 1234 -j MARK --set-mark 4321
ip route add default via 192.168.1.1 dev eth0 table 3412
ip rule add fwmark 4321 table 3412

در حین آزمایش علامت اتصال، علامت دیوار آتش و شماره جدول را جدا نگه دارید. استفاده مجدد از یک شماره برای دو نقش قاعده‌ای می‌سازد که درست به نظر می‌رسد و بسته‌های اشتباه را مطابقت می‌دهد. ورودی پیش‌فرض جدول همچنین به via با دروازه LAN روی یک پیوند اترنت معمولی نیاز دارد؛ dev eth0 خالی فقط وقتی کار می‌کند که رابط نقطه‌به‌نقطه باشد یا گام بعدی به روش دیگری حل شود. میزبان Jessie گزارش‌شده تصادفاً روی پیوندی بود که شکل خالی در آن کار می‌کرد، و این قاعده‌ای برای توزیع نیست که کپی شود.

بدون قفل شدن بیرون بررسی کنید

با قطع کردن آزمایش نکنید. نشست اول را باز نگه دارید، تونل را بالا بیاورید، و از هسته بپرسید آدرس خودتان کدام مسیر را می‌گیرد:

ip route get 80.128.240.55

پاسخ باید رابط فیزیکی و دروازه قدیمی را نام ببرد، نه تونل را. سپس یک اتصال SSH دوم باز کنید؛ این آزمایش واقعی است، چون نشست قدیمی ممکن است روی وضعیتی زنده بماند که اتصال جدید نمی‌تواند بازتولید کند. اگر دومی معلق شود در حالی که اولی هنوز پاسخ می‌دهد، قاعده هرگز با ترافیکی که مهم است مطابقت نکرده، و علامت‌ها یا آدرس منبع جایی است که باید نگاه کنید.

در تمام مدت تمرین یک کنسول خارج از باند در دسترس نگه دارید. سروری که تنها مسیر دسترسی‌اش تونلی است که همین حالا شکسته‌اید از طریق همان تونل قابل تعمیر نیست، و عقب‌گرد آسان‌تر است وقتی شماره‌های جدول و پیشوندهایی را که اضافه کرده‌اید نوشته‌اید.

مقالات مرتبط