چگونه خروجی لینوکس را قفل کنیم تا هنگام قطع VPN چیزی نشت نکند
مسیریابی و فیلترکردن دو تصمیم جدا هستند. قلاب خروجی را قفل کنید و سپس استثناهای نقطه پایانی، DNS و مدیریت را که تونل برای اتصال دوباره لازم دارد محدود کنید.
یک باکس رسانه روی اتصال خانگی را تصور کنید که قرار است فقط از طریق یک تونل به اینترنت برسد. وقتی تونل قطع میشود، برنامه باید متوقف شود نه اینکه بیصدا روی رابط فیزیکی ادامه دهد. رسیدن به این رفتار مسئلهی دیوار آتش است نه مسیریابی، و این تمایز مهم است چون مسیر را میتوان با راهاندازی دوبارهی سرویس عوض کرد، در حالی که فیلتر همانجا میماند که گذاشتهاید. در ادامه میبینید که مسیر بسته در واقع چگونه تصمیم میگیرد و سپس چگونه استثناهایی را که تونل را در حال اتصال دوباره نگه میدارند محدود کنید.
خروجی محلی قلابی متفاوت از ارسال است
بستهای که از برنامهای روی دستگاه خارج میشود از قلاب خروجی میگذرد؛ بستهای که دستگاه برای میزبان دیگری مسیریابی میکند از ارسال میگذرد. سیاستی که فقط forward را نام میبرد دومی را محدود میکند و اولی را کاملاً باز میگذارد، و به همین دلیل بسیاری از قفلهای خروجی درست به نظر میرسند و کاری نمیکنند. تطبیق رابط به همان قاعده تعلق دارد: oifname "tun0" accept ترافیکی را عبور میدهد که پیشتر از تونل مسیریابی شده است. مسیریابی و فیلترکردن نیز دو تصمیم جدا میمانند، بنابراین میتوان مسیری برای اتصال وجود داشته باشد در حالی که فیلتر بسته را رد میکند. شما به همین جداسازی تکیه میکنید.
دروازهای که برای دستگاههای دیگر ارسال میکند به هر دو قلاب نیاز دارد. قفلکردن تنها خروجی، خود دستگاه را محافظت میکند و هر کارخواه پاییندست را برای نشت آزاد میگذارد.
فهرست استثناها را از نقطه پایانی به بیرون بنویسید
از نقطه پایانی تونل شروع کنید: یک نشانی مقصد یا مجموعهی کوچک تأییدشده، پروتکل انتقال و درگاه مقصد، برای نمونه udp dport 1194 ip daddr 203.0.113.7 accept. اگر کارخواه نام میزبان را حل میکند، تبادل DNS آغازین به قاعدهی خودش محدود به resolver و درگاه 53 نیاز دارد، نه اجازهی کلی به نشانی آن resolver. هر استثنا باید دلیلی را که برای آن وجود دارد نام ببرد. اجازه برای همهی ترافیک UDP به درگاه VPN بسیار بیشتر از آن یک سرویس تأییدشدهای را که در ذهن داشتید پوشش میدهد.
حل آغازین همان جایی است که قفلها معمولاً میپوسند. مجموعهی نشانیای که با زمانسنج تازه میشود به رفتار مشخصی نیاز دارد وقتی تازهسازی شکست میخورد، و این رفتار نمیتواند بازکردن اتصال تا موفقشدن باشد. تا وقتی تونل برپاست از طریق تونل تازه کنید، و در غیر این صورت به آخرین نقطه پایانی سالم شناختهشده برگردید.
مدیریت محلی هم به همین رفتار نیاز دارد. یک زیرشبکهی مدیریت فقط به این دلیل که نشانیهایش خصوصی است قابل اعتماد نیست، و قاعدهای که به آن اعتماد کند مسیر دومی دور قفل دعوت میکند.
تطبیق رابط اثبات سلامت تونل نیست
قاعدههایی که هر چیزی را که از tun0 خارج میشود میپذیرند فرض میکنند بستهای روی آن رابط از تونل آمده است. نام رابطها دوباره ساخته میشوند، و یک نام هویت رمزنگاری نیست. همتا هم میتواند رفته باشد در حالی که رابط برپا میماند، که قاعده را به یک بیاثری بسیار قانعکننده تبدیل میکند.
ردیابی اتصال تلهی مرتبطی را اضافه میکند. قاعدهی گسترده برای اتصالهای برقرارشده اجازهای را که یک جریان پیشتر گرفته بود بازپخش میکند، بنابراین نشستی که پیش از قطع تونل آغاز شده بعد از آن هم کار میکند. پذیرش حالتمند را به رابطها و نشانیهایی که واقعاً منظورتان است محدود کنید، وگرنه قفلی ساختهاید که خودش را باز میکند. قاعدههای ورودی و خروجی هم به پرسشهای متفاوتی پاسخ میدهند، و سختکردن یکی با نادیدهگرفتن دیگری دستگاه را در جهتی که در نظر نگرفتهاید در دسترس میگذارد.
چه چیزی از سقوط سرویس جان سالم میبرد
فیلتری که اسکریپتی پس از بالا آمدن تونل نصب میکند همراه با تونل ناپدید میشود، درست همان لحظهای که لازم بود. قفل را هنگام بوت بارگذاری کنید و بگذارید سرویس فقط استثناهای خودش را مدیریت کند.
حذف مسیر پیشفرض هم جایگزین نیست. مسیر وضعیتی است که سرویس مالک آن است و بازنویسی میکند، و حذف آن میتواند راه لازم برای اتصال دوباره را بگیرد. IPv6 به برنامهی خودش نیاز دارد، چون کشف همسایه و اعلانهای مسیریاب سرویسهای پیوند هستند که باید کار کنند در حالی که ترافیک عادی مسدود است. DHCP در همان دسته است. اینها را بهعنوان استثنا با هدف بنویسید، نه اینکه بعداً بهصورت قطعی کشفشان کنید.
مسیر بازیابی پیش از استقرار
قفل را همانطور که شکست میخورد آزمایش کنید: بوت بدون تونل، کشتن سرویس، تغییر نقطه پایانی و اتصال دوباره. هر مورد باید برنامهها را متوقف کند و کانال بازیابی را فعال نگه دارد. این کار را از کنسول انجام دهید، چون پوستهی راه دور همان نشستی است که بیشترین احتمال قفلشدن با قاعدهی خودتان را دارد.
سپس بررسی کنید یک برنامهی معمولی هنوز به چه چیزی میرسد، با مقصدی بیخطر و درخواستی که بتوانید بررسی کنید. نتیجهای که میخواهید رد شدن روی اتصال و موفقیت از طریق تونل است، نه یک وقفهی مبهم که میتواند هر دو معنی را بدهد. مجموعهقواعد را زیر همان مالکیت بقیهی دیوار آتش نگه دارید، بهجای اینکه کل جدول را از یک اسکریپت پوسته جایگزین کنید. سیاستی که در آن هر اجازه بتواند خودش را توجیه کند ارزشمندتر از مجموعهقواعد بلندی است که هیچکس نمیتواند توضیحش دهد.