0,0
рейтинг
22 января 2010 в 17:50

Администрирование → 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, первую из опций можно и опустить. но, на всякий случай, пусть будет.
Александр Русских @oldengremlin
карма
86,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Администрирование

Комментарии (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
        З.Ы. У Вас опечатка в слове «Если» =)
        • +1
          1:1

          :D
  • 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.

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