Ваше устройство находится за NAT оператора, может открывать исходящие соединения и запускает SSH-сервер, до которого никто не доберётся. Приходящий запрос обычно формулируется как "дайте ему VPN", и это один ответ из нескольких. Прежде чем согласиться, решите, нужен ли вам один административный TCP-порт или маршрутизируемый путь ко всей подсети, потому что это разные проекты с разной экспозицией.

Обратный туннель хорошо отвечает на узкую версию. Устройство дозванивается до вашего концентратора, просит его слушать на loopback-порту и перенаправляет этот порт назад в свой SSH-сервис. Затем администраторы попадают к слушателю через концентратор, а не через публичный интернет.

Три условия, которые решают выбор

Запишите их до любой настройки. Это граница между ограниченным административным входом и расширением сети, и их смешение — тот путь, на котором туннель из пяти строк превращается в бесхозную плоскую сеть.

ConditionReverse tunnel fitsSomething else is needed
How many services must be reachable?One, or a small fixed set on loopbackAnything that needs many ports or dynamic discovery
Who connects, and how are they authenticated?Named administrators with their own hub accountsThird parties, or anything needing per-flow audit you do not control
Does the device's own LAN need to be reachable?NoYes, so a routed VPN or a managed platform is the honest answer

Третья строка — та, о которой спорят. Туннель к SSH-порту устройства не помещает его соседей в вашу сеть, и не стоит через цепочку дополнительных перенаправлений делать вид, что помещает. Если требование действительно LAN, так и скажите и проектируйте именно её.

Сторона концентратора: ограниченная учётная запись реле

Дайте каждому устройству собственную учётную запись реле с аутентификацией по открытому ключу и без интерактивной сессии. Match блок, ограниченный этой учётной записью, держит разрешение маленьким, а закрытый ключ остаётся на устройстве, где ему место.

Match User relay-dev-7
    AuthenticationMethods publickey
    PubkeyAuthentication yes
    AllowTcpForwarding remote
    PermitListen 127.0.0.1:21022
    GatewayPorts no
    MaxSessions 0
    PermitTTY no
    X11Forwarding no
    AllowAgentForwarding no

MaxSessions 0 — интересная строка. Он запрещает сессии оболочки и подсистем, но по-прежнему разрешает перенаправление, нужное устройству, поэтому украденный ключ нельзя превратить в интерактивный вход. PermitListen фиксирует адрес и порт слушателя на стороне концентратора, и GatewayPorts no держит его на loopback вместо того, чтобы открывать в сеть, где стоит концентратор.

Проверьте действующую конфигурацию перед перезагрузкой и держите вторую сессию открытой, пока это делаете. Match блок, который случайно применяется ко всем, или опечатка в имени опции — классический способ запереть себя снаружи машины, которую вы укрепляете. Выгрузите работающую конфигурацию и перечитайте опции, а не доверяйте только что написанному файлу. Учтите, что поддержка опций различается между сборками, поэтому принятая в новом сервере строка может просто игнорироваться старым.

Сторона устройства: перенаправление, которое громко падает

Устройство открывает соединение и запрашивает слушатель. Два адреса в аргументе -R означают разное, и чтение их слева направо — самый быстрый способ запомнить, какой из них какой.

ssh -NT \
    -o ExitOnForwardFailure=yes \
    -o ServerAliveInterval=30 \
    -o ServerAliveCountMax=3 \
    -R 127.0.0.1:21022:127.0.0.1:22 \
    [email protected]

Левая пара — это то, где должен слушать концентратор. Правая пара — то, к чему устройство подключается, когда приходит запрос, разрешаемое с его собственной стороны. Если их поменять, получится туннель, который чисто поднимается и перенаправляет не туда, а это хуже отказа.

ExitOnForwardFailure=yes заставляет команду выходить, когда запрошенный слушатель не удаётся поднять, поэтому цикл перезапуска говорит вам правду вместо того, чтобы оставить полурабочую сессию. Он ничего не говорит о том, здоров ли локальный SSH-сервис позже, поэтому сочетайте его с менеджером процессов и эпизодической настоящей проверкой соединения.

Никогда не заменяйте адрес прослушивания loopback шаблоном, чтобы обойтись без лишнего перехода. Это единственное изменение — разница между административным путём и публично доступным портом, и обычно оно случается при отладке, а потом остаётся. Если коллега не может добраться до порта через концентратор, исправьте конфигурацию перехода, а не расширяйте привязку. Loopback — весь аргумент безопасности этого проекта.

Доступ администратора через концентратор

Администратор с обычной учётной записью на концентраторе может прыгнуть через него до перенаправленного порта. Учётная запись реле для этого не используется, и именно в этом смысл держать их раздельно.

ssh -J [email protected] -o HostKeyAlias=device-7 \
    -p 21022 [email protected]

Проверьте ключ хоста устройства под выбранным псевдонимом, потому что этот ключ идентифицирует устройство в конце цепочки, а туннель — только транспорт. Вход от конца до конца по-прежнему аутентифицирует обе стороны; туннель, заканчивающийся на общем концентраторе, не делает его сам по себе доверенным путём.

Возьмите на себя жизненный цикл

Запускайте команду устройства под менеджером процессов ровно с одним активным экземпляром и политикой перезапуска, которую вы выбрали сознательно. Опции keepalive обнаруживают мёртвого партнёра; они не воскрешают процесс, который завершился.

Затем напишите процедуру вывода из эксплуатации. Каждое устройство получает свой слушатель и свой ключ, поэтому вывод означает отзыв этой учётной записи и удаление этого ключа, а не ротацию общего для всего парка секрета.

Наконец, помните, что даёт вам loopback. Он ограничивает сетевую экспозицию и ничего не делает с другими локальными пользователями на общем концентраторе, поэтому политика доступа самого концентратора всё равно должна быть правильной. Справочник по sshd_config описывает каждую из использованных выше опций, и стоит полностью прочитать разделы о перенаправлении, прежде чем расширять любую из них.

Похожие статьи