Вам потрібно вирішити, скільки техніки заслуговує ваша лабораторія VPN. Маршрутизована шлюзова VM між двома сегментами VirtualBox відтворює трансляцію адрес, зворотний шлях і позицію міжмережевого екрана, за яким сидить реальний клієнт. Один сегмент лише для хоста дає одні контрольовані двері й нічого більше. Версія зі шлюзом коштує три гості та таблицю маршрутизації, яку ви підтримуєте; версія лише для хоста коштує одного гостя й одну політику. Три питання розділяють їх, і третє вирішує, чи ваш тест узагалі може пройти.

Дайте відповідь на три питання, перш ніж щось клонувати

Почніть із того, що має спостерігати сервер VPN. Якщо сервер має бачити адресу джерела, яка не належить тестовому гостю, щось має транслювати між ними, і цим чимось має бути маршрутизатор, яким керуєте ви. Мережа лише для хоста дає хосту адаптер у сегменті гостя, а не транслятор. Коли гостю потім треба дістатися чогось ззовні, ви підключаєте адаптер NAT, і власний NAT-двигун VirtualBox переписує джерело, не питаючи вас.

Далі запитайте, чи може гість дістатися чогось іншого, ніж через тунель. Ця відповідь обирає внутрішню або лише для хоста, і це те питання, яке більшість описів лабораторій пропускає. Нарешті запитайте, що має статися, коли тунель падає, бо це визначає політику, а не топологію, а лабораторія, яка доводить лише щасливий шлях, не перевірила майже нічого.

What the test requiresRouted gateway VMHost-only guest
Server sees a translated source addressYes, from your own MASQUERADE ruleNo, VirtualBox NAT does it instead
The guest has exactly one egressYes, while the second adapter faces the tunnelOnly until a NAT adapter is attached
Policy is testable during a tunnel failureRules live in one placeRules live on each guest

З'єднайте три ролі внутрішніми мережами

Використайте три гості та два іменовані сегменти, а шлюз нехай буде єдиною машиною з адаптером на обох:

VBoxManage modifyvm lab-client --nic1 intnet --intnet1 WAN
VBoxManage modifyvm lab-server --nic1 intnet --intnet1 LAN
VBoxManage modifyvm lab-gw --nic1 intnet --intnet1 WAN --nic2 intnet --intnet2 LAN

Окремого кроку створення для внутрішньої мережі немає. Рядок у --intnet1 і є сегмент: дві машини ділять його лише за точного збігу назви, і ніщо на хості до нього не підключене. Саме ця остання властивість робить лабораторію чисто повторюваною, бо маршрути хоста, його власний клієнт VPN і його міжмережевий екран не можуть випадково дістатися гостей. Внутрішній сегмент також не має сервера DHCP, якщо ви його не додасте, тож статичні адреси — найкоротший шлях.

Дайте клієнту лише його WAN-адресу, а шлюз за замовчуванням має вказувати на WAN-адресу шлюзу. Сервер отримує LAN-адресу і використовує LAN-адресу шлюзу як свій шлюз за замовчуванням. У гостя, який тримає дві адреси на одному сегменті або має заблуканий маршрут до іншого сегмента, є шлях в обхід маршрутизатора, і тести нижче будуть вам брехати.

Я тримаю текстовий файл поруч із назвами VM з чотирма адресами й двома назвами сегментів і вставляю його в кожну оболонку. Тижні по тому, коли зміна профілю щось ламає, цей файл — різниця між налагодженням профілю й налагодженням власної пам'яті.

Виберіть внутрішню або лише для хоста для сегмента, який не має протікати

Режим лише для хоста створює віртуальний адаптер на самому хості, зазвичай vboxnet0, і дає хосту адресу в сегменті гостя. Це зручно для адміністрування і згубно для тесту ізоляції, бо хост тепер може дістатися гостя безпосередньо, і кожна служба на боці хоста стає можливим шляхом. Внутрішній режим не має адаптера хоста взагалі. Два режими легко переплутати в панелі налаштувань мережі, тож перевіряйте задокументовану різницю, а не позначку (перегляньте сторінку подробиці про мережу VirtualBox).

Для гостя, який мусить використовувати тунель, внутрішній режим — безпечніше значення за замовчуванням, а шлюз — єдиний вихід. Якщо ви залишаєте лише для хоста, ставтеся до адаптера хоста як до шляху керування і скажіть це вголос: хост може дістатися гостя, а гість не має мати можливості використовувати хост як вихід.

VBoxManage modifyvm lab-client --nic1 hostonly --hostonlyadapter1 vboxnet0

Ізоляція, яку ви можете довести, — це ізоляція, яку ви налаштували. У гостя з одним внутрішнім адаптером, маршрутом за замовчуванням на шлюзі й без адаптера NAT немає шляху в обхід шлюзу. У гостя з адаптером лише для хоста й адаптером NAT є два шляхи, і лише один із них — той, який ви хотіли перевірити.

Маршрутизуйте й транслюйте на шлюзі, а потім змусьте його відмовити закрито

VirtualBox не пересилає між сегментами; це робить гість. Коли VM сервера VPN стоїть за шлюзом, увімкніть пересилання й транслюйте трафік клієнта, коли він виходить до сервера:

sysctl -w net.ipv4.ip_forward=1
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

З цим правилом сервер бачить LAN-адресу шлюзу замість адреси клієнта, і саме так реальний клієнт за NAT оператора виглядає для головного вузла мережі. Збережіть значення sysctl у /etc/sysctl.d/, а правило — у тій службі міжмережевого екрана, яку використовує дистрибутив, інакше перезавантаження тихо поверне лабораторію в маршрутизований, але нетрансльований стан.

Пересилання — це не авторизація. За стандартної політики FORWARD зі значенням ACCEPT гість, чий маршрут за замовчуванням вказує на шлюз, виходить через той інтерфейс, який вибере таблиця маршрутизації, з тунелем або без. Якщо у шлюзу є ще й адаптер NAT для встановлення пакетів, цей адаптер — робочий незашифрований вихід у ту мить, коли тунель падає, і ваш тест «лише VPN» ніколи не був тестом «лише VPN».

Коли сервер віддалений, а тунель завершує сам шлюз, те саме рішення вказує на інтерфейс тунелю, а не на мережеву карту, яка виходить в інтернет:

iptables -P FORWARD DROP
iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT
iptables -A FORWARD -i tun0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

Тримайте власний зовнішній транспорт тунелю й позасмуговий маршрут керування окремо від пересиланого трафіку. Якщо єдиний спосіб полагодити шлюз — через тунель, який ви налагоджуєте, лабораторія стає вправою із замкнення. Послідовна консоль, адаптер керування лише для хоста або знімок відомого доброго стану дешевші за ручне відновлення зламаного маршрутизатора.

Перевіряйте шлях із боку гостя, а не хоста

Працюйте назовні. Підтвердьте, що клієнт дістається WAN-адреси шлюзу, потім сервера через шлюз, потім що з'єднання до порту VPN виходить і повертається. Запис на обох інтерфейсах шлюзу показує, чи надходить відповідь і чи відкидається вона на зворотному шляху, чого запис лише на клієнті розрізнити не може:

tcpdump -ni eth0 udp port 1194
tcpdump -ni tun0 udp port 1194

Потім доведіть вихід. Запитайте з гостя службу відображення адрес, яке джерело вона бачить, і порівняйте з власною вихідною адресою шлюзу; якщо відповідь збігається з адресою хоста, шлях в обхід тунелю існує. Перевірте, який розв'язувач гість насправді використовує, і перевірте IPv6 окремо, бо сегмент, де IPv6 увімкнено, а тунель несе лише IPv4, протікає за задумом, а не випадково.

Нарешті, зламайте це навмисно. Зупиніть тунель або заблокуйте його зовнішній порт і відкрийте нове з'єднання з гостя. Воно має не вдатися, і причина має бути такою, яку ви можете назвати: немає маршруту, є правило відхилення або розв'язувач мертвий. Перезапустіть тунель і підтвердьте, що гість відновлюється без перебудови мережі. Якщо mesh VPN на кшталт Hamachi або ZeroTier ділить лабораторію, пам'ятайте, що мостовий адаптер іде за назвою адаптера, а не за mesh, тож міст треба перенаправити після того, як клієнт встановить власний віртуальний адаптер.

VBoxManage list bridgedifs
VBoxManage modifyvm lab-client --bridgeadapter1 <mesh-adapter-name>

Спільне використання тунелю гостя з хостом відображає проблему. Спрямувати маршрут хоста за замовчуванням на гостя — працює, як і проксі всередині гостя; NAT через хост не несе тунель гостя для трафіку, який почав хост. Збережіть назви сегментів і правила міжмережевого екрана в одному місці, зробіть знімок робочого стану й запишіть адресу джерела, яку спостерігав сервер. Тоді наступна зміна профілю коштуватиме одного запуску скрипта замість перебудованої лабораторії.

Схожі статті