SSH config и туннели: короткие подключения и port forwarding
Автор: Казачкин Даниил Михайлович · Обновлено
Файл SSH config превращает длинный набор параметров в проверяемый профиль подключения. Туннель затем использует то же защищённое соединение, чтобы передать TCP-трафик между…
Файл SSH config превращает длинный набор параметров в проверяемый профиль подключения. Туннель затем использует то же защищённое соединение, чтобы передать TCP-трафик между локальной и удалённой сторонами. Он не делает прикладной протокол безопасным вне границ tunnel.
Профиль Host без копирования команд
Конфигурация пользователя находится в ~/.ssh/config. Для учебной проверки удобно передать отдельный файл через -F и посмотреть вычисленный результат командой ssh -G без сетевого подключения.
config=$(mktemp)
chmod 600 "$config"
printf '%s\n' \
'Host demo' \
' HostName server.example' \
' User deploy' \
' Port 2222' \
' IdentitiesOnly yes' >"$config"
ssh -F "$config" -G demo | grep -E '^(hostname|user|port|identitiesonly) 'Правила применяются сверху вниз: для большинства параметров используется первое найденное значение. Поэтому узкие Host-блоки ставят до широкого Host *. Include и Match добавляют гибкость, но усложняют объяснение итоговой конфигурации; ssh -G остаётся главным способом проверки.
Local forwarding
Форма -L local_host:local_port:target_host:target_port заставляет SSH-клиент слушать локальный порт, а server-side соединение открывать к target.
ssh -N \
-L 127.0.0.1:15432:db.internal:5432 \
demoПосле установления соединения приложение подключается к 127.0.0.1:15432. Имя db.internal разрешается с точки зрения SSH-сервера. Bind на 127.0.0.1 ограничивает tunnel локальной машиной; 0.0.0.0 может открыть порт другим узлам и требует отдельного решения безопасности.
Remote и dynamic forwarding
- -R просит сервер слушать порт и пересылать соединения к стороне клиента; возможность зависит от sshd policy.
- -D создаёт локальный SOCKS proxy. Приложение должно быть явно настроено на него, включая желаемый способ DNS resolution.
- -N не запускает remote command и подходит для tunnel-only session; ExitOnForwardFailure=yes заставляет подключение упасть, если listener не создан.
Ошибка и диагностика
Симптом «SSH подключился, но tunnel не работает» разделите на этапы. Сначала добавьте ExitOnForwardFailure=yes и verbose, затем проверьте listener через ss -ltn. После этого выясните, может ли сам SSH-сервер разрешить target host и открыть target port. Успешная аутентификация не доказывает доступность последнего hop.
Практика
Создайте временный config с двумя Host aliases и общим Host *. Через ssh -G подтвердите итоговые user, hostname, port и identityfile. Затем письменно разберите маршрут local forward к внутренней БД: кто слушает локальный порт, где разрешается имя БД и на каком участке данные перестают идти внутри SSH.
Что важно запомнить
- ssh -G показывает итог после применения Host/Match и помогает находить скрытые настройки.
- -L, -R и -D задают разные точки listener и назначения; нарисуйте путь до запуска.
- Tunnel защищает SSH-участок и не отменяет аутентификацию приложения или сетевую policy.
Частые вопросы
Почему локальный порт уже занят?
Другой процесс слушает его либо остался старый tunnel. Найдите owner через ss/lsof и выберите точное действие, а не завершайте процессы по широкому имени.
Где разрешается target host в -L?
Обычно на удалённой стороне SSH-соединения, потому что именно sshd открывает конечное TCP-соединение.
Можно ли хранить пароль в SSH config?
Стандартный OpenSSH config не предназначен для паролей. Используйте public-key authentication и отдельное управление секретами, не внешние скрипты с паролем в argv.