آیا کلاینتهای دو سرور OpenVPN به یکدیگر دسترسی دارند؟
دو سرور OpenVPN دو استخر کلاینت میسازند، نه یک شبکه. با زیرشبکههای متمایز، مسیرهای دوطرفه و مرز اعتماد صریح بین آنها مسیریابی کنید.
برپا کردن یک OpenVPN سرور دوم به شما جای دومی برای اتصال کلاینتها میدهد و نه بیشتر. این کار آن کلاینتها را روی شبکهٔ سرور اول قرار نمیدهد، و گزینهای به نام client-to-client فقط ارسال بسته درون یک فرایند سرور واحد را تغییر میدهد. دو استخر زمانی یک شبکه میشوند که آگاهانه بین آنها مسیریابی کنید، با یک مسئول برای هر جهت. همهٔ موارد زیر حالت TUN در فضای کاربر را با آن ارسال درونی خاموش فرض میکنند، بنابراین تصمیم با هسته است.
افسانه: یک فهرست حساب، یک شبکه
احراز هویت و دسترسپذیری با هم اشتباه گرفته میشوند چون هر دو در پیکربندی سرور زندگی میکنند. کاربری که میتواند به هر یک از دو دروازه وارد شود، از بیرون مثل کاربر یک سامانه با دو در به نظر میرسد. در داخل، هر سرور نشانیها را از استخر خود توزیع میکند و مسیرها را فقط برای کلاینتهایی نصب میکند که آنها را پایان میدهد. بنابراین کلاینتی روی دروازهٔ A که بستهای به کلاینتی روی دروازهٔ B میفرستد، مقصدی را میخواهد که سرور خودش هرگز از آن نشنیده است. بسته به مسیر پیشفرض A میرود، از تونل بیرون میآید و به دیوار آتشی میرسد که هرگز از او اجازه خواسته نشده است.
پس افزودن سرور دوم افزونهگی، کشف یا دامنهٔ پخش مشترک اضافه نمیکند. یک شبکهٔ مسیریابیشده اضافه میکند که به نقشه نیاز دارد، و نقشه با آدرسدهی آغاز میشود.
به هر دروازه استخر و نشانی ترانزیت خودش را بدهید
دو بازه که نمیتوانند با هیچ چیز دیگری همپوشانی داشته باشند، بههمراه یک پیوند ترانزیت کوچک بین میزبانها، کل نقشهٔ نشانی است. ترانزیت را روی بخش خصوصی که کنترل میکنید نگه دارید و پیش از آنکه هیچ سروری اجارهای بدهد، اعداد را بنویسید.
| Gateway | Client pool | Transit address |
|---|---|---|
| gateway-a | 10.64.10.0/24 | 172.28.44.1/30 |
| gateway-b | 10.64.20.0/24 | 172.28.44.2/30 |
در برابر وسوسهٔ دادن استخر یکسان به دو سرور مقاومت کنید تا پروفایلها یکسان بمانند. یک مسیر هسته نمیتواند بگوید کدام یک از دو میزبان در حال حاضر مالک نشانی دلبخواهی درون یک بازهٔ مشترک است، پس جدول مسیریابی به یک دروازه اشاره میکرد و ممکن بود کلاینت به دیگری متصل باشد. نامهای واسط قراردادهای محلیاند، نه وضعیت مشترک. هر دو میزبان اینجا دستگاه تونل را tun0 و پیوند ترانزیت را transit0 مینامند، که درست است چون هیچ بستهای این نامها را حمل نمیکند.
مسیر را در هر دو طرف نصب کنید
هر دروازه به مسیری برای استخر دیگری از طریق نشانی ترانزیت نیاز دارد، و ارسال بسته باید روشن باشد تا هر یک بتواند نقش پرش را ایفا کند. ابتدا جدول کنونی را تأیید کنید، سپس ورودی را اضافه کنید و آن را از طریق مدیر شبکهٔ میزبان ماندگار کنید نه با قلاب اتصال دوباره.
sysctl net.ipv4.ip_forward
ip route add 10.64.20.0/24 via 172.28.44.2 dev transit0
ip route get 10.64.20.37
همین را با استخرهای جابهجاشده روی میزبان دیگر تکرار کنید. افزودن مکرر همان مسیر از یک اسکریپت بیربط همان راهی است که میزبان با چند نسخه و تغییر مرموز دفعهٔ بعد که کسی جدول را میخواند روبهرو میشود. اگر پیوند ترانزیت خودش تونل باشد، مسیر به توپولوژی آن تونل اشاره میکند و پرش باید از اتصال دوبارهٔ آن جان سالم به در ببرد. نشانی ترانزیتی که سی ثانیه ناپدید شود، مسیر بین دو استخر را با خود میبرد، که ویژگی طراحی است و بهتر است آن را اعلام کرد تا کشف.
مسیر کلاینت را بدون جعل مالکیت هل بدهید
کلاینتها به مسیری برای استخر دوردست نیاز دارند، وگرنه سیستمعامل خودشان بسته را به دروازهٔ پیشفرض میفرستد و تونل هرگز آن را نمیبیند. پیکربندی سرور جای طبیعی برای تحویل این است.
push "route 10.64.20.0 255.255.255.0"
خط آینه را در پیکربندی سرور دیگر بگذارید، سپس یک کلاینت آزمایشی را دوباره وصل کنید و جدولش را بخوانید. کلاینتی که مسیرهای هلدادهشده را نادیده میگیرد به پیکربندی تأییدشدهٔ خود نیاز دارد، و مسیری که هرگز نمیرسد کنترل دسترسی نیست. به کلاینت برای کل استخر دروازهٔ دیگر iroute ندهید. آن دستور برای زیرشبکهای پشت یک کلاینت متصل وجود دارد، و استفاده از آن برای پوشاندن مسیر گمشده بین دروازهها سروری میسازد که گمان میکند مالک نشانیهایی است که به آنها نمیرسد.
یک درخواست را اثبات کنید و دیگری را رد کنید
یک عملیات واقعی انتخاب کنید، مثلاً HTTPS از کلاینتی روی 10.64.10.21 به سرویسی روی 10.64.20.37، و دقیقاً همان را روی هر دو میزبان مجاز کنید. هر دیوار آتش درخواست را در سمت ورودی و پاسخ ردیابیشده را در سمت بازگشت میپذیرد؛ سیاست سرویس مقصد خودش هنوز باید آن را بپذیرد.
iptables -A FORWARD -i tun0 -o transit0 -s 10.64.10.21 -d 10.64.20.37 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -i transit0 -o tun0 -d 10.64.10.21 -s 10.64.20.37 -p tcp --sport 443 -m conntrack --ctstate ESTABLISHED -j ACCEPT
با مسیرهای دوطرفه، NAT مبدأ لازم نیست و اینجا فعالانه زیانآور است: ترجمهٔ مبدأ پنهان میکند کدام کلاینت درخواست را داده و سیاست مبتنی بر مبدأ در سمت مقصد را خنثی میکند. بررسی کنید قاعدهٔ masquerade موجود برای خروج به اینترنت این مسیر را هم نگیرد. سپس رد شدن را بیازمایید. سرویسی که باید در استخر B بومی بماند باید از استخر A دسترسناپذیر بماند، و جفتهای کلاینت روی یک دروازه هم باید آزموده شوند، چون سیاست ارسالی که همین حالا تغییر دادید بر آنها هم اعمال میشود.
یک اصلاح دیگر در مدل ذهنی: پیوند ترانزیت بستههای درونی رمزگشاییشده را حمل میکند، پس مرز اعتماد است نه تضمین خصوصی. اگر از شبکهای میگذرد که کنترلش نمیکنید، آن پرش را با تونل رمزنگاریشدهٔ تأییدشده محافظت کنید و از توپولوژی واقعیاش مسیریابی کنید. TLS سرتاسری هنوز خودش برنامه را احراز میکند، و به همین دلیل سرویس درونی باید همچنان از آن استفاده کند.