Реализация локального и удаленного перенаправления портов SSH для туннелирования
Откройте безопасный сетевой доступ и обход брандмауэров с помощью перенаправления портов SSH. Это подробное руководство описывает практическую реализацию как локального (`-L`), так и удаленного (`-R`) туннелирования SSH. Изучите необходимый синтаксис, поймите ключевые различия между доступом к удаленным сервисам и предоставлением доступа к локальным сервисам, а также ознакомьтесь с наглядными примерами для таких задач, как защита подключений к базам данных или обмен средами разработки. Включает важные рекомендации по созданию постоянных, безопасных фоновых туннелей с использованием аутентификации по ключу.
Реализация локального и удаленного перенаправления портов SSH для туннелирования
Перенаправление портов SSH — это один из тех инструментов, о которых вы забываете, пока брандмауэр, частная подсеть или неудобная сеть вендора не блокируют простой путь. Тогда это становится самым быстрым и чистым решением. Вы можете использовать его для доступа к базе данных через шлюз, тестирования частной страницы администратора с ноутбука или предоставления доступа к локальному серверу разработки машине, которая не может напрямую подключиться к вашему ноутбуку.
Основная идея проста: SSH открывает порт прослушивания на одной стороне соединения и передает трафик через зашифрованную сессию SSH к месту назначения на другой стороне. Часть, которая сбивает с толку, — это направление. Локальное перенаправление с -L позволяет вашей машине получить доступ к чему-то рядом с SSH-сервером. Удаленное перенаправление с -R позволяет чему-то рядом с SSH-сервером получить доступ к чему-то рядом с вашей машиной.
Локальное перенаправление: доставка удаленного сервиса на ваш ноутбук
Используйте локальное перенаправление, когда сервис, который вам нужен, доступен с SSH-сервера, но не с вашей рабочей станции.
ssh -L 15432:db.internal.example:5432 [email protected]
После подключения ваш ноутбук слушает на 127.0.0.1:15432. Когда вы указываете psql, DBeaver или конфигурацию приложения на этот локальный порт, SSH отправляет трафик на bastion.example.com, и шлюз открывает соединение с db.internal.example:5432.
Читайте команду слева направо:
локальный порт на моей машине : хост назначения, видимый SSH-сервером : порт назначения
Это "видимый SSH-сервером" имеет значение. Если база данных называется db.internal.example только внутри частной сети, вашему ноутбуку не нужно разрешать это имя. Это делает шлюз. Если база данных слушает только на localhost на шлюзе, используйте это:
ssh -L 15432:127.0.0.1:5432 [email protected]
Локальное перенаправление обычно является более безопасным по умолчанию, потому что порт прослушивания находится на вашей рабочей станции. По умолчанию OpenSSH привязывает локальные перенаправленные порты к интерфейсу обратной связи, поэтому другие машины в вашей Wi-Fi или офисной сети не могут использовать туннель. Вы можете быть явным:
ssh -L 127.0.0.1:15432:db.internal.example:5432 [email protected]
Избегайте привязки к 0.0.0.0, если вы действительно не хотите делиться туннелем с другими хостами. Команда, подобная этой, делает ваш ноутбук прокси для частной базы данных для любого, кто может достичь порта 15432 на вашем ноутбуке:
ssh -L 0.0.0.0:15432:db.internal.example:5432 [email protected]
Это может быть полезно в лаборатории. Но редко то, что вам нужно на обычной рабочей станции.
Удаленное перенаправление: предоставление доступа к локальному сервису через сервер
Удаленное перенаправление меняет сторону прослушивания. Используйте его, когда сервис работает на вашей машине, но кому-то или чему-то рядом с SSH-сервером нужен к нему доступ.
ssh -R 18080:127.0.0.1:3000 [email protected]
Это заставляет public.example.com слушать на порту 18080. Соединения с этим портом передаются обратно через SSH на 127.0.0.1:3000 на вашем ноутбуке. Это удобно, когда вы тестируете приемник вебхуков, делитесь временным демо или отлаживаете обратный вызов от системы staging, которая не может напрямую вызвать ваш ноутбук.
Есть один распространенный сюрприз: удаленные перенаправленные порты обычно привязываются к обратной связи на SSH-сервере по умолчанию. Это означает, что curl http://127.0.0.1:18080 работает при запуске на public.example.com, но http://public.example.com:18080 из вашего браузера — нет.
Чтобы сделать удаленный перенаправленный порт доступным с других машин, SSH-сервер должен разрешить это. В /etc/ssh/sshd_config соответствующая настройка обычно:
GatewayPorts clientspecified
Затем вы можете запросить публичную привязку:
ssh -R 0.0.0.0:18080:127.0.0.1:3000 [email protected]
Используйте это осторожно. Вы публикуете локальный сервис через сервер. Поставьте перед ним брандмауэр, используйте высокий случайный порт и не выставляйте в интернет административные инструменты, базы данных разработки или неаутентифицированные приложения.
Поддерживайте туннели стабильными и надежными
Для долго работающего туннеля вам обычно не нужна оболочка на удаленном хосте:
ssh -N -L 15432:db.internal.example:5432 [email protected]
-N означает "не запускать удаленную команду". Добавьте keepalives, когда туннель пересекает NAT, VPN или облачные балансировщики нагрузки, которые сбрасывают неактивные TCP-сессии:
ssh -N \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-L 15432:db.internal.example:5432 \
[email protected]
Для необслуживаемого использования предпочтите systemd пользовательский сервис, autossh или ваш супервизор процессов вместо голой команды ssh -f. Фоновый запуск с -f работает, но делает неудачные запуски и устаревшие туннели менее заметными.
ssh -fN -L 15432:db.internal.example:5432 [email protected]
Если вы используете -fN, сначала протестируйте ту же команду без -f. Запросы пароля, запросы неизвестного ключа хоста и конфликты портов гораздо легче диагностировать в режиме переднего плана.
Контрольный список устранения неполадок
Когда туннель подключается, но приложение все равно не работает, проверяйте каждый шаг вместо того, чтобы гадать.
Сначала подтвердите, что локальный слушатель существует:
ss -ltnp | grep 15432
Затем протестируйте место назначения с SSH-сервера:
ssh [email protected] 'nc -vz db.internal.example 5432'
Если это не удается, проблема не в перенаправлении SSH. Шлюз не может достичь сервиса, имя не разрешается там, группа безопасности блокирует порт или сервис привязан к неправильному интерфейсу.
Если слушатель не запускается, локальный порт может уже использоваться:
lsof -iTCP:15432 -sTCP:LISTEN
Если удаленное перенаправление не удается с сообщением типа remote port forwarding failed, сервер может блокировать перенаправление TCP. Проверьте AllowTcpForwarding в sshd_config и проверьте, не занят ли запрошенный порт.
Полезные привычки безопасности
Используйте аутентификацию по ключу и ограничьте учетную запись, используемую для туннелей. Для выделенного пользователя туннеля вы можете комбинировать ограниченный доступ к оболочке, правила брандмауэра и параметры SSH, такие как PermitOpen или PermitListen, в зависимости от необходимого направления. Эти средства управления предотвращают превращение удобного туннеля в широкий сетевой доступ.
Называйте туннели в своих заметках или runbooks по назначению, а не только по команде. "Ноутбук 15432 к реплике отчетности продакшена через шлюз" легче проверить, чем загадочную строку ssh -L в истории оболочки.
Локальное перенаправление помогает вам получить доступ внутрь. Удаленное перенаправление позволяет другим получить доступ к вам. Как только это различие станет ясным, большинство проблем с туннелированием SSH сводятся к проверке того, какая сторона слушает, какая сторона разрешает место назначения и какой брандмауэр находится между ними.
Несколько реальных шаблонов, которые вы увидите
Распространенный производственный шаблон — туннель для обслуживания базы данных. У вас есть реплика отчетности в частной подсети, шлюз со строгим доступом SSH и инструмент аналитика на вашем ноутбуке. Локальное перенаправление подходит идеально:
ssh -N -L 127.0.0.1:15432:reporting-db.internal:5432 [email protected]
Приложение на вашем ноутбуке должно использовать 127.0.0.1, а не частное имя хоста базы данных. Если инструмент настаивает на проверке имени хоста SSL для хоста базы данных, вам может потребоваться подключиться с именем хоста базы данных и добавить локальную запись hosts или настроить клиент с правильным режимом SSL. Туннель только перемещает байты TCP; он не переписывает детали протокола базы данных.
Другой шаблон — временный приемник вебхуков:
ssh -N -R 127.0.0.1:19090:127.0.0.1:9090 [email protected]
В этой версии перенаправленный порт намеренно доступен только с самого шлюза. Затем вы можете настроить сервис staging на шлюзе для вызова http://127.0.0.1:19090/hook. Это безопаснее, чем публиковать порт на всю сеть.
Для короткого публичного демо используйте публичную привязку только после добавления правила брандмауэра:
ssh -N -R 0.0.0.0:19090:127.0.0.1:3000 [email protected]
Затем ограничьте шлюз:
sudo ufw allow from 203.0.113.40 to any port 19090 proto tcp
Без этого ограничения любой, кто может достичь шлюза, может попробовать перенаправленный сервис.
Что не решает туннелирование SSH
Перенаправление SSH не заменяет аутентификацию сервиса. Если база данных принимает локальные соединения без пароля, туннель может расширить эту слабую границу доверия дальше, чем предполагалось. Если локальное приложение разработки не имеет страницы входа, удаленное перенаправление может опубликовать его как есть.
Оно также не делает ненадежное место назначения надежным. Если шлюз не может разрешить внутреннее имя, если сервис не работает или если группа безопасности блокирует путь, туннель может успешно установиться, в то время как приложение не работает. Вот почему тестирование с SSH-сервера так полезно.
Наконец, туннели легко забыть. Устаревший туннель на общем шлюзе может оставить неожиданный порт открытым. Для всего долго работающего поместите команду в файл сервиса с четким именем, владельцем и политикой перезапуска. Для всего временного закрывайте его, когда работа завершена, и проверяйте, что слушатель исчез с помощью ss -ltnp.