обратный SSH-туннель

У меня есть встроенное устройство, которое стоит в поле и подключено через USB-накопитель к Интернету. Чтобы иметь возможность получить к нему доступ, я устанавливаю обратный ssh-туннель на порту 19996 к моему домашнему ПК, чтобы получить к нему доступ.

Теперь я переустанавливаю этот туннель каждые 10 минут (с помощью cron), чтобы убедиться, что у меня практически непрерывный доступ, даже когда провайдер решит изменить мой IP-адрес.

Теперь я понял, что мой список процессов заполнен

"4383 root     ssh -R 19996:localhost:22 -f -N user@host"

и netstat также загружен соединениями. Как я могу гарантировать, что этого не произойдет? Мне нужен только один открытый туннель за раз, а не 100 из них.


person stdcerr    schedule 31.05.2012    source источник
comment
Burrow.io — отличный инструмент для этого, если вам нужен HTTP или HTTPS. Бесплатная учетная запись позволяет создать один туннель (HTTP), и все, что вам нужно сделать на своем устройстве, — это запустить команду curl. Он даже подтвердит, что соединение всегда установлено, устраняя необходимость в работе Cron.   -  person Paulo Arruda    schedule 10.12.2014


Ответы (5)


Я написал следующий сценарий оболочки, который, кажется, работает нормально!

#!/bin/sh
RETVAL=`netstat | grep 'S0106b0487afe2a57'| grep -c 'ssh ESTABLISHED'`
echo "${RETVAL} open tunnel(s)"
if [ "$RETVAL" -lt "1" ]
  then
        echo "starting reverse ssh tunnel"
        `ssh -R 19999:localhost:22 -f -N user@host`
        echo "done"
fi
person stdcerr    schedule 31.05.2012
comment
Я использовал RETVAL=netstat | grep '<hostname>:ssh' | grep -c 'ssh ESTABLISHED', и, похоже, он работает нормально. - person MitchBroadhead; 24.03.2015

вместо этого используйте autossh, который восстановит соединение, если оно будет отключено. попробуйте сначала найти это в репозитории вашего дистрибутива, а затем в сети, если вы не можете его найти.

person johnshen64    schedule 31.05.2012
comment
проблема в том, что мой дистрибутив был собран самостоятельно с помощью buildroot (с busybox). Мне нужно будет перекомпилировать весь ребенок .... я бы предпочел что-то еще, если смогу ... но хороший совет, спасибо! :) - person stdcerr; 31.05.2012

Я написал следующий скрипт, который cron запускается каждые 5 минут. Хотя я ожидаю, что это сработает, я все еще постоянно нахожу соединения, не позволяющие мне войти с удаленной стороны. Чтобы ответить на комментарий выше: похоже, он не исчезает из netstat. Я проверяю netstat, и он по-прежнему говорит «ssh ESTABLISHED» для соединения, и поэтому, когда мой скрипт запускается, я получаю результат «сокеты кажутся подключенными. Предполагая, что обратный туннель ssh работает нормально». Должен быть лучший способ проверить удаленную сторону и получить результат, который предполагает, что он работает?

#!/bin/bash

#$Id: ssh_reverse_tunnel.sh 14 2012-10-13 22:53:21Z root $

REMOTE_USER="user"
REMOTE_DOMAIN="domain"
SOCKETS_USED=`netstat -p ssh | grep 'ssh ESTABLISHED' | grep -c $(host $REMOTE_DOMAIN | awk {'print $NF'})`

establish_connecton() {
  echo "establishing reverse ssh tunnel connection..."
  ssh -R 12222:localhost:22 -R12223:localhost:5901 -f -N -T ${REMOTE_USER}@${REMOTE_DOMAIN} &
  echo "done."
  echo
  exit
}

if [ $(ps -ef | grep "ssh -R 12222" | grep -v grep | wc -l) == 0 ]; then
  echo "no reverse ssh tunnel connection exists."
  establish_connecton
fi

if [ "$SOCKETS_USED" -lt 1 ]; then
  echo "no reverse ssh tunnel sockets are connected. nuking stale pids and re-establishing connection"
  # check for stale pids and kill them if found.
  if [ $(ps -ef | grep "ssh -R 12222" | grep -v grep | wc -l) -gt 0 ]; then
    # stale pids exist, kill them...
    ps -ef | grep "ssh -R 12222" | grep -v grep | awk {'print $2'} | \
      while read PID; do
        echo "kill -9 $PID"
      done
  fi
  establish_connecton
else
  echo "sockets appear connected. assuming reverse ssh tunnel is running fine."
fi

Надеюсь, что кто-то найдет вышеизложенное полезным и может сообщить мне, где встроить дополнительные проверки.

person Martijn Brunott    schedule 14.10.2012

Просто убейте предыдущий процесс (по ID) после запуска нового. Вы можете получить идентификатор процесса с помощью команды ps.

person Robert    schedule 31.05.2012
comment
но если я убью существующий, текущий сеанс ssh будет прерван, верно? Не очень удобно, если меня высаживают каждые 10 минут... - person stdcerr; 31.05.2012
comment
Да, но технически есть еще одна проблема. Процесс не должен иметь возможность привязываться к одному и тому же локальному порту после того, как он уже запущен... поэтому только один должен работать до тех пор, пока он не будет завершен. Если вы запускаете эти команды подряд, одна из них должна генерировать ошибку и немедленно завершаться ... так что проблема многих процессов не выглядит так, как будто она должна возникнуть. Возможно, здесь происходит что-то еще. Попробуйте запустить их локально из этого окна и посмотрите, какой результат вы получите. - person Robert; 31.05.2012
comment
Что ж, на самом деле, я делаю то же самое со своего офисного ПК здесь (устанавливаю обратный туннель к моему домашнему ПК), и я получаю точно то же самое. Здесь, в офисе, я использую Kubuntu 12.04, так что дистрибутив с севера на вершине точно такой же ... :o Но при установке туннеля я получаю сообщение об ошибке Предупреждение: удаленная переадресация портов не удалась для порта прослушивания 19999, но я получаю это на моей маленькой встроенной покупке тоже... но она все еще добавляет процесс в список процессов... это просто неправильно... :( - person stdcerr; 31.05.2012
comment
Есть ли способ, которым вы можете проверить, что команда вообще не может привязаться к порту, и завершить зависший процесс в случае сбоя? Таким образом, процесс, который фактически удерживает порт открытым, останется открытым, и вы не потеряете связь. Что-то вроде этого: cyberciti.biz/faq /what-are-exit-statuses-of-ssh-command (выведите $?, а затем сделайте что-нибудь на основе кода возврата/статуса) - person Robert; 31.05.2012
comment
Тем временем я написал небольшой скрипт bash, который ищет определенный внешний адрес и «ssh ESTABLISHED», и если я получаю менее 1 соединения, я снова открываю его. Однако я не знаю, исчезнет ли он из netstat в случае динамического изменения IP... Я предполагаю, что по крайней мере изменится состояние, верно? - person stdcerr; 01.06.2012

Вы можете использовать сокет команды ssh, чтобы проверить, активно ли соединение. Это должно выглядеть так:

#!/bin/bash
if ! ssh -S mysocket -O check user@host ; then
    ssh -M -S mysocket -R 19996:localhost:22 -f -N user@host
fi

Затем вы можете закрыть это конкретное соединение, используя

ssh -S mysocket -O exit user@host

Также может быть полезно установить ServerAliveInterval на значение больше 0 с -o ServerAliveInterval=N. Так как это убьет ваш туннель, если соединение потеряно.

person Kristoffer    schedule 28.08.2013