SSH-туннели — пробрасываем порт

    Не всегда есть возможность, да и не всегда надо, строить полноценный туннель с интерфейсной парой адресов. Иногда нам нужно лишь «прокинуть» вполне определённые порты.

    Тут важно понимать, что туннель можно организовать как изнутри сети, к ресурсам которой вы хотите получить доступ, на внешний ssh-сервер. Также можно организовать туннель с хоста в Интернете на пограничный ssh-сервер сети, чтобы получить доступ к внутренним ресурсам.

    Итак. По-порядку.

    Строим туннель из сети в мир.

    $ ssh -f -N -R 2222:10.11.12.13:22 username@99.88.77.66


    теперь введя на хосте 99.88.77.66:

    $ ssh -p2222 localhost


    мы попадём на хост 10.11.12.13.

    Таким-же образом можно получить доступ к любому другому ресурсу, например:

    $ ssh -f -N -R 2080:10.11.12.14:80 username@99.88.77.66


    Введя на хосте 99.88.77.66:

    $ w3m -dump http://localhost:2080


    получим дамп web-ресурса на 10.11.12.14.

    Строим туннель из мира в сеть.

    $ ssh -f -N -L 4080:192.168.0.10:80 nameuser@88.77.66.55


    Аналогично, вводим на своём хосте:

    $ w3m -dump http://localhost:4080


    и получаем доступ к web-ресурсу узла 192.168.0.10, который находится за хостом 88.77.66.55.

    Поддерживаем туннели в поднятом состоянии
    Ни для кого не секрет, что связь иногда обрывается, туннели при этом будут отваливаться по таймауту.
    Чтобы не утруждать себя дополнительным монотонным вбиванием команды на поднятие туннеля и мониторингом этого процесса, автоматизируем его. Смело вводим:

    $ crontab -e

    и создаём расписание примерно следующего вида:

    TUNCMD1='ssh -f -N -R 2222:10.11.12.13:22 username@99.88.77.66'
    TUNCMD2='ssh -f -N -R 2080:10.11.12.14:80 username@99.88.77.66'
    
    */5 * * * * pgrep -f "$TUNCMD1" &>/dev/null || $TUNCMD1
    */5 * * * * pgrep -f "$TUNCMD2" &>/dev/null || $TUNCMD2


    Сохраняемся. Проверяем по

    $ crontab -l


    что расписание принято.

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

    $ man 1 ssh


    По практическому опыту — cron-задания на перезапуск абсолютно недостаточно.
    Разве что соединение абсолютно стабильно. В реальной жизни встречается в 0% случаев.
    Даже соединённые напрямую кабелем две сетевые карты легко могут потерять n-ное количество пакетов и tcp-соединение «упадёт».
    Клиент и сервер будут пребывать в святой уверенности, что всё в порядке, просто вторая сторона ничего не передаёт.
    Нужен keepalive.
    Примерно так:


    TCPKeepAlive yes
    ServerAliveInterval 300
    ServerAliveCountMax 3


    Интервал и счётчик — по вкусу.
    Добавлять их надо либо в /etc/ssh_config, либо в ~/.ssh/config, либо прямо в команде через опцию -o.
    В принципе, судя по man ssh_config, первую из опций можно и опустить. но, на всякий случай, пусть будет.
    Поделиться публикацией
    Комментарии 80
      –11
      пробасываем — Ыыы…
        +1
        опечаточка, как бы… ;)
        0
        Написано хорошо — без воды и мусора, что сейчас редкость :)
        Спасибо.
          0
          Ну, я бы сказал вообще по-спартански ;) Не помешало бы парочку схемок.
            +1
            Схемок чего?
            Адреса 192.168.0.10, 10.11.12.13 и 10.11.12.14 используемые в примерах входят в диапазон сетей RFC1918, т.е. являются приватными, а следовательно находятся за NAT'ом внутри локальной сети.
            Адреса 99.88.77.66 и 88.77.66.55, в свою очередь, в диапазон сетей определённых RFC1918 не входят, следовательно являются примерами хостов в сети Интернет.
            Хотя проброс портов конечно-же можно использовать и внутри одного широковещательного домена, просто для обеспечения безопасного соединения (например туннелирование незащищённого VNC внутри ssh-потока).
          0
          A autossh разве не решает задач поддерживания туннеля в поднятом состоянии?
            +1
            Возможно. Но, скажу честно, до этого момента я даже не подозревал о существовании такого пакета ;)
            $ aptitude search autossh
            p   autossh   - Automatically restart SSH sessions and tunnels

            Хотя, с другой стороны, проблема ведь не настолько сложно решается руками при помощи cron'а, да и кипалив нам в помощь :)
              +1
              Не сложно конечно, но одно дело три строчки, другое дело — одна ;)
                0
                Ну, походу это скорее вопрос религиозных убеждений :)
            +1
            Самое интересное началось, когда мне понадобилось соединить два компа из-за NAT'ов по VNC :)
            VNC-client host: ssh -L 4896:localhost:4897 user@server
            VNC-server host: ssh -R 4897:localhost:4899 user@server
            , VNC server настраиваем слушать на localhost:4899, VNC client — коннектиться на localhost:4896. Ну, и так далее, до упора можно накидывать узлы.
              +1
              Да. Спасибо.
              Об этом я как-то не сказал, так как подразумевал, что экспериментаторы не перевелись на земле русской :)
              Но это правда, вложений портов, так сказать, вглубь может быть много.
              Естественно, что при этом придётся учитывать то, что ip-пакеты будут расти в объёме и всё чаще и всё сильнее фрагментироваться, что может в итоге сказаться на производительности в целом.
            • НЛО прилетело и опубликовало эту надпись здесь
                0
                Для полноты картины не хватает упомянуть, что у Windows пользователей тоже есть возможность пробрасывать порты через ssh туннели с помощью Putty.
                  –2
                  В принципе, можно ей же и под линуксом делать туннели, бывает проще незнакомому человеку объяснить куда тыкнуть в гуишной программе, чем в консоли, по опыту :)
                    0
                    и когда это интересно Putty портировали под Linux? про вайн не надо :)
                    0
                    под линукс есть графическая утилита gstm
                    • НЛО прилетело и опубликовало эту надпись здесь
                        +2
                        Очень многие пользователи не могут правильно набрать продиктованный по буквам (причем ни английским, ни латинским) адрес e-mail или www. Но при этом вполне воспринимают на слух слова, которые видят на экране (или на бумаге, не суть) перед собой и в состоянии кликнуть по ним мышкой.

                        По мне так проще сказать по телефону «нажмите Пуск, а потом Блокнот», чем диктовать (причем после «Нажмите Пуск, а потом Выполнить») «Эн английская, как номер; о; тэ; е русская; пэ английская, как русская эр; а русская; дэ» и то не будучи увереным, что все правильно наберут да еще догадаются нажать Enter.
                        • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            Вообще я отвечал на конкретный коммент вне контекста статьи или PuTTY (а вообще под виндой предпочитаю Tunnelier для работы по ssh). Если был не прав — извините.
                            • НЛО прилетело и опубликовало эту надпись здесь
                            0
                            Фонетический алфавит вам в помощи когда GUI нету, или для e-mail или www. Если конечно пользователь поймет о чем вы… На практике в 8 из десяти случаев кнопочками получается лучше и быстрее.
                      0
                      Я думаю те, кому это нужно, и сами это знают :)
                      Могу еще добавить, что туннели удобно и просто делать с помощью putty
                        +5
                        Можно было бы и по-подробнее.
                        > $ ssh -f -N -R 2222:10.11.12.13:22 username@99.88.77.66
                        Это где нужно делать?
                        Что за хост 10.11.12.13? Что за магические числа: 22 и 2222?

                        > теперь введя на хосте 99.88.77.66:
                        >
                        > $ ssh -p2222 localhost
                        И зачем это? Не проще ли в данном случае устанавливать соединение со стороны 99.88.77.66? Если нет, объясните почему (подозреваю, что NAT или firewall)?

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

                        PS. Я-то понял суть, но мне это уже не ново, а вот о новичках можно было б и позаботиться.
                          –1
                          > а вот о новичках можно было б и позаботиться
                          Позволю не согласиться.
                          Пищи для размышлений тут более чем достаточно.
                          Это скорее послужит тем-же новичкам как сжатый и лаконичный справочник.
                          А если хотят изучить теорию — есть man'ы, есть google и т.д.
                          Если всю пищу новичкам класть готовой в рот — они никогда не научатся готовить. ;)
                          Хотя… Хотя это лишь моё имхо. Возможно я и не прав. :(
                            +6
                            Ну, мне кажется, тогда можно было бы написать ещё более лаконичную статью:
                            SSH-туннели — пробрасываем порт
                            man ssh

                            :)
                            +1
                            будучи не новичком — следовало догадаться, что 10.11.12.13 — приватный IP и напрямую с 99.88.77.66 не доступный
                              +2
                              Приватный IP мало о чём не говорит. Хост, с которого «пробрасывается порт», судя по всему, тоже в приватной сети. Не зная топологии сети, можно только догадываться о назначении конкретного IP в данной ситуации.
                              Всё что я хотел сказать: Коли написана и опубликована данная статья, значит автор хотел кому-то помочь (иначе, лежала бы эта статья на рабочем компе в текстовом файле :) ). Но новичкам таким скудным материалом он не поможет, а не новичкам этот материал не очень нужен. Следовательно, может быть, стоит пересмотреть подход к статье и дать более развёрнутые комментарии к командам и ключам, чтобы новичок «пришёл, увидел, победил» :)

                              Если кто-то воспринял мой комментарий, как «наезд», прошу прощения. Я не собирался этого делать!
                            +1
                            Почему-то не упоминается, что с помощью ssh можно также сделать и полноценный tun/tap туннель: ssh -w
                              0
                              а применение таких тунелей можно?
                                0
                                да самое любое
                                например, когда нужна связь не по tcp ;-)
                                например, легко поднимается nfs по udp в обход всем firewalls
                                  0
                                  Скажем так, создаётся полноценный интерфейс, для которого, в частности, могут быть применены правила фильтрации iptables, через него может быть смаршрутизирован трафик и прочее, прочее, прочее… Всё зависит только от фантазии :)
                                  +1
                                    0
                                    Вообще-то я имел ввиду эту статью, а не «в интернете нигде не упоминается».
                                  0
                                  Статья полезная. Но, в связи со стилем изложения суть досконально поймут только те, кому эта статья уже не нужна. Я, например, понял процентов 80% — не админ, юниксоид, не бородатый, поэтому какие-то вещи не сходу понятны.
                                    0
                                    добавлю, пожалуй в мемориз, пригодится.
                                    у кого можно заказать ликбез, по назначению интерфейсу нескольких адресов(без алиасов — eth1:1...), и последующей работой в iptables(он с алиасами не дружит))?
                                      0
                                      ip a a ip-address/mask brd broadcast dev iface
                                      например:
                                      ip a a 192.168.1.1/28 brd 192.168.1.15 dev eth0

                                      имхо, ifconfig — зло! :) ну, а если серьёзно, то ifconfig, равно как и route, просто морально устаревшие инструменты. iproute — это наше всё! ;)
                                        0
                                        таким образом, понимаю, можно сразу подсеть назначить интерфейсу?
                                      0
                                      ssh туннель — это половина магии. Вторая половина — сделать этот туннель невидимым.
                                      Я решал такую задачу: на работе есть сервер, например, cvs.office.com, нужен доступ, допустим, к CVS (порт 2401). Сервер, естественно, снаружи не виден, на него можно попасть только через gate.office.com, к которому есть ssh доступ. Необходимо обеспечить доступ к cvs.office.com:2401 с ноутбука, который может подключаться из офиса и из дома без необходимости что-либо перенастраивать на ноутбуке. Дома есть роутер (192.168.0.1) с линукс.

                                      Во-первых, делаем туннель с роутера с авторизацией по ключу:

                                      autossh -M 0 -f username@gate.office.com \
                                      -i /gate.ppk -N \
                                      -L 192.168.0.1:12401:cvs.office.com:2401

                                      Туннель поддерживается не через cron, а с помощью autossh, который уже упоминался в предыдущих комментариях. На мой взгляд, использование autossh более явно выражает намерения :)

                                      А теперь самое интересное — ноутбук, подключенный из дома, должен как и из офиса идти на cvs.office.com:2401
                                      Его запрос перехватит роутер и направит его в туннель:

                                      iptables -t nat -A PREROUTING -p tcp -d cvs.office.com --dport 2401 -j DNAT --to-destination 192.168.0.1:12401

                                      Такая прозрачность удобна, а в программах, которые не позволяют переназначить порт, бывает просто необходима. Надеюсь, идея кому-нибудь пригодится.
                                        0
                                        я бы на вашем месте vpn использовал, если есть возможность.
                                          +1
                                          Я бы на моем тоже использовал :) Месяцев восемь назад назад админы пообещали, что через полгода сделают vpn. Хорошо, что я не стал их дожидаться.
                                        +1
                                        А еще ssh умеет быть SOCKS proxy
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                              0
                                              Елси вам эта статья не показалась информативной, это не значит, что она всем показалась таковой.
                                              У вас кстати опечатка в слове «портов».
                                                0
                                                Я имел ввиду, что не каждая перепечатка информации из гугла имеет право зваться Статьей.
                                                Как правило, полноценная статья — самостоятельное исследование/работа.

                                                Что до опечатки — бывает)
                                                  +1
                                                  З.Ы. У Вас опечатка в слове «Если» =)
                                              0
                                              Автор, срочно изучите опцию SSH ProxyCommand. Можно найти поиском
                                              То, что Вы тут описали, достойно только человека, сидящего в линуксе меньше полугода и впервые увидевшего ман по SSH.
                                                +1
                                                Поддержу прямоходящих. Можно вылить тонны аргументов, но для новичков — статья малозначима, т.к. слишком много на «дожевать» оставлено. Для остальных — бесполезна, т.к. легко заменима 5мин man ssh.
                                                  –2
                                                  Блин, тема очень интересна, но из вашего объяснения ничерта не понял((

                                                  //Маленькое предложение — вместо IP адресов вставьте что-то вроде example.net example2.net и т.п., а то от циферок глаза разбегаются
                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                      0
                                                      SSH туннель — какое то неблагодарное занятие. Плюс для туннеля нужен акк на машине. Гораздо практичнее поднять openvpn.
                                                        0
                                                        cookbook )
                                                          0
                                                          >Тут важно понимать, что туннель можно организовать как изнутри сети, к ресурсам которой вы хотите получить доступ, на внешний ssh-сервер. Также можно организовать туннель с хоста в Интернете на пограничный ssh-сервер сети, чтобы получить доступ к внутренним ресурсам.

                                                          Раз пять перечитал, но не понял можно ли организовать тоннель, чтобы исходящий трафик с публичного хоста (есть root-доступ) пускай на локальный порт этого же хоста (а в идеале на произвольный порт произвольного публичного хоста) транслировался на порт удаленного приватного (за провайдерским NAT) хоста (root тоже есть). Как написать программу (а точнее две) на Си я представляю, но можно ли не изобретать велосипед и воспользоваться ssh?

                                                          А вообще согласен с многими комментаторами выше, что пост либо излишне лаконичен, либо излишне избыточен. Пользу принесёт, имхо, только тем, кто и не подозревал о существовании такой возможности — теперь они о ней узнают :)
                                                            0
                                                            Во-во, у меня так и получилось понять, что и как мне делать. Я понял, что каким-то макаром сделать кое-что можно, но как — ни фига не понял.
                                                            Если конкретно мне надо следующее: с моего компа, который ходит в инет через роутер (который имеет внешний IP), получить доступ до компа тёщи, который за натом. Нат провайдеровский, т.е. на нём ничего пробросить не получится. У мебя на роутере порт проброшен, т.е. снаружи на мой комп зайти можно. Задача: зайти на комп тёщи. Реально такое? Это как раз то, что описано в топике или нет? :)
                                                              +1
                                                              root@комп_тёщи # ssh -f -n -R 2222:127.0.0.1:22 адрес_твоего_компа

                                                              root@твой_комп # ssh -p 2222 127.0.0.1
                                                              Password:
                                                              root@комп_тёщи #
                                                                0
                                                                Класс! Спасибо.
                                                                  0
                                                                  При такой схеме получается, что тещин комп как бы слушает 2222 порт на моем компе, но слушает его чисто средствами ssh, я правильно понял? А можно как нибудь заставить тещин комп слушать произвольный (например 80) по произвольному протоколу (например http)?
                                                                    0
                                                                    Т.е. если я правильно понял, на тёщином компе запущен веб-сервер, нужно научиться ходить на него со своего компа. Как-то так будет:

                                                                    root@комп_тёщи # ssh -f -n -R 8080:127.0.0.1:80 адрес_твоего_компа
                                                                    root@твой_комп # links httр://127.0.0.1:8080/index.html
                                                                    Profit!

                                                                    Для красоты 8080 можно заменить на 80, если таковой свободен у тебя на 127.0.0.1.
                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                              • НЛО прилетело и опубликовало эту надпись здесь
                                                                  0
                                                                  воспользоваться ключом -p
                                                                  пример:
                                                                  ssh -f -N -R 2222:10.11.12.13:22 username@99.88.77.66 -p %port_num%
                                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                                      0
                                                                      Посмотреть в браузере?
                                                                      Пробросить вместо/вместе с 22-м портом ещё и 80-й.
                                                                      ssh -f -N -R 8080:10.11.12.13:80 -p xxxx username@99.88.77.66
                                                                      теперь если на 99.88.77.66 в браузере ввести localhost:8080 то увидим ресурсы которые висят на 10.11.12.13 внутри сети. Значительный минус этого подхода если на 10.11.12.13 настроен в веб-сервере виртуалхост, ведь обращение к серверу идёт по ip, а не по мнемоническому имени.
                                                                      Может кто знает как это можно обойти?
                                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                                          0
                                                                          > нужно чтобы или localhost можно было задать как прокси в настройках броузера
                                                                          тогда нужно на 10.11.12.13 поднять какой-нибудь проксик и уже адресоваться на него через localhost

                                                                          > чтобы была доступна вся интрасеть доступная узлу 10.11.12.13
                                                                          ну а в этом случае просто поднять ssh layer 3, о чём можно почитать в соседнем топике.
                                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                                  0
                                                                  А через 2 линуховых сервака можно порт пробросить?

                                                                  т.е. у меня есть
                                                                  хост 1 — 192.168.0.1
                                                                  с него есть доступ по SSH до 192.168.1.100

                                                                  с 192.168.1.100 есть доступ по SSH до 192.168.2.200

                                                                  и только с 192.168.2.200 виден интернет.

                                                                  При этом 192.168.2.200 с хоста 192.168.0.1 не виден.

                                                                  (конечно если на 192.168.1.100 есть что-то большее чем SSH, то всё реализуется просто)
                                                                    0
                                                                    192.168.0.1: cat ~/.ssh/config:
                                                                    Host 192.168.2.200
                                                                    ProxyCommand ssh user100@192.168.1.100 ssh user200@192.168.2.200 nc localhost 22

                                                                    и далее, как описано в статье
                                                                    192.168.0.1: ssh -L :<remote_host>:<remote_port> user200@192.168.2.200

                                                                    Для кастомных username, паролей и ключей — см. man ssh_config
                                                                    0
                                                                    Помогите, пожалуйста, реализовать такую схему. Есть купленный сервер, к которому алиасами прописано несколько IP. Задача в том, чтобы с домашней машины посмотреть в сеть (мир), через один из алиасных IP.
                                                                      0
                                                                      это нужно VPN заюзать, думаю. например, OpenVPN
                                                                        0
                                                                        … либо, если можно использовать прокси, поставить на сервере прокси-сервера (http[s], socks), а до них организовать туннель, как описано в статье.

                                                                        P.S. Ещё хороший способ организации VPN без дополнительного софта — ppp over ssh.
                                                                        0
                                                                        а как на винде порт с одного на другой зарулить?
                                                                          0
                                                                          Не поделитесь, как пробросить сокет с удалённого сервера на локальный порт 3310? Пусть будет удалённый сокет /var/run/mysqld.sock
                                                                            0
                                                                            Подозреваю, что как-то так как описано в этой goo.gl/y4faFi статье «OpenSSH Unix Domain Socket Forwarding».
                                                                            0
                                                                            Есть еще обертки для Python`a для создания ssh туннелей.
                                                                            github.com/pahaz/sshtunnel — обертка над paramiko для создания туннелей.
                                                                            github.com/jmagnusson/bgtunnel — обертка над консольным ssh для создания тоннелей.
                                                                            github.com/paramiko/paramiko — нитвная имплементация ssh.

                                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                            Самое читаемое