как работает обратное туннелирование ssh?

<p>насколько я понимаю, брандмауэры (при условии настроек по умолчанию) запрещают весь входящий трафик, у которого нет предшествующего соответствующего исходящего трафика.</p><p>основываясь на <a href="http://www.vdomck.org/2005/11/reversing-ssh-connection.html">реверсирование ssh-соединения</a> и <a href="http://www.revsys.com/writings/quicktips/ssh-tunnel.html">ssh-туннелирование стало проще</a> , обратное ssh-туннелирование можно использовать, чтобы обойти надоедливые ограничения брандмауэра.</p><p>я хотел бы выполнить команды shell на удаленной машине. удаленная машина имеет собственный брандмауэр и находится за дополнительным брандмауэром (маршрутизатором). у него есть ip-адрес, например 192.168.1.126 (или что-то подобное). я не за брандмауэром, и я знаю ip-адрес удаленного компьютера, как видно из интернета (не адрес 192.168.1.126). кроме того, я могу попросить кого-нибудь сначала выполнить <code>ssh (something)</code> как root на удаленной машине.</p><p>может ли кто-нибудь объяснить мне, шаг за шагом, как работает обратное туннелирование ssh, чтобы обойти брандмауэры (брандмауэры локальных и удаленных машин и дополнительный брандмауэр между ними)?</p><p>какова роль переключателей (<code>-r</code>, <code>-f</code>, <code>-l</code>, <code>-n</code>)?</p>

<p>я люблю объяснять подобные вещи с помощью визуализации. :-)</p><p>думайте о своих соединениях ssh как о трубках. большие трубы. обычно через эти пробирки вы запускаете shell на удаленном компьютере. оболочка работает в виртуальном терминале (tty). но вы уже знаете эту часть.</p><p>думайте о своем туннеле как о трубе внутри трубы. у вас все еще есть большое ssh-соединение, но опция -l или -r позволяет вам установить внутри него меньшую трубку.</p><p>у каждой трубки есть начало и конец. большая трубка, ваше ssh-соединение, начиналась с вашего ssh-клиента и заканчивалась на ssh-сервере, к которому вы подключены. все меньшие трубки имеют одинаковые конечные точки, за исключением того, что роль "начала" или "конца" определяется тем, использовали ли вы <code>-l</code> или <code>-r</code> (соответственно) для их создания.</p><p>(вы не сказали, но я собираюсь предположить, что упомянутая вами "удаленная" машина, находящаяся за брандмауэром, может выходить в интернет с помощью трансляции сетевых адресов (nat). это очень важно, поэтому пожалуйста, исправьте это предположение, если оно неверно.)</p><p>когда вы создаете туннель, вы указываете адрес и порт, на который он будет отвечать, а также адрес и порт, на который он будет доставлен. параметр <code>-l</code> указывает туннелю ответить на локальной стороне туннеля (хост, на котором работает ваш клиент). параметр <code>-r</code> указывает туннелю ответить на удаленной стороне (ssh-сервер).</p><p><img src="https://i.stack.imgur.com/hbsem.png" alt="ssh tunnel directions"></p><p>итак ... чтобы иметь возможность ssh из интернета на машину за брандмауэром, вам нужна рассматриваемая машина, чтобы открыть ssh-соединение с внешним миром и включить <code>-r</code> туннель, точка входа которого это "удаленная" сторона его соединения.</p><p>из двух моделей, показанных выше, вам нужна модель справа.</p><p>от огненного стража:</p><pre><code>ssh -f -n -t -r22222:localhost:22 yourpublichost.example.com </code></pre><p>это говорит вашему клиенту установить туннель с точкой входа <code>-r</code>. все, что подключено к порту 22222 в дальнем конце туннеля, фактически достигнет "порта localhost 22", где "localhost" находится с точки зрения точки выхода туннеля (т. е. вашего ssh-клиента).</p><p>другие варианты:</p><ul> <li><code>-f</code> сообщает ssh самому фону после его аутентификации, поэтому вам не нужно сидеть и запускать что-то на удаленном сервере, чтобы туннель оставался живым.</li> <li><code>-n</code> говорит, что вы хотите ssh-соединение, но на самом деле вы не хотите запускать какие-либо удаленные команды. если все, что вы создаете, это туннель, то включение этой опции экономит ресурсы.</li> <li><code>-t</code> отключает псевдо-tty распределение, которое подходит, потому что вы не пытаетесь создать интерактивную оболочку.</li> </ul><p>будет проблема с паролем, если вы не настроили ключи dsa или rsa для входа без пароля.</p><p>обратите внимание, что настоятельно рекомендуется использовать одноразовую учетную запись (не свою учетную запись), которую вы настроили только для этого туннеля/клиента/сервера.</p><p>теперь в вашей командной консоли <strong> yourpublichost </strong> установите соединение с хостом, защищенным брандмауэром, через туннель:</p><pre><code>ssh -p 22222 username@localhost </code></pre><p>вы получите вызов ключа хоста, так как вы, вероятно, никогда не заходили на этот хост раньше. после этого вы получите пароль для учетной записи <code>username</code> (если вы не настроили ключи для входа без пароля).</p><p>если вы собираетесь получать доступ к этому хосту на регулярной основе, вы также можете упростить доступ, добавив несколько строк в ваш файл <code>~/.ssh/config</code>:</p><pre><code>host remotehostname user remoteusername hostname localhost port 22222 </code></pre><p>отрегулируйте <code>remotehostname</code> и <code>remoteusername</code> в соответствии. поле <code>remoteusername</code> должно совпадать с вашим именем пользователя на удаленном сервере, но <code>remotehostname</code> может быть любым именем хоста, которое вам подходит, оно не должно совпадать ни с чем разрешаемым.</p><p>смотрите также:</p><ul> <li> <a href="https://superuser.com/a/591963">предоставьте обратную конечную точку на <strong> нелокальном </strong> ip</a> </li> <li> <a href="https://stackoverflow.com/a/26470428/1072112">советы по использованию <code>controlmaster</code> для поддержания вашего туннеля</a> </li> </ul>

<h2>я нарисовал несколько эскизов</h2><p>машина, на которой набрана команда ssh tunnel, называется <strong>"ваш хост"</strong>.</p><p><img src="https://i.stack.imgur.com/a28n8.png" alt="ssh tunnel starting from local"></p><hr><p><img src="https://i.stack.imgur.com/4ik3b.png" alt="ssh tunnel starting from remote"></p><h2>введение</h2><ol> <li> <p>местный: <code>-l specifies that the given port on the local (client) host is to be forwarded to the given host and port on the remote side.</code></p> <p>\_<code>ssh -l sourceport:forwardtohost:onport connecttohost</code>\_ означает: подключиться с помощью ssh к <code>connecttohost</code> и перенаправить все попытки подключения на <strong>локально</strong> <code>sourceport</code> на порт <code>onport</code> на компьютере называется <code>forwardtohost</code>, доступ к которому можно получить с машины <code>connecttohost</code>.</p> </li> <li> <p>удаленный: <code>-r specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side.</code></p> <p>\_<code>ssh -r sourceport:forwardtohost:onport connecttohost</code>\_ означает: подключиться с помощью ssh к <code>connecttohost</code> и перенаправить все попытки подключения на <strong>удаленный</strong> <code>sourceport</code> на порт <code>onport</code> на компьютере называется <code>forwardtohost</code>, к которому можно обратиться с вашего локального компьютера.</p> </li> </ol><h2>дополнительные опции</h2><ul> <li>\_<code>-f</code>\_ сообщает ssh о фоновом режиме после аутентификации, поэтому вам не нужно сидеть и запускать что-то на удаленном сервере, чтобы туннель оставался живым.</li> <li>\_<code>-n</code>\_ говорит, что вы хотите ssh-соединение, но на самом деле вы не хотите запускать какие-либо удаленные команды. если все, что вы создаете, это туннель, то включение этой опции экономит ресурсы.</li> <li>\_<code>-t</code>\_ отключает псевдо-tty распределение, что подходит, потому что вы не пытаетесь создать интерактивную оболочку.</li> </ul><h2>ваш пример</h2><p>третье изображение представляет этот туннель. <strong>но</strong> синий компьютер под названием "ваш хост" представляет компьютер, на котором <em> кто-то </em> запускает ssh-туннель, в данном случае это машина с брандмауэром ,.</p><p>поэтому попросите <em> кого-то </em> запустить туннельное соединение ssh с вашей машиной. команда должна в основном выглядеть</p><pre>\_<code>ssh -r 12345:localhost:22 yourip </code>\_</pre><p>теперь туннель открыт. теперь вы можете подключиться через ssh к брандмауэру через туннель с помощью команды</p><pre>\_<code>ssh -p 12345 localhost </code>\_</pre><p>который подключится к вашему собственному <code>localhost</code> (вашему компьютеру) через порт \_<code>12345</code>\_, но порт \_<code>12345</code>\_ будет перенаправлен через туннель на порт 22 локального хоста компьютера с брандмауэром (то есть с брандмауэром) сам компьютер).</p>

<p>туннелирование ssh работает с использованием уже установленного ssh-соединения для отправки дополнительного трафика.</p><p>когда вы подключаетесь к удаленному серверу, у вас обычно есть только 1 канал для обычного взаимодействия с пользователем (или 3 канала, если вы считаете stdin/stdout/stderr отдельным). в любое время локальный или удаленный процесс ssh может открыть дополнительные каналы в существующем соединении. эти каналы затем отправляют/получают туннельный трафик. при отправке или получении любого трафика процесс ssh просто говорит: "этот трафик предназначен для канала foobar".</p><p>по сути, это работает так:</p><ol> <li>вы указываете ssh начать прослушивание через порт xxxx и что любой полученный трафик должен быть туннелирован, а затем установлен на y.y.y.y на порту zzzz.</li> <li>локальный ssh начинает прослушивать порт xxxx (обычно на <code>127.0.0.1</code>, но можно изменить).</li> <li>некоторое приложение открывает соединение с портом xxxx на локальной машине.</li> <li>локальный ssh открывает канал для удаленного ssh и говорит "любой трафик на этом канале идет на y.y.y.y: zzzz</li> <li>удаленный ssh подключается к y.y.y.y: zzzz и отправляет обратно "ок, канал открыт"</li> <li>теперь любой трафик, отправляемый по соединению с портом xxxx на локальном компьютере, передается по ssh через y.y.y.y: zzzz.</li> </ol><p>этот процесс одинаков для прямого и обратного туннелирования (просто поменяйте местами слова "локальный" и "удаленный" в вышеописанной процедуре). любая сторона может начать туннель. это даже не должно быть при первом запуске ssh. вы можете открывать туннели, пока ssh уже запущен (см. <code>escape characters</code>, конкретно <code>~c</code>).</p><p>на роль <code>-r</code>, <code>-f</code>, <code>-l</code>, а также <code>-n</code>, вам действительно нужно просто обратиться к странице справочника, она даст вам наилучшее объяснение. но я упомяну <code>-r</code> а также <code>-l</code>.<br> <code>-r</code> говорит удаленному ssh прослушивать соединения и что локальный ssh должен подключаться к реальному месту назначения. <code>-l</code> указывает локальному ssh прослушивать соединения, и этот удаленный ssh должен подключаться к реальному месту назначения.</p><p><em>обратите внимание, это очень грубое описание, но оно должно дать вам достаточно информации, чтобы знать, что происходит</em></p>

<p>это объясняется в руководстве по ssh, особенно различия между <code>-l</code> (местный) и <code>-r</code> (дистанционный пульт).</p><hr><h3><code>-l</code></h3><blockquote> <p><code>-l [bind\_address:]port:host:hostport</code></p> <p>указывает, что <strong> указанный порт на локальном (клиентском) хосте должен быть перенаправлен на данный хост и порт на удаленной стороне </strong>.</p> <p>это работает путем выделения сокета для прослушивания порта на локальной стороне, необязательно привязанного к указанному адресу bind\_address.</p> <p>всякий раз, когда устанавливается соединение с этим портом, <strong> соединение пересылается </strong> по безопасному каналу, и устанавливается соединение <strong> на <code>host</code> порт <code>hostport</code> с удаленного компьютера </strong>.</p> </blockquote><p>в следующем примере туннелируется сеанс irc с клиентского компьютера <code>127.0.0.1</code> (<code>localhost</code>) используя порт 1234 для удаленного сервера <code>server.example.com</code>:</p><pre><code>$ ssh -f -l 1234:localhost:6667 server.example.com sleep 10 </code></pre><p><sup>обратите внимание <code>-f</code> опция фонов ssh и удаленная команда <code>sleep 10</code> указывается, чтобы дать время для запуска службы, которая должна быть туннелирована.</sup></p><p>пример:</p><pre><code>ssh `-n` -l 22000:localhost:11000 remote.server.com </code></pre><ul> <li> <p><code>-n</code> после подключения просто повесьте туда (вы не получите приглашение в командной строке)</p> <blockquote> <p>не выполняйте удаленную команду.</p> </blockquote> </li> <li> <p><code>-l 22000</code> соединение будет осуществляться через порт 22000 вашей личной, <strong> [~ # ~] l [~ # ~] </strong> ocal machine</p> </li> <li><code>localhost:11000</code> - <code>remote.server.com</code> убедится, что на другом конце туннеля находится <code>localhost</code>, порт <code>11000</code></li> </ul><p> <a href="https://i.stack.imgur.com/zub1d.png"><img src="https://i.stack.imgur.com/zub1d.png" alt="ssh -n -l 22000:192.168.1.2:11000 remote.server.com"></a> </p><p><sup>источник: <a href="http://www.augustcouncil.com/~tgibson/tutorial/tunneling\_tutorial.html">иллюстрированное руководство, учебное пособие, инструкции по туннелированию ssh</a> .</sup></p><hr><h3><code>-r</code></h3><blockquote> <p><code>-r [bind\_address:]port:host:hostport</code></p> <p>указывает, что <strong> указанный порт на удаленном (серверном) хосте должен быть перенаправлен на данный хост и порт на локальной стороне </strong>.</p> <p>это работает путем выделения сокета для прослушивания <code>port</code> на удаленной стороне, и всякий раз, когда устанавливается соединение с этим портом, <strong> соединение перенаправляется </strong> по безопасному каналу и устанавливается соединение <strong> с <code>host</code> портом <code>hostport</code> с локальной машины </strong>.</p> </blockquote><p>пример:</p><pre><code>ssh -n -r 22000:localhost:11000 remote.server.com </code></pre><ul> <li> <p><code>-n</code> после подключения просто повесьте туда (вы не получите приглашение в командной строке)</p> <blockquote> <p>не выполняйте удаленную команду.</p> </blockquote> </li> <li> <p><code>-r</code> 22000 соединение будет происходить через порт 22000 компьютера (в данном случае удаленного) <strong> [~ # ~] r [~ # ~] </strong>. server.com)</p> </li> <li><code>localhost:11000</code> ваш персональный локальный компьютер позаботится о том, чтобы на другом конце туннеля находился <code>localhost</code>, порт <code>11000</code></li> </ul><p> <a href="https://i.stack.imgur.com/jdt9u.png"><img src="https://i.stack.imgur.com/jdt9u.png" alt="ssh -n -r 22000:localhost:11000 remote.server.com"></a> </p><p><sup>источник: <a href="http://www.augustcouncil.com/~tgibson/tutorial/tunneling\_tutorial.html">иллюстрированное руководство, учебное пособие, инструкции по туннелированию ssh</a> .</sup></p>