Динамічне переспрямування SSH як SOCKS-проксі поверх вашої VPN
У застосунку, який говорить лише SOCKS, у звичайній VPN немає проксі-кінцевої точки. Два переходи, один локальний слухач і один пошук імені, який сервер SSH має виконати сам.
Застосунку, який говорить лише SOCKS, немає з ким розмовляти у звичайній VPN, бо тунель переносить пакети, а застосунок хоче проксі-кінцеву точку. OpenSSH може надати цю точку, якщо власник доступу дозволяє, оскільки динамічне переспрямування перетворює один сеанс SSH на локальний проксі. Далі є два переходи, які треба тримати окремо: тунель, що досягає хоста SSH, і з'єднання, яке цей хост відкриває далі. Їх розділення пояснює і те, чому схема працює, і те, чого вона ніколи не зробить.
Чим слухач SSH стає, а чим ні
Динамічне переспрямування змушує клієнт SSH слухати локально й говорити SOCKS4 або SOCKS5 з усім, що підключається. Кожен запит називає пункт призначення, і сервер SSH відкриває наступне з'єднання, тому пошук пункту призначення може відбуватися на дальньому боці. Це переспрямування TCP на рівні застосунку, а не VPN для всього пристрою. Воно не несе ні UDP-асоціації, ні ICMP, ні чогось для застосунків, які повністю ігнорують налаштування проксі. Перехід від сервера SSH до застосунку теж не всередині вашого тунелю, що важливо, коли пункт призначення приймає трафік лише з відомих мереж.
Передумови реальні: маршрут до хоста SSH, авторизований обліковий запис, перевірений ключ хоста сервера й дозвіл на переспрямування. Жодної з них не створює проксі, а остання зазвичай відсутня першою. Підтвердьте всі чотири, перш ніж щось інше налагоджувати, бо з боку клієнта збій виглядає однаково, якої б не бракувало.
Запустіть його на loopback з явним портом
Виберіть невикористаний локальний порт і явно прив'яжіть його до loopback, а не залишайте адресу порожньою. Три варіанти нижче існують кожен з однієї причини.
ssh -D 127.0.0.1:1080 -NT -o ControlPath=none -o ExitOnForwardFailure=yes \
[email protected]
-N пропускає віддалену команду, а -T пропускає псевдотермінал, тож сеанс існує лише для переспрямування. ExitOnForwardFailure змушує клієнт завершитися, коли слухача не можна створити, замість роботи без запитаного переспрямування. ControlPath=none тримає сеанс поза наявним мультиплексованим з'єднанням, яке могло б додати власні переспрямування. Loopback тримає слухач поза LAN, але на спільній машині це не межа авторизації, бо до нього можуть дістатися й інші локальні процеси. Довідка клієнта OpenSSH документує всі ці прапорці, а попередження про loopback випливає з того, чим є сокет, що слухає.
Надсилайте імена через проксі, а не повз нього
Клієнт SOCKS5 може сам розв'язати пункт призначення або попросити проксі зробити це, і цей вибір визначає, який резолвер відповість. З socks5h curl надсилає ім'я хоста через проксі, тож пошук відбувається на сервері SSH. Зі звичайним socks5 ноутбук розв'язує першим і подорожує лише з'єднання, що тихо знецінює сенс, коли ім'я внутрішнє. Запит нижче також очищає список без проксі, щоб успадковане значення NO_PROXY не могло провести його повз проксі.
curl -sS --noproxy '' --proxy socks5h://127.0.0.1:1080 https://app.corp.example/health
Перевірка сертифіката й власний вхід застосунку все ще діють, бо проксі не замінює ні того, ні того. Залишаються два пошуки: ноутбук має досягти хоста SSH дозволеним шляхом VPN і DNS, а сервер SSH має сам розв'язати ім'я застосунку. Другий можна перевірити окремо, перш ніж через проксі піде будь-який трафік.
ssh [email protected] getent hosts app.corp.example
Доведіть один дозволений пункт призначення, потім закрийте сеанс
Перевірте пункт призначення, який політика дозволяє, і той, який вона має відхилити, бо робоче переспрямування доводить лише те, що слухач працює, і нічого більше. Застосунок бачить адресу джерела, яку вибирає сервер SSH, і це не адреса тунелю вашого ноутбука. Там, де дальній бік журналює з'єднання за джерелом, саме ця різниця є першим, що треба перевірити, коли запит відхилено.
Зупиніть сеанс через процес, який ним володіє, а не вбиваючи сторонню оболонку. Потім переконайтеся, що слухач зник, бо порт, який ще відповідає, — це сеанс, який ви насправді не закрили. Видаліть лише налаштування проксі, яке ввів цей приклад, і залиште решту конфігурації застосунку спокійно. Термінал без нагляду з правилом переспрямування — не сервіс, і постійному проксі потрібен схвалений життєвий цикл, а не забуте вікно.
ss -ltn | grep 1080
Збої, які ця схема не може виправити
Деякі симптоми вказують прямо на наведені вище межі, і раннє їх розпізнавання економить пів дня налагодження проксі. Таблиця пов'язує те, що ви бачите, з тим, що це зазвичай означає. Усе в останньому стовпці — питання проєктування, а не помилка конфігурації.
| What you see | What it usually means | Where to look |
|---|---|---|
| The app connects and nothing follows | It ignores proxy settings entirely | Its own network settings, not the SSH session |
| A name resolution error for the destination | The SSH server cannot resolve it | Server resolver and search domains |
| A UDP-only application fails | Dynamic forwarding carries TCP only | This arrangement cannot serve it |
| curl works, the browser does not | The browser is not using the socks5h endpoint | Browser proxy configuration |
| The listener answers after the session ended | Another process owns port 1080 | The ss output, then the owning process |
Перші три рядки — ті, які люди діагностують неправильно, бо кожен дає спробу з'єднання замість помилки про сам проксі. Ім'я, що розв'язується на ноутбуці, нічого не каже про резолвер сервера, і збій читається радше як проблема сертифіката або тайм-ауту. Застосунки лише з UDP стоять поза схемою, а не зламані всередині неї, і жодна додаткова опція ssh цього не змінює. Рядок про браузер — звичайне нагадування, що налаштування проксі задаються для кожного застосунку. Останній рядок — причина, чому існує перевірка під час закриття: порт, який ще слухає, означає, що тепер ним володіє щось інше.