Динамично пренасочване на 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 сървърът избира, а това не е адресът на тунела на вашия лаптоп. Когато далечната страна записва връзките по източник, тази разлика е първото нещо за проверка, когато заявка бъде отказана.
Спрете сесията чрез процеса, който я притежава, вместо като убивате несвързан shell. След това потвърдете, че слушателят е изчезнал, защото порт, който още отговаря, е сесия, която всъщност не сте затворили. Премахнете само настройката за прокси, която това упражнение въведе, и оставете останалата конфигурация на приложението непокътната. Терминал без надзор с правило за пренасочване не е услуга и постоянното прокси изисква одобрен жизнен цикъл, а не забравен прозорец.
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 опция не променя това. Редът за браузъра е обичайното напомняне, че настройките за прокси са за всяко приложение поотделно. Последният ред е причината проверката при затваряне да съществува: порт, който още слуша, означава, че сега нещо друго го притежава.