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, первую из опций можно и опустить. но, на всякий случай, пусть будет.
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 80
    • –11
      пробасываем — Ыыы…
    • 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, через него может быть смаршрутизирован трафик и прочее, прочее, прочее… Всё зависит только от фантазии :)
                                • 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
                                                            ssh -f -N -R 2222:10.11.12.13:22 username@99.88.77.66

                                                            А если username@99.88.77.66 порт SSH отличный от 22, как указать правильно?
                                                            • 0
                                                              ssh -f -N -R 2222:10.11.12.13:22 -p xxxx username@99.88.77.66 — так работает… А как мне посмотреть в браузере intranet 10.11.12.13 сети?
                                                              • 0
                                                                воспользоваться ключом -p
                                                                пример:
                                                                ssh -f -N -R 2222:10.11.12.13:22 username@99.88.77.66 -p %port_num%
                                                                • 0
                                                                  Если внимательно прочесть, то я ответил на свой вопрос сам, спасибо, и задал другой. Есть идеи?
                                                                  • 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…
                                                                      • 0
                                                                        > нужно чтобы или localhost можно было задать как прокси в настройках броузера
                                                                        тогда нужно на 10.11.12.13 поднять какой-нибудь проксик и уже адресоваться на него через localhost

                                                                        > чтобы была доступна вся интрасеть доступная узлу 10.11.12.13
                                                                        ну а в этом случае просто поднять ssh layer 3, о чём можно почитать в соседнем топике.
                                                                        • 0
                                                                          Спасибо, тоже пришел к этому. Последний вариант подходит, но надо осторожней настраивать squid(acl), но это дело поправимое.
                                                              • 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.

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