Как Ваш компьютер может дать доступ к себе через туннель средствами ssh, autossh, autosshd
Здесь будет подробно рассказано, как дать кому-то доступ на ваш (мобильный) компьютер через туннель.
Туннель нужен, если у вашего компьютера нет постоянного адреса в Интернете. Это будет удобно, если вы ездите с ним и подключаетесь к Интернету по-разному.
(Иногда в подобных ситуациях люди используют проприетарный TeamViewer. Можно обойтись без него и иметь всё под своим контролем.)
Туннель (на самом деле, проброс одного порта) будет создаваться средствами ssh (openssh-client), autossh, autosshd. Это основная задача, описанию решения которой посвящён этот рассказ.
- кому-то в этом руководстве будет названо я для простоты.
- ssh в этом рассказе появится ещё и в другой роли: как средство входа для меня на ваш компьютер (с вашей стороны это обеспечивает openssh-server). Но эти две роли независимы друг от друга.
- Считается, что я имею больше опыта администрирования, поэтому указания для вас подробные, а для меня -- краткие, схематичные.
- Я должен буду вам сообщить, а вы подставить конкретные значения для моих данных: {{{MY_HOST}}}, {{{MY_HOST_SSHPORT}}}, {{{MY_PUBLIC_KEY}}}, {{{ME}}}. (Пример этого руководства с чьими-то конкретными данными: Участник:IvanZakharyaschev/Как дать мне доступ по ssh на Ваш (мобильный) компьютер.)
Туннель
Конфигурация туннеля
вы и я: ваше имя
- Договоримся об имени для вашего компьютера (по которому я буду вести у себя учёт). Обозначим его NAME; дальше вместо NAME будем подставлять это выбранное ваше имя.
вы: ваш ключ, которому я позволю делать туннель у меня
(делает обычный пользователь, не root)
- ssh-keygen -f ~/.ssh/id_for_tun_NAME -C 'tunnel wanted by NAME'
- Сообщите мне его открытую (т.н. "публичную") часть: cat ~/.ssh/id_for_tun_NAME.pub
с моей стороны: пользователь и выбор порта для туннеля
(делает администратор)
- useradd -m tun_NAME
- Позволяю входить по вашему ключу: cat >> ~tun_NAME/.ssh/authorized_keys (Заготовка файла ~tun_NAME/.ssh/authorized_keys уже будет после useradd.)
- TODO: Хорошо бы ещё запретить этому специальному пользователю (для обслуживания туннеля с моей стороны) выполнять любые команды из-под ssh, запускать командную оболочку, входить для иных целей, помимо туннеля.
- Выбираю у себя номер порта и сообщаю его вам. (Пусть он обозначается PORT_NAME.) Возможна конфигурация, когда порт выбирается автоматически (как в конфигурации ниже); тогда заранее договариваться о номере порта не надо.
вы: сохраняете конфигурацию
(делает тот же обычный пользователь, не root)
- Впишите в ~/.ssh/config конфигурацию (например, cat >> ~/.ssh/config -- дописывает в конец файла; потом Ctrl-D), о которой мы договорились:
Host {{{MY_NAME}}}_tunnel Hostname {{{MY_HOST}}} Port {{{MY_HOST_SSHPORT}}} User tun_NAME IdentityFile ~/.ssh/id_for_tun_NAME ForwardX11 no Compression yes CompressionLevel 9 RemoteForward 0 localhost:22
0 в качестве номера порта значит, что порт будет подобран автоматически (и напечатается ssh-клиентом -- см. команду ниже). В таком случае о номере порта можно заранее не договариваться.
(NAME нужно заменить на имя, выделенное для вас.)
(Вместо {{{MY_NAME}}}_tunnel можете придумать любое другое удобное для вас обозначение того, к кому вы пробрасываете туннель, и использовать его в командах ниже.)
Отредактировать ~/.ssh/config можно каким-нибудь текстовым редактором[1].
мы: виден ли выделенный для вас порт снаружи
Напомню себе и вам о ещё одном варианте строчки из этой конфигурации:
RemoteForward *:0 localhost:22
или (при ручном выборе номера порта)
RemoteForward *:PORT_NAME localhost:22
-- этот вариант нужен, если мы с вами договоримся, что назначенный для вас порт на моей стороне должен слушать на всех сетевых интерфейсах моего компьютера (и виден из моих локальных сетей). Тогда я смогу его легко пробросить и совсем наружу в интернет.
Я должен, чтобы слушание на всех интерфейсах работало, включить следующую опцию в /etc/openssh/sshd_config[2]:
GatewayPorts yes
Запуск туннеля
вы: инициируете туннель (каждый раз, когда нужно)
(делает тот же обычный пользователь, не root)
- ssh {{{MY_NAME}}}_tunnel
(там будет написан номер выделенного порта у меня, если мы решили конфигурировать туннель с автоматическим выделением порта на моей стороне. Можете мне его сообщить -- будет обозначаться PORT_NAME.)
На самом деле, в нашем деле "правильнее" было бы дать команду с опцией:
- ssh -N {{{MY_NAME}}}_tunnel
-- опция -N указывает ssh-клиенту, чтобы он только перенаправлял порты (т.е. создавал "туннель"), но не давал вам командную оболочку другого компьютера (моего, к которому вы подключаетесь). Я мог бы как раз и запретить специальному пользователю, под которым с моей стороны обслуживается туннель, работать с командной оболочкой (потому что исполнять команды на моём компьютере -- не наша цель).
С вашей стороны: вход для меня
(Ниже описаны самые обыкновенные действия для заведения пользователя для кого-то.)
пользователь для меня и ключ
(Вы можете узнать, какое имя пользователя я предпочитаю; здесь: {{{ME}}}.)
- useradd -G wheel -m {{{ME}}} (группа wheel нужна, если я должен быть администратором)
- Сообщайте мне пароль root, когда мне нужно администрировать, или добавьте меня в /etc/sudoers.[3]
- cat >> ~{{{ME}}}/.ssh/authorized_keys
{{{MY_PUBLIC_KEY}}}
ssh-сервер у вас работает?
- service sshd status
- Если нет, включите: service sshd start
- Если не стоит этот пакет, поставьте: apt-get install openssh-server
- Включите навсегда: chkconfig sshd on
- Посмотрите, будет ли он запускаться теперь всегда: chkconfig sshd[4]
Замечание: ssh-сервер у вас безопасен?
Вообще-то, если мы договоримся, что на порт, выделенный для Вас с моей стороны, надо пускать всех с Интернета, то стоит обеспокоиться тем, чтобы нельзя было Вас атаковать подбором паролей к Вашим пользователям, т.е. в настройках ssh-сервера запретить вход по паролю (останется вход по ключу). (TODO: написать конкретно!)
Сессия удалённой работы/администрирования
я: иду
(обычный пользователь)
- ssh 0 -l {{{ME}}} -p PORT_NAME -v
- su - или sudo su - (использую, соответственно, ваш пароль root-а или пароль пользователя {{{ME}}}, который вы установили -- их вы мне должны сообщить)
Автоматический туннель
Для большего удобства давайте позаботимся об автоматическом поддержании туннеля (средствами autossh и "обёрктой" вокруг него -- autosshd).
Преимущество команды autossh перед ssh в том, что такая команда будет перезапускать ssh с туннелем в случае всяких проблем. (Вам не нужно будет вручную заново давать эту команду.)
Преимущество же autosshd в том, что туннель будет запускаться системным сервисом, т.е. каждый раз при загрузке вашей системы, и вам не нужно будет об этом заботиться и давать самим команду. Это может также быть удобно, если я удалённо буду экспериментировать с перезагрузкой вашей системы. (Системный сервис, конечно, можно будет при желании отключить потом.)
Вот несколько всё более сложных усовершенствований:
вы: делайте autossh вместо ssh
(делает ваш обычный пользователь)
(Пакет autossh должен быть у вас установлен администратором, например, так: apt-get install autossh.)
Для запуска туннеля вместо
- ssh -N {{{MY_NAME}}}_tunnel
попробуйте:
- autossh -M 0 -N {{{MY_NAME}}}_tunnel
У autossh обязательна опция -M, которая даёт порт для мониторинга соединения, но документация /usr/share/doc/autossh-1.4c/README говорит, что современные ssh могут сами это делать (см. опции ServerAliveInterval
, ServerAliveInterval
). -M 0 как раз отключает этот мониторинг.
вы: пусть специальный пользователь _autossh занимается туннелем
- предварительно поставьте autosshd (версия пакета в репозитории пакетов Sisyphus могла уже измениться, конечно -- см. ссылки для скачивания):
apt-get install ftp://ftp.altlinux.org/pub/distributions/ALTLinux/Sisyphus/files/noarch/RPMS/autosshd-0.0.2-alt8.noarch.rpm
(Лучше поставьте из архива именно ту версию, которую я "одобрил", т.е. с которой я проверял эту инструкцию: apt-get install ftp://ftp.altlinux.org/pub/distributions/archive/sisyphus/date/2014/01/31/noarch/RPMS.classic/autosshd-0.0.2-alt8.noarch.rpm! Чтобы не перезаписать конкретную версию при обновлении, можно добавить строчку RPM::Hold { "^autosshd"; };
в конфигурацию APT, например, в отдельный новый файл /etc/apt/apt.conf.d/autosshd-tested.conf.)
Будет создан специальный пользователь _autossh с домашней директорией /var/lib/autosshd/.[5]
- перенесите настройки ssh-туннеля к этому специальному пользователю (YOU -- имя вашего обычного пользователя):
- cp -v ~YOU/.ssh/id_for_tun_NAME* ~_autossh/.ssh/
- cat ~YOU/.ssh/config >> ~_autossh/.ssh/config
- chown _autossh:_autossh -R ~_autossh/.ssh
Теперь вашу обычную команду инициации туннеля (ssh -N {{{MY_NAME}}}_tunnel) можно исполнять от имени нового специального пользователя; так вы будете в большей безопасности от атак из сети и от ошибок в ssh (ваши личные данные, с которыми вы работаете от имени своего обычного пользователя, а также вся система в случае, если вы можете переключаться в администратора -- если вы в группе wheel). Однако специальный пользователь _autossh настроен так, что под ним "зайти" в систему нельзя, поэтому просто самому проверить и запустить ssh -N {{{MY_NAME}}}_tunnel, сделав, скажем, su - _autossh, не получится. Можно рассматривать сделанные нами настройки ssh для пользователя _autossh как задел для работы autosshd (или как пример того, что эти настройки можно сделать под каким-то другим пользователем и от этого может быть польза).
вы: настройка autosshd
- настройки в файле /etc/autossh.d/{{{MY_NAME}}}_tunnel.conf (нужен какой-нибудь ненулевой AUTOSSH_PORT![6] и в опциях (auto)ssh должна быть -N!):
#usage: autossh [-V] [-M monitor_port[:echo_port]] [-f] [SSH_OPTIONS] # # -M specifies monitor port. May be overridden by environment # variable AUTOSSH_PORT. 0 turns monitoring loop off. # Alternatively, a port for an echo service on the remote # machine may be specified. (Normally port 7.) # -f run in background (autossh handles this, and does not pass it to ssh.) # -V print autossh version and exit. # #Environment variables are: # AUTOSSH_LOGLEVEL - level of log verbosity AUTOSSH_LOGLEVEL=4 # AUTOSSH_MESSAGE - message to append to echo string (max 64 bytes) # AUTOSSH_PIDFILE - write pid to this file # AUTOSSH_FIRST_POLL - time before first connection check (seconds) # # AUTOSSH_POLL - how often to check the connection (seconds) #AUTOSSH_POLL=600 # AUTOSSH_PORT - port to use for monitor connection #AUTOSSH_PORT=20000 # AUTOSSH_GATETIME - how long must an ssh session be established # before we decide it really was established # (in seconds). Default is 30 seconds; use of -f # flag sets this to 0. #AUTOSSH_GATETIME=30 # AUTOSSH_LOGFILE - file to log to (default is to use the syslog facility) #AUTOSSH_LOGFILE=$HOST.log # AUTOSSH_DEBUG - turn logging to maximum verbosity and log to stderr AUTOSSH_DEBUG=yes # AUTOSSH_PATH - path to ssh if not default #AUTOSSH_PATH=/usr/local/bin/ssh # AUTOSSH_MAXSTART - max times to restart (default is no limit) #AUTOSSH_MAXSTART=100 # AUTOSSH_MAXLIFETIME - set the maximum time to live (seconds) AUTOSSH_PIDFILE=/var/run/autosshd/{{{MY_NAME}}}_tunnel.pid AUTOSSH_LOCKFILE={{{MY_NAME}}}_tunnel.lck AUTOSSH_LOGFILE=/var/lib/autosshd/{{{MY_NAME}}}_tunnel.log HOST={{{MY_NAME}}}_tunnel USER=_autossh #AUTOSSH_PORT parameter must be unique for each connection and can not be 0 AUTOSSH_PORT=6666 MANUAL=no AUTOSSH_OPTIONS=" -M ${AUTOSSH_PORT} -f -N ${HOST}"
- для удобства в /var/lib/autosshd/.ssh/config предлагается назначить фиксированный порт на моей стороне -- PORT_NAME, о котором мы договорились (т.е. который я вам выделил и сообщил); вместо
RemoteForward 0 localhost:22
сделайте:
RemoteForward PORT_NAME localhost:22
например, что-нибудь вроде (Предупреждение: это совсем не тот порт, что AUTOSSH_PORT, который появлялся просто как часть внутренней кухни, несовершенной):
RemoteForward 6060 localhost:22
- проверка, запускается ли настроенный сервис -- как обычно:
- вы запускаете: service autosshd start
- вы смотрите о его состоянии: service autosshd status
- я проверяю: ssh 0 -p PORT_NAME -l {{{ME}}} (могу также вписать эти параметры в раздел вроде "Host NAME" в свой ~/.ssh/config)
- включаем сервис на каждый запуск системы -- как обычно:
- включен ли уже: chkconfig --list autosshd
- пусть будет включён: chkconfig autosshd on
- включен ли теперь: chkconfig --list autosshd
Примечания (о частных особенностях систем)
- ↑ Какой-нибудь текстовый редактор: например, medit в Simply Linux: medit ~/.ssh/config; или, например, emacs -- пакет с ним можно поставить, если он не стоит.
- ↑ man ssh_config:
If the bind_address is not specified, the default is to only bind to loopback addresses. If the bind_address is ‘
*
’ or an empty string, then the forwarding is requested to listen on all interfaces. Specifying a remote bind_address will only succeed if the server'sGatewayPorts
option is enabled (see sshd_config(5)). - ↑ На самом деле, например, в ALT Linux p7 пользователи из группы wheel и так уже могут пользоваться sudo. Но чтобы пользоваться sudo, нужно иметь свой пароль. Его можете установить вы: passwd {{{ME}}}; или дать это сделать мне, когда я войду и стану администратором через su -, узнав от вас ваш пароль root-а.
- ↑ Для систем со старым-добрым SysV init можно использовать и команду chkconfig --list sshd; а для новомодного systemd (например, в ALT Linux p7) эта команда даст информацию так:
# chkconfig sshd Внимание: Отправляется запрос 'systemctl is-enabled sshd.service'. disabled #
- ↑ После установки autosshd-0.0.2-alt3 видим:
# fgrep ssh /etc/passwd sshd:x:484:465::/var/empty:/dev/null _autossh:x:480:458:Autossh daemon:/var/lib/autosshd:/dev/null # rpm -qf /var/lib/autosshd --scripts preinstall scriptlet (through /bin/sh): # Add the "_autossh" user /usr/sbin/groupadd -r -f _autossh 2>/dev/null ||: /usr/sbin/useradd -r -g _autossh -c 'Autossh daemon' \ -s /dev/null -d /var/lib/autosshd _autossh 2>/dev/null ||: /usr/sbin/usermod -p `pwgen -s 24 1` _autossh postinstall scriptlet (through /bin/sh): if [ ! -f /var/lib/autosshd/.ssh/id_dsa ]; then mkdir -p /var/lib/autosshd/.ssh /usr/bin/ssh-keygen -t dsa -b 1024 -C "AutoSSH daemon" -N "" -q -f /var/lib/autosshd/.ssh/id_dsa echo "StrictHostKeyChecking no" > /var/lib/autosshd/.ssh/config cp /var/lib/autosshd/.ssh/id_dsa.pub /var/lib/autosshd/.ssh/authorized_keys fi chown -R _autossh:_autossh /var/lib/autosshd/ chown _autossh:_autossh /var/run/autossh.d/ /usr/sbin/post_service autosshd preuninstall scriptlet (through /bin/sh): /usr/sbin/preun_service autosshd postuninstall scriptlet (through /bin/sh): /usr/sbin/userdel -r _autossh 2>/dev/null ||: /usr/sbin/groupdel -r _autossh 2>/dev/null ||: #
- ↑ Хоть сам autossh может работать с современным ssh с -M 0, но autosshd устроен так, что он по номеру этого заданного порта выслеживает процесс autossh (и потом управляет им).