Вопрос или проблема
У нас есть проблема с выполнением SSH-подключений через удаленную переадресацию порта.
Сценарий – корпоративная сеть, в которой сервер во внутренней сети (назовем его “источник”) должен войти через SSH на сервер в DMZ (“цель”). Поскольку сервер назначения в DMZ заблокирован для подключений из внутренней сети (и даже не может быть виден из внутренней сети), у нас есть промежуточный сервер в DMZ, через который мы проходим (“jumphost”). Мы делаем это, настроив удаленную переадресацию порта на промежуточном сервере.
Мы выполняем эту команду с сервера источника во внутренней сети на промежуточный сервер:
origin> ssh -R *:1234:target:22 myusername@jumphost
Это нужно для установления SSH-сеанса на промежуточном сервере, чтобы он начал слушать на порту 1234 (просто пример произвольного номера порта) и пересылать подключения на этот порт к целевому серверу на порт 22 (SSH).
Затем мы устанавливаем второй SSH-сеанс, все еще с сервера источника на промежуточный сервер, на порту 1234, который затем действительно подключается к целевому серверу на порту 22 – это наш ‘реальный’ SSH-сеанс, где мы можем выполнять нашу работу на целевом сервере:
origin> ssh jumphost -P 1234
Конфигурация
Промежуточный сервер настроен разрешать удаленную переадресацию порта со следующими настройками в sshd_config:
AllowTcpForwarding yes
GatewayPorts yes
Также в стене открыты порты между сервером источником и промежуточным сервером для порта 22 (для начального SSH-подключения для настройки удаленной переадресации порта) и порта 1234 (для последующего SSH-подключения на переадресуемый порт). Также есть стена между промежуточным сервером и целью, открытую на порту 22.
Результат
Когда мы устанавливаем второе подключение (то, которое идет через переадресуемый порт), соединение немедленно закрывается (“соединение закрыто с удаленного хоста”).
Запуск tcpdump на целевом сервере показывает отсутствие активности, т.е. кажется, что соединение блокируется.
Тем не менее, мы можем успешно установить обычный SSH-сеанс с промежуточного сервера на цель. Только когда вход идет через переадресуемый порт, соединение закрывается, хотя оба подключаются к цели на порту 22.
Более того, если мы сделаем переадресацию порта на сервер во внутренней сети (т.е. подключение от источника во внутренней сети к промежуточному серверу в DMZ и обратно к третьему серверу во внутренней сети), то SSH-сеанс устанавливается успешно.
Спекуляции и вопросы
Все это приводит меня к мысли, что какая-то настройка сетевой безопасности действует, которая предотвращает подключение через переадресуемый порт на промежуточном сервере к целевому серверу в DMZ. К сожалению, я недостаточно осведомлен, чтобы знать:
(1) Является ли SSH-соединение, идущее с сервера источника через переадресуемый порт на промежуточном сервере, ‘другим’ с точки зрения политики сетевой безопасности, что оно может технически блокироваться, и если да, то как? И что нужно сделать для снятия этого ограничения?
(2) Любые другие причины, по которым это соединение не допускается – конфигурация стен, конфигурация роутера, настройки SSH на источнике или промежуточном сервере, что-нибудь еще?
(3) Может ли оно не удаваться, потому что сервер источника не знает целевой сервер, и поэтому первая ssh-команда не работает как предполагалось? Другими словами, интерпретируется ли имя хоста, указанное в первой ssh-команде (“target”), на клиенте (источник) или на сервере, к которому мы подключаемся для создания туннеля (промежуточном сервере)?
Что меня больше всего озадачивает, так это то, что обычный SSH-сеанс может быть установлен с промежуточного сервера к цели, я бы подумал, что SSH-подключение, поступающее через переадресуемый порт, будет тем же самым, но почему-то это не так.
Любая помощь очень ценится.
Похоже, вам следует использовать локальную переадресацию порта вместо удаленной переадресации порта. Вы можете обратиться к следующему полезному сообщению в блоге Дирка Лосса:
Оно включает следующий иллюстративный диаграмму:
Для нам нужно знать, что оно описывает отношения между 4 различными ролями, участвующими в создании и использовании SSH-туннеля:
- ssh клиент (например,
ssh
– командная строка OpenSSH-клиента), используемый для установки туннеля; - ssh сервер (например,
sshd
– демон сервера OpenSSH), используемый для поддержания другого конца туннеля; - сервер приложений (например, еще один ssh сервер или http сервер);
- клиент приложения (например, еще один ssh клиент или веб-браузер), который хочет получить доступ к серверу приложений через туннель.
Также важно понимать, что два разных типа переадресации соответствуют двум разным случаям использования:
-
Локальная переадресация: когда клиент приложения подключается через ssh клиент
-
Удаленная переадресация: когда клиент приложения подключается через ssh сервер
Удаленная переадресация называется так потому, что она выполняется удаленно (на сервере ssh), а не локально (на клиенте ssh). Я также нахожу “удаленная переадресация = обратная переадресация” полезным мнемонизмом.
Таким образом, как видно, чтобы инициировать подключение от ssh
клиента на хосте origin
через sshd
сервер на промежуточном jumphost
к третьему хосту target
, вы должны использовать локальную переадресацию портов. Удаленная переадресация портов предназначена для случая, в котором начальная точка туннеля находится на хосте, работающем на сервере sshd
, а не на хосте, работающем на клиенте ssh
.
В руководстве по команде синтаксис локальной переадресации портов записан следующим образом:
ssh -L [bind_address:]port:host:hostport user@remote
Это можно написать более интуитивно, как следующее:
ssh -L [local_bind_address:]local_port:remote_host:remote_host_port user@proxy_host
Или, используя ваши обозначения:
ssh -L [origin_bind_address:]origin_port:target_host:target_host_port user@jump_host
Если мы изменим вашу команду для использования локальной переадресации портов, то мы получим следующее:
user@origin:~$ ssh -L *:1234:target:22 myusername@jumphost
Переадресация портов полезна и ответ от @igal корректен (используйте -L с локальной переадресацией портов). Однако в большинстве случаев проще просто указать промежуточный сервер и подключиться к защищенному серверу с помощью одной команды:
ssh -J [email protected] [email protected]
# ^Промежуточный сервер^ ^Конечная цель^
Также возможно иметь несколько промежуточных серверов последовательно:
ssh -J [email protected],[email protected] [email protected]
# ^Промежуточный сервер^ Второй промежуточный сервер^ ^Конечная цель^
Другой вариант, который более удобен для повторного использования, это настройка промежуточной станции в ~/.ssh/config:
# Промежуточный сервер. Доступен через стену:
Host jumphost
HostName jumphost.my.dom
# Конечный сервер, доступный через промежуточный сервер:
Host ProtectedServer
HostName protectedserver.my.dom
ProxyJump someuser@jumphost
После начальной настройки вы должны иметь возможность создать ssh/scp/sftp на защищенный сервер, используя:
ssh myuser@ProtectedServer
Множественные прыжки также возможны с подобным ~/.ssh/config:
# Первый промежуточный сервер. Доступен через стену:
Host Hop1
HostName jumphost.my.dom
# Второй промежуточный сервер. Доступен через первый промежуточный сервер:
Host Hop2
HostName hop2.my.dom
ProxyJump someuser@Hop1
# Конечный сервер, доступный через второй промежуточный сервер:
Host ProtectedServer
HostName protectedserver.my.dom
ProxyJump otheruser@Hop2
Если имена пользователей не различаются, их можно опустить из прокси-сервера:
# Первый промежуточный сервер. Доступен через стену:
Host Hop1
HostName jumphost.my.dom
# Второй промежуточный сервер. Доступен через первый промежуточный сервер:
Host Hop2
HostName hop2.my.dom
ProxyJump Hop1
# Конечный сервер, доступный через второй промежуточный сервер:
Host ProtectedServer
HostName protectedserver.my.dom
ProxyJump Hop2
.
Ответ или решение
Проблема, которую вы описали, связана с установкой SSH-соединения через удаленную переадресацию портов, и ситуация несколько осложняется взаимодействием внутри корпоративной сети, где необходимо подключаться к серверу в демилитаризованной зоне (DMZ) через промежуточный узел (jumphost). Давайте разберем эту задачу с точки зрения теории, примера и применения, и постараемся найти решение.
Теория
Переадресация портов SSH — это мощный инструмент, который позволяет перенаправлять порты через зашифрованные соединения, тем самым обходя ограничения и решая проблемы доступности. Существует два основных типа переадресации портов:
-
Локальная переадресация портов (Local Port Forwarding), когда клиент SSH открывает определённый локальный порт и перенаправляет его на конкретный удалённый адрес и порт на конечном узле через SSH-сервер.
-
Удаленная переадресация портов (Remote Port Forwarding), когда сервер SSH открывает определённый порт и перенаправляет его на указанный адрес и порт на стороне клиента SSH.
В вашем случае был изначально выбран второй вариант, когда при подключении к jumphost
сервера устанавливается удаленная переадресация. Однако, как показывает ваш опыт, это не считается оптимальным решением для данной топологии сети.
Пример
Из примера в задании ваше текущее подключение выполняется с использованием следующей команды:
origin> ssh -R *:1234:target:22 myusername@jumphost
Эта команда указывает SSH-серверу на jumphost
открыть порт 1234 и пересылать входящие на этот порт соединения на target:22
. Это может быть причиной проблемы, так как отслеживается не просто факт переадресации, но сам характер соединения, который может быть небезопасным при использовании удаленной переадресации.
Применение
Для успешного обхода возникшей проблемы рекомендуется использовать локальную переадресацию портов. Это позволяет обойти потенциальные ограничения на стороннем сервере относительно подключений через удаленные порты. Измените команду на следующую:
ssh -L 1234:target:22 myusername@jumphost
Теперь вы открываете локальный порт 1234 на origin
сервере и устанавливаете туннель через jumphost
к target
, что безопаснее и не вызовет недоразумений на стороне конечного сервера.
Также, стоит учесть использование ProxyJump
для упрощения цепочки SSH-подключений. Это уменьшает сложность и делает управление доступом более рациональным. Воспользуйтесь конфигурацией SSH:
Host jumphost
HostName jumphost.my.dom
Host ProtectedServer
HostName target.my.dom
ProxyJump myusername@jumphost
С этой конфигурацией, когда вы выполните ssh myuser@ProtectedServer
, соединение будет прозрачно установлено через jumphost
.
Возможные трудности и решения
-
Политики безопасности могут блокировать именно тип соединений, устанавливаемых через удаленные порты. Проанализируйте настройки брандмауэра и маршрутизаторов.
-
DNS-резолвинг: Проверьте, где именно определяется адрес
target
. Если это выполнение происходит на сторонеorigin
, а не наjumphost
, это может вызвать осложнения, если имяtarget
не резолвится корректно. -
SSH-конфигурации: Как на сервере
origin
, так и наjumphost
, чтобы разрешить корректное и беспрепятственное выполнение команд, стоит удостовериться, что все узлы настроены должным образом.
Таким образом, используя локальную переадресацию портов и увеличив эффективность конфигурации SSH путем использования ProxyJump
, вы сможете решить проблему с подключением и избежать "разрывов соединений" ("connection closed by remote host"). Данный подход улучшает управляемость и безопасность операций в IT инфраструктуре.