Один із маршрутів назовні з цієї робочої станції — проксі SOCKS, і OpenVPN за ним повідомляє про тайм-аут з'єднання без жодних корисних подробиць. Браузер на тій самій машині працює через цей проксі, облікові дані правильні, і порт відповідає. Три речі розходяться досить часто, щоб перевірити їх першими: версія SOCKS, якою говорить проксі, транспорт, який вибрав клієнт, і те місце, де відбувається розв'язання імен. Підтвердьте кожну, перш ніж звинувачувати міжмережевий екран.

Узгодьте версію SOCKS до міжмережевого екрана

Community OpenVPN говорить SOCKS5 для socks-proxy. Спрямуйте його на проксі, який пропонує лише SOCKS4, і TCP-з'єднання відкриється, а потім зависне: клієнт чекає відповіді на привітання, яке інша сторона ніколи не розбирає. Ззовні це зависання виглядає точно як відфільтрований порт, тому питання версії йде раніше за будь-яке правило міжмережевого екрана. Одне завантаження з підтримкою SOCKS вирішує це однією командою.

curl --socks5-hostname 127.0.0.1:9050 gw.lab.example

Завершений запит доводить одразу дві речі: проксі прийняв запит SOCKS і розв'язав ім'я. Схема URL не потрібна, бо curl вважає голе ім'я хоста HTTP, і для цього тесту цього достатньо.

Це завантаження також виключає збій, який приховує журнал клієнта. Проксі може дозволити браузер і все одно відмовити в призначенні VPN, і тоді відмова відбувається на CONNECT, до будь-якої автентифікації VPN. OpenVPN повідомляє лише про тайм-аут, тому власна відповідь проксі — це доказ, який вам потрібен.

Транспорт має бути TCP з обох боків

Тут SOCKS5 несе потік TCP, тому самому тунелю потрібен proto tcp-client. Профіль, досі налаштований на UDP, цим шляхом не працюватиме, бо клієнт не використовує режим UDP-асоціації протоколу. Перемикання профілю — це справжня зміна, а не формальність: далекий бік має слухати TCP на тому самому порту. Далі корисне навантаження стає TCP усередині TCP, де втрачений сегмент повторюється двічі й темп падає, що інтерактивні сеанси помічають значно сильніше, ніж великі передачі.

proto tcp-client
remote gw.lab.example 8443
socks-proxy 127.0.0.1 9050

Директива приймає хост проксі, необов'язковий порт і необов'язковий файл облікових даних. Помістіть їх у сам профіль, щоб копія поводилася так само в іншому місці.

Замкніть увесь ланцюжок в одному контейнері

Робити ланцюжок на хості означає зайняти його маршрут за замовчуванням і залишити розпізнавач у стані, який потім ніхто не пояснить. Простір імен або контейнер обмежують його натомість, тож хост зберігає свій шлях, а крок SOCKS і тунель живуть разом. Усередині нічого не підніметься без пристрою тунелю, прав на його налаштування й доступного проксі. Сервіс Compose отримує це з cap_add: NET_ADMIN і примонтованим /dev/net/tun.

cap_add:
  - NET_ADMIN
devices:
  - /dev/net/tun:/dev/net/tun

Ця пара вужча, ніж запуск контейнера в привілейованому режимі, і це весь потрібний доступ до пристрою. Клієнт Tor або окремий контейнер проксі може дати слухача. У будь-якому разі прив'яжіть його до loopback і дістаньтеся з простору імен через хост, замість виставляти проксі в мережу.

Розв'язання імен — саме там ізоляція зазнає невдачі

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

docker compose exec vpn cat /etc/resolv.conf
docker compose exec vpn getent hosts internal.lab.example

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

Доведіть кожен крок по черзі

Список короткий. Запит SOCKS5 отримує відповідь, тунель доходить до свого слухача через проксі, а пакети, що покидають простір імен, несуть адресу, якої чекає далекий бік. Підтверджуйте по одному, замість нарощувати конфігурацію. Коли клієнт каже «підключено», а нічого не рухається, розрив майже завжди в другому або третьому факті.

curl --socks5-hostname 127.0.0.1:9050 gw.lab.example
docker compose exec vpn ip route get 203.0.113.10
docker compose exec vpn getent hosts internal.lab.example

Запишіть поєднання, яке спрацювало: версія SOCKS, транспорт, розпізнавач і налаштування простору імен. Розв'язувати цей ланцюжок удруге з пам'яті дорожче за нотатку. Тримайте ці чотири факти в тікеті, а не в чаті.

Ланцюжок, який повідомляє «підключено» і нічого не пропускає, зазвичай зламався на тому кроці, який ви ще не довели. Перевірте цей крок, перш ніж додавати ще один шар.

Схожі статті