Итак, перед нами стоит задача – обеспечить доступ к своему серверу по SSH через окно браузера. Почему именно так? Да просто потому, что такой подход – самый универсальный. Существует огромное количество сетей, в которых закрыты все порты, которые администратор (или его начальство) посчитал нужным закрыть, в том числе и 22 – стандартный порт для протокола SSH. Но порты 80 (HTTP) и 443 (HTTPS) практически всегда открыты. По крайней мере, радикалов, перекрывающих и эти порты я пока не встречал – зачем тогда вообще предоставлять доступ в Интернет?

HTTP я настоятельно не рекомендую использовать, поскольку весь трафик (в том числе имя пользователя и пароль) в этом случае передаются в незашифрованном виде и доступны почти любому желающему. Хотя и такой доступ можно настроить, этот вариант не будем даже рассматривать. А жаждущие экстрима пусть лучше оставляют ключи от квартиры на гвоздике возле двери. Так, по крайней мере, для окружающих вреда меньше :).

С преамбулой заканчиваем, переходим к делу. Что нам понадобится для осуществления задуманного? Во-первых, сам сервер, без него никак. В этой заметке неявно подразумевается что на сервере установлен GNU/Linux. Во-вторых, необходимо, чтобы на нём был установлен SSH-сервер. В подавляющем большинстве дистрибутивов установлен по умолчанию. Ну и наконец, я представляю нашего сегодняшнего героя – замечательную программу shellinabox. Вообще говоря, есть ещё несколько программ с подобными возможностями (о них я упомяну позже), но shellinabox мне лично нравится намного больше, так как работает заметно быстрее аналогов и поддерживает UTF-8, что лично для меня важно. shellinabox абсолютно бесплатна в использовании и распространяется под лицензией GNU GPL v2.

Установка (по крайней мере, в debian-based дистрибутивах) очень проста:

wget http://shellinabox.googlecode.com/files/shellinabox_2.10-1_i386.deb
sudo dpkg -i shellinabox_2.10-1_i386.deb

Там же присутствуют готовые пакеты для x86-64 и ARM, а также исходники.

Установка из исходников также весьма тривиальна:

wget http://shellinabox.googlecode.com/files/shellinabox-2.10.tar.gz
tar xzf shellinabox-2.10.tar.gz
cd shellinabox-2.10
./configure
make
sudo make install

Проследите, чтобы shellinabox собрался с поддержкой ssl – пригодится ;). Более подробно про инсталляцию из исходных кодов можно посмотреть здесь (файл INSTALL из архива с исходниками). Хочу также заметить, что команда make uninstall отрабатывает корректно. Если у вас на сервере установлена FreeBSD, то shellinabox есть в портах (/usr/ports/www/shellinabox).

Если вы установили shellinabox из deb-пакета, то, скорее всего, сразу после установки он сразу запустился, а в /etc/init.d уже лежит скрипт вот с таким содержимым:

# Set some default values
SHELLINABOX_DATADIR="${SHELLINABOX_DATADIR:-/var/lib/shellinabox}"
SHELLINABOX_PORT="${SHELLINABOX_PORT:-4200}"
SHELLINABOX_USER="${SHELLINABOX_USER:-shellinabox}"
SHELLINABOX_GROUP="${SHELLINABOX_GROUP:-shellinabox}"

#
#       Function that starts the daemon/service.
#
d_start() {
 if [ -z "$SHELLINABOX_DAEMON_START" -o \
         "$SHELLINABOX_DAEMON_START" = "0" ]; then
   return 0
 fi

 eval start-stop-daemon --start --oknodo --pidfile "'$PIDFILE'" \
   --exec "'$DAEMON'" -- -q --background="'$PIDFILE'" \
   -c "'${SHELLINABOX_DATADIR}'" -p "'${SHELLINABOX_PORT}'" \
   -u "'${SHELLINABOX_USER}'" -g "'${SHELLINABOX_GROUP}'" \
   $(for i in $(ls /etc/shellinabox/options-enabled/*.css |
     sed -e \
      's/.*[/]\([0-9]*\)[-_+][^/:,;]*[.]css/\1/'|
     sort -u); do
     for j in /etc/shellinabox/options-enabled/"$i"*.css; do
      echo -n "$j" |
      sed -e 's/\(.*[/]\)\([0-9]*\)\([-_+]\)\([^/:,;]*\)[.]css/\4:\3\1\2\3\4.css,/
              s/:_/:-/'
     done |
     sed -e 's/,$/;/'
    done |
    sed -e 's/;$//
            //b
            s/.*/--user-css "\0"/')                         \
    "${SHELLINABOX_ARGS}"
}

#
#       Function that stops the daemon/service.
#
d_stop() {
  start-stop-daemon --stop --oknodo --pidfile "$PIDFILE"
  rm -f "$PIDFILE"
}

#
#       Function that stops the daemon/service.
#
d_stop() {
  start-stop-daemon --stop --oknodo --pidfile "$PIDFILE"
  rm -f "$PIDFILE"
}

#
#       Function that reloads the config file for the daemon/service.
#
d_reload() {
  # Only reload if there are no active sessions running
  [ -r "$PIDFILE" ] &&
    [ `ps o pid= --ppid "\`cat "$PIDFILE"\`\`ps o pid= --ppid \
                                                \\\`cat "$PIDFILE"\\\`|
                                             xargs -r -n 1 printf ',%s'\`" |
       wc -l` -gt 1 ] &&
    return 1

  d_stop
  d_start
}

#
#       Function that check the status of the daemon/service.
#
d_status() {
  [ -r "$PIDFILE" && kill -0 `cat "$PIDFILE"` ] &&
    echo "$DESC is running" || echo "$DESC is not running"
}

case "$1" in
    start)
        log_daemon_msg "Starting $DESC" "$NAME"
        d_start
        log_end_msg $?
        ;;
    stop)
        log_daemon_msg "Stopping $DESC" "$NAME"
        d_stop
        log_end_msg $?
        ;;
    reload)
        log_daemon_msg "Reloading services for $DESC" "$NAME"
        d_reload
        log_end_msg $?
        ;;
    restart|force-reload)
        log_daemon_msg "Restarting $DESC" "$NAME"
        d_stop
        d_start
        log_end_msg $?
        ;;
    status)
        d_status
    ;;
    *)
        echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload|reload}" >&2
        exit 1
        ;;
esac

exit 0

Если после установки процесс shellinaboxd не запущен (проверяем ps -ef | grep shellinaboxd), то запускаем его /etc/init.d/shellinaboxd start или даже просто shellinaboxd. Сразу после этого можно проверить, набрав а адресной строке браузера «https://my.server.domain:4200». Если всё сделано правильно, то вы увидите в окне браузера приглашение ввести имя пользователя. Примерно вот такое:

 

Если всё так, то нас уже можно поздравить :). Но всё же, это немного не то, чего нам хотелось бы – нам нужно использовать 443 порт, чтобы даже через самый «злобный» прокси-сервер мы могли бы получить доступ к терминалу нашего сервера. И вот тут появляются нюансы.

Вариант первый – в системе нет web-сервера или есть, но он не использует 443 порт. В этом случае в приветённом выше скрипте инициализации (или в том, который вы написали по аналогии с этим) меняем строку «SHELLINABOX_PORT=“;${SHELLINABOX_PORT:-4200}“;» на «SHELLINABOX_PORT=“;443”» (либо в файле /etc/defaults/shellinabox заменить «SHELLINABOX_PORT=4200» на «SHELLINABOX_PORT=4200») и перезапускаем демон shellinaboxd. Всё! Осталась только настроить опции запуска (в Debian – в файле /etc/defaults/shellinabox. Подробнее. см manual) и фаервол для разрешения/запрета подключения с различных адресов.

В том случае, если web-сервер используется, я рекомендую настроить прокси. Например, в случае использования apache это выглядить так:

Подключаем mod_proxy:

a2enmod mod_proxy
a2enmod mod_proxy_http

В конфигурационный файл apache в секцию (или аналогичную) добаляем такие строчки:

<Proxy *>
        Order Deny,allow
        Allow from all
</Proxy>
ProxyPass /shell/ http://127.0.0.1:4200/
ProxyPassReverse /shell/ http://127.0.0.1:4200/

И перезапускаем apache. При такой настройке shell будет доступен по адресу «https://my.server.domain/shell». Также полезно будет добавить такие опции запуска shellinaboxd, как –localhost-only (чтобы демон слушал только на loopback интерфейсе) и –disable-ssl (если демон работает только на локальном интерфейсе, то ни к чему повышать нагрузку на процессор дополнительным шифрованием, если оно и так выполняется апачем). Рекомендую ещё усилить безопасность, настроив apache таким образом, чтобы он запрашивал имя пользователя и пароль при обращении по этому URL.

Теперь, как я и обещал, отмечу альтернативные web-ssh клиенты. Из заслуживающих внимания я нашёл всего два. Это ajaxterm – написанный на python клиент, существенным (для меня) недостатком которого является то, что он не поддерживает юникод. И WebShell – основанный на ajaxterm клиент для iPhone, которым, тем не менее, можно пользоваться не только с iPhone, но и из любого браузера, поддерживающего JavaScript и AJAX.

Комментарии

comments powered by Disqus